1#![no_std]
78
79use core::cmp::Ordering;
80use core::convert::AsRef;
81use core::fmt::{Debug, Display, Formatter};
82use core::hash::{Hash, Hasher};
83use core::ops::{Deref, DerefMut};
84use core::ptr;
85
86#[repr(transparent)]
97#[derive(Copy, Clone, Default)]
98pub struct ByAddress<T>(pub T)
99where
100 T: ?Sized + Deref;
101
102impl<T> ByAddress<T>
103where
104 T: ?Sized + Deref,
105{
106 fn addr(&self) -> *const T::Target {
108 &*self.0
109 }
110
111 pub fn from_ref(r: &T) -> &Self {
113 unsafe {
115 &*(r as *const T as *const Self)
116 }
117 }
118}
119
120struct DebugAdapter<'a, T>(&'a T)
121where
122 T: ?Sized + Deref + Debug;
123
124impl<'a, T> Debug for DebugAdapter<'a, T>
125where
126 T: ?Sized + Deref + Debug,
127{
128 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
129 self.0.fmt(f)?;
130 f.write_str(" @ ")?;
131 (self.0.deref() as *const T::Target).fmt(f)?;
132 Ok(())
133 }
134}
135
136impl<T> Debug for ByAddress<T>
137where
138 T: ?Sized + Deref + Debug,
139{
140 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
141 f.debug_tuple("ByAddress")
142 .field(&DebugAdapter(&self.0))
143 .finish()
144 }
145}
146
147impl<T> Display for ByAddress<T>
148where
149 T: ?Sized + Deref + Display,
150{
151 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
152 self.0.fmt(f)
153 }
154}
155
156impl<T> PartialEq for ByAddress<T>
158where
159 T: ?Sized + Deref,
160{
161 fn eq(&self, other: &Self) -> bool {
162 ptr::eq(self.addr(), other.addr())
163 }
164}
165impl<T> Eq for ByAddress<T> where T: ?Sized + Deref {}
166
167impl<T> Ord for ByAddress<T>
169where
170 T: ?Sized + Deref,
171{
172 fn cmp(&self, other: &Self) -> Ordering {
173 self.addr().cmp(&other.addr())
174 }
175}
176
177impl<T> PartialOrd for ByAddress<T>
179where
180 T: ?Sized + Deref,
181{
182 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
183 Some(self.addr().cmp(&other.addr()))
184 }
185}
186
187impl<T> Hash for ByAddress<T>
189where
190 T: ?Sized + Deref,
191{
192 fn hash<H: Hasher>(&self, state: &mut H) {
193 self.addr().hash(state)
194 }
195}
196
197impl<T> Deref for ByAddress<T>
200where
201 T: ?Sized + Deref,
202{
203 type Target = T;
204
205 fn deref(&self) -> &Self::Target {
206 &self.0
207 }
208}
209
210impl<T> DerefMut for ByAddress<T>
211where
212 T: ?Sized + Deref,
213{
214 fn deref_mut(&mut self) -> &mut Self::Target {
215 &mut self.0
216 }
217}
218
219impl<T, U> AsRef<U> for ByAddress<T>
220where
221 T: ?Sized + Deref + AsRef<U>,
222{
223 fn as_ref(&self) -> &U {
224 self.0.as_ref()
225 }
226}
227
228impl<T, U> AsMut<U> for ByAddress<T>
229where
230 T: ?Sized + Deref + AsMut<U>,
231{
232 fn as_mut(&mut self) -> &mut U {
233 self.0.as_mut()
234 }
235}
236
237impl<T> From<T> for ByAddress<T>
238where
239 T: Deref,
240{
241 fn from(t: T) -> ByAddress<T> {
242 ByAddress(t)
243 }
244}
245
246#[repr(transparent)]
255#[derive(Copy, Clone, Default)]
256pub struct ByThinAddress<T>(pub T)
257where
258 T: ?Sized + Deref;
259
260impl<T> ByThinAddress<T>
261where
262 T: ?Sized + Deref,
263{
264 fn addr(&self) -> *const T::Target {
266 &*self.0
267 }
268
269 pub fn from_ref(r: &T) -> &Self {
271 unsafe {
273 &*(r as *const T as *const Self)
274 }
275 }
276}
277
278impl<T> Debug for ByThinAddress<T>
279where
280 T: ?Sized + Deref + Debug,
281{
282 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
283 f.debug_tuple("ByThinAddress")
284 .field(&DebugAdapter(&self.0))
285 .finish()
286 }
287}
288
289impl<T> Display for ByThinAddress<T>
290where
291 T: ?Sized + Deref + Display,
292{
293 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
294 self.0.fmt(f)
295 }
296}
297
298impl<T> PartialEq for ByThinAddress<T>
300where
301 T: ?Sized + Deref,
302{
303 fn eq(&self, other: &Self) -> bool {
304 core::ptr::eq(self.addr() as *const (), other.addr() as *const _)
305 }
306}
307impl<T> Eq for ByThinAddress<T> where T: ?Sized + Deref {}
308
309impl<T> Ord for ByThinAddress<T>
311where
312 T: ?Sized + Deref,
313{
314 fn cmp(&self, other: &Self) -> Ordering {
315 (self.addr() as *const ()).cmp(&(other.addr() as *const ()))
316 }
317}
318
319impl<T> PartialOrd for ByThinAddress<T>
321where
322 T: ?Sized + Deref,
323{
324 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
325 Some((self.addr() as *const ()).cmp(&(other.addr() as *const ())))
326 }
327}
328
329impl<T> Hash for ByThinAddress<T>
331where
332 T: ?Sized + Deref,
333{
334 fn hash<H: Hasher>(&self, state: &mut H) {
335 (self.addr() as *const ()).hash(state)
336 }
337}
338
339impl<T> Deref for ByThinAddress<T>
342where
343 T: ?Sized + Deref,
344{
345 type Target = T;
346
347 fn deref(&self) -> &Self::Target {
348 &self.0
349 }
350}
351
352impl<T> DerefMut for ByThinAddress<T>
353where
354 T: ?Sized + Deref,
355{
356 fn deref_mut(&mut self) -> &mut Self::Target {
357 &mut self.0
358 }
359}
360
361impl<T, U> AsRef<U> for ByThinAddress<T>
362where
363 T: ?Sized + Deref + AsRef<U>,
364{
365 fn as_ref(&self) -> &U {
366 self.0.as_ref()
367 }
368}
369
370#[cfg(test)]
371mod tests {
372 extern crate std;
373 use std::format;
374
375 use crate::{ByAddress, ByThinAddress};
376
377 trait A: std::fmt::Debug {
378 fn test(&self) {}
379 }
380 trait B: A {
381 fn test2(&self) {}
382 }
383
384 #[derive(Debug)]
385 struct Test {}
386 impl A for Test {}
387 impl B for Test {}
388
389 fn force_vtable<O: B>(v: &O) -> &dyn A {
390 v
391 }
392
393 #[test]
394 fn test_thin_ptr_fail() {
395 let t = Test {};
396 let tr1: &dyn A = &t;
397 let tr2: &dyn A = force_vtable(&t);
398
399 let a = ByAddress(tr1);
400 let b = ByAddress(tr2);
401
402 assert_ne!(a, b);
403 }
404
405 #[test]
406 fn test_thin_ptr_success() {
407 let t = Test {};
408 let tr1: &dyn A = &t;
409 let tr2: &dyn A = force_vtable(&t);
410
411 let a = ByThinAddress(tr1);
412 let b = ByThinAddress(tr2);
413
414 assert_eq!(a, b);
415 }
416
417 #[test]
418 fn test_debug() {
419 let x = &1;
420 let b = ByAddress(x);
421 let expected = format!("ByAddress(1 @ {:p})", x);
422 let actual = format!("{:?}", b);
423 assert_eq!(expected, actual);
424
425 let t = ByThinAddress(x);
426 let expected = format!("ByThinAddress(1 @ {:p})", x);
427 let actual = format!("{:?}", t);
428 assert_eq!(expected, actual);
429 }
430}