Skip to main content

nblf_queue/core/
packed.rs

1use core::{
2    fmt::Debug,
3    marker::PhantomData,
4    num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32},
5    ptr::NonNull,
6};
7
8// TODO add safety comments in branch `allow_empty`
9
10/// This trait is used to store the value in a `Slot`.
11/// The slot may truncate the value to `MIN_BIT_WIDTH` bits.
12/// Types implementing `AsPackedValue` may be stored in slots with `MAX_CARGO_BIT_WIDTH` >= `MIN_BIT_WIDTH`. This will be checked at compile time.
13/// `MIN_BIT_WIDTH` cannot be larger than 64
14/// # SAFETY
15/// - both `decode` and `encode` must be atomic and non-blocking
16/// - `decode` must only be called on a value returned by `encode`
17/// - the encoded value must be reconstructable fully from the lower `MIN_BIT_WIDTH` bits
18/// - `is_rt_safe` must return false (or panic/not compile), if it is not safe to encode the payload in `MIN_BIT_WIDTH` under the runtime environment.
19pub unsafe trait AsPackedValue: Sized {
20    /// The minimal bit width from which this type may be reconstructed.
21    const MIN_BIT_WIDTH: usize;
22    /// Truncates `Self` to the lower `MIN_BIT_WIDTH` bits.
23    /// The caller is responsible for reconstructing this value usign `decode`
24    fn encode(zelf: Self) -> TruncatedU64<Self>;
25
26    /// Reconstructs `Self` from the lower `MIN_BIT_WIDTH` bits returned by `encode`.
27    /// # SAFETY
28    /// The caller must ensure that the passed value is a valid value returned by `encode`
29    unsafe fn decode(raw: TruncatedU64<Self>) -> Self;
30
31    /// Validates wether self is actually safe to pack into Self::MIN_BIT_WIDTH bits at runtime.
32    fn is_rt_safe() -> bool;
33}
34
35/// An U64, with the upper N bits set to 0.
36#[repr(transparent)]
37pub struct TruncatedU64<T> {
38    v: u64,
39    _phantom: PhantomData<T>,
40}
41
42impl<T> Clone for TruncatedU64<T> {
43    fn clone(&self) -> Self {
44        *self
45    }
46}
47
48impl<T> Copy for TruncatedU64<T> {}
49
50impl<T> Debug for TruncatedU64<T> {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        f.debug_struct("TruncatedU64")
53            .field("value", &self.v)
54            .finish()
55    }
56}
57
58impl<T> PartialEq for TruncatedU64<T> {
59    fn eq(&self, other: &Self) -> bool {
60        self.v.eq(&other.v)
61    }
62}
63
64impl<T> Eq for TruncatedU64<T> {}
65
66impl<T> TruncatedU64<T> {
67    /// Returns the raw u64 stored in this type
68    pub fn read(&self) -> u64 {
69        self.v
70    }
71}
72
73impl<T: AsPackedValue> TruncatedU64<T> {
74    /// Contructs a new `TruncatedU64` from an u64.
75    /// This method will zero the upper 64 - `T::MIN_BIT_WIDTH` bits.
76    pub fn new(mut value: u64) -> Self {
77        // TODO make this a const created mask
78        if T::MIN_BIT_WIDTH < 64 {
79            value = unpack!((value): T::MIN_BIT_WIDTH).1;
80        }
81        Self {
82            v: value,
83            _phantom: PhantomData,
84        }
85    }
86}
87
88macro_rules! atomic_encode_primitive {
89    ($type:ty) => {
90        // Safety:
91        // primitve numeric types with size <= WIDTH can be typecast safely
92        unsafe impl $crate::core::AsPackedValue for $type {
93            const MIN_BIT_WIDTH: usize = size_of::<$type>() * 8;
94
95            fn encode(zelf: Self) -> $crate::core::TruncatedU64<Self> {
96                $crate::core::TruncatedU64::new(zelf as u64)
97            }
98
99            unsafe fn decode(raw: $crate::core::TruncatedU64<Self>) -> Self {
100                (raw.read()) as Self
101            }
102
103            fn is_rt_safe() -> bool {
104                true
105            }
106        }
107    };
108}
109
110macro_rules! atomic_encode_non_zero_primitive {
111    ($type:ty, $raw:ty) => {
112        // Safety:
113        // primitve numeric types with size <= WIDTH can be typecast safely
114        unsafe impl $crate::core::AsPackedValue for $type {
115            const MIN_BIT_WIDTH: usize = size_of::<$type>() * 8;
116
117            fn encode(zelf: Self) -> $crate::core::TruncatedU64<Self> {
118                $crate::core::TruncatedU64::new(zelf.get() as u64)
119            }
120
121            unsafe fn decode(raw: $crate::core::TruncatedU64<Self>) -> Self {
122                Self::new(raw.read() as $raw)
123                    .expect("trying to construct a NonZero from a zero value")
124            }
125
126            fn is_rt_safe() -> bool {
127                true
128            }
129        }
130    };
131}
132
133atomic_encode_primitive!(u32);
134atomic_encode_primitive!(u16);
135atomic_encode_primitive!(u8);
136atomic_encode_primitive!(i32);
137atomic_encode_primitive!(i16);
138atomic_encode_primitive!(i8);
139
140atomic_encode_non_zero_primitive!(NonZeroU32, u32);
141atomic_encode_non_zero_primitive!(NonZeroU16, u16);
142atomic_encode_non_zero_primitive!(NonZeroU8, u8);
143atomic_encode_non_zero_primitive!(NonZeroI32, i32);
144atomic_encode_non_zero_primitive!(NonZeroI16, i16);
145atomic_encode_non_zero_primitive!(NonZeroI8, i8);
146
147// Safety:
148// () has no size and data
149unsafe impl AsPackedValue for () {
150    const MIN_BIT_WIDTH: usize = 0;
151
152    fn encode(_zelf: Self) -> TruncatedU64<Self> {
153        TruncatedU64::new(0)
154    }
155
156    // Safety:
157    // nothing to do
158    unsafe fn decode(_raw: TruncatedU64<Self>) -> Self {}
159
160    fn is_rt_safe() -> bool {
161        true
162    }
163}
164
165// TODO for targets with ptr width <=48 bits, we could also atomic_encode_primitive ptrs + usize
166
167/// Some x86_64 and aarch64 based hardware has support for level 5 pagetables / use more than 48 bits for pointers. These implementations are not safe on hardware using more that 48 bits for pointers.
168/// This invariant will be checked at runtime.
169#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
170mod bit64 {
171    use super::*;
172
173    fn assert_ptr_safety() {
174        let dummy = 42;
175        let raw = &dummy as *const i32;
176        let addr = raw as u64;
177        let top_16 = addr >> 48;
178        let bit_47 = (addr >> 47) & 1;
179
180        assert!(
181            (bit_47 == 0 && top_16 == 0) || (bit_47 == 1 && top_16 == 0xFFFF),
182            "Pointer {:p} exceeds 48-bit address space! AsPackedValue is unsafe here. Consider using a PooledQueue, a Tagged128 Slot or a custom ptrlike value encodeable in <= 48bits.",
183            raw
184        );
185    }
186
187    // Safety:
188    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
189    //
190    // WARNING: This implementation is unsound on systems using more than 48 bits
191    unsafe impl<T> AsPackedValue for *const T
192    where
193        T: Sized,
194    {
195        const MIN_BIT_WIDTH: usize = 48;
196
197        fn encode(zelf: Self) -> TruncatedU64<Self> {
198            TruncatedU64::new(zelf as u64)
199        }
200
201        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
202            crate::utils::sign_extend(raw.read()) as *const T
203        }
204
205        fn is_rt_safe() -> bool {
206            assert_ptr_safety();
207            true
208        }
209    }
210
211    // Safety:
212    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
213    //
214    // WARNING: This implementation is unsound on systems using more than 48 bits
215    unsafe impl<T> AsPackedValue for *mut T
216    where
217        T: Sized,
218    {
219        const MIN_BIT_WIDTH: usize = 48;
220
221        fn encode(zelf: Self) -> TruncatedU64<Self> {
222            TruncatedU64::new(zelf as u64)
223        }
224
225        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
226            crate::utils::sign_extend(raw.read()) as *mut T
227        }
228
229        fn is_rt_safe() -> bool {
230            assert_ptr_safety();
231            true
232        }
233    }
234
235    // Safety:
236    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
237    //
238    // WARNING: This implementation is unsound on systems using more than 48 bits
239    unsafe impl<T> AsPackedValue for NonNull<T>
240    where
241        T: Sized,
242    {
243        const MIN_BIT_WIDTH: usize = 48;
244
245        fn encode(zelf: Self) -> TruncatedU64<Self> {
246            TruncatedU64::new(zelf.as_ptr() as u64)
247        }
248
249        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
250            Self::new(crate::utils::sign_extend(raw.read()) as *mut T)
251                .expect("tried to recosntruct a NonNull from 0")
252        }
253
254        fn is_rt_safe() -> bool {
255            assert_ptr_safety();
256            true
257        }
258    }
259
260    // Safety:
261    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
262    //
263    // WARNING: This implementation is unsound on systems using more than 48 bits
264    unsafe impl<T> AsPackedValue for &'static T {
265        const MIN_BIT_WIDTH: usize = 48;
266
267        fn encode(zelf: Self) -> TruncatedU64<Self> {
268            TruncatedU64::new(zelf as *const T as u64)
269        }
270
271        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
272            // Safety:
273            // The caller must ensure that this is called on a value created by `encode` and the reference is still valid
274            unsafe { &*(crate::utils::sign_extend(raw.read()) as *const T) }
275        }
276
277        fn is_rt_safe() -> bool {
278            assert_ptr_safety();
279            true
280        }
281    }
282
283    // Safety:
284    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
285    //
286    // WARNING: This implementation is unsound on systems using more than 48 bits
287    unsafe impl<T> AsPackedValue for &'static mut T {
288        const MIN_BIT_WIDTH: usize = 48;
289
290        fn encode(zelf: Self) -> TruncatedU64<Self> {
291            TruncatedU64::new(zelf as *mut T as u64)
292        }
293
294        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
295            // Safety:
296            // The caller must ensure that this is called only once on a value created by `encode` and the reference is still valid
297            unsafe { &mut *(crate::utils::sign_extend(raw.read()) as *mut T) }
298        }
299
300        fn is_rt_safe() -> bool {
301            assert_ptr_safety();
302            true
303        }
304    }
305
306    #[cfg(any(feature = "alloc", test))]
307    mod alloc_ {
308        use alloc::{
309            boxed::Box,
310            rc::{self, Rc},
311            sync::{self, Arc},
312        };
313
314        use super::*;
315
316        // Safety:
317        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
318        //
319        // WARNING: This implementation is unsound on systems using more than 48 bits
320        unsafe impl<T> AsPackedValue for Box<T> {
321            const MIN_BIT_WIDTH: usize = 48;
322
323            fn encode(zelf: Self) -> TruncatedU64<Self> {
324                let raw = Box::into_raw(zelf);
325                TruncatedU64::new(raw as u64)
326            }
327
328            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
329                // Safety:
330                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
331                unsafe { Box::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
332            }
333
334            fn is_rt_safe() -> bool {
335                assert_ptr_safety();
336                true
337            }
338        }
339
340        // Safety:
341        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
342        //
343        // WARNING: This implementation is unsound on systems using more than 48 bits
344        unsafe impl<T> AsPackedValue for Rc<T> {
345            const MIN_BIT_WIDTH: usize = 48;
346
347            fn encode(zelf: Self) -> TruncatedU64<Self> {
348                let raw = Rc::into_raw(zelf);
349                TruncatedU64::new(raw as u64)
350            }
351
352            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
353                // Safety:
354                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
355                unsafe { Rc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
356            }
357
358            fn is_rt_safe() -> bool {
359                assert_ptr_safety();
360                true
361            }
362        }
363
364        // Safety:
365        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
366        //
367        // WARNING: This implementation is unsound on systems using more than 48 bits
368        unsafe impl<T> AsPackedValue for Arc<T> {
369            const MIN_BIT_WIDTH: usize = 48;
370
371            fn encode(zelf: Self) -> TruncatedU64<Self> {
372                let raw = Arc::into_raw(zelf);
373                TruncatedU64::new(raw as u64)
374            }
375
376            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
377                // Safety:
378                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
379                unsafe { Arc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
380            }
381
382            fn is_rt_safe() -> bool {
383                assert_ptr_safety();
384                true
385            }
386        }
387
388        // Safety:
389        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
390        //
391        // WARNING: This implementation is unsound on systems using more than 48 bits
392        unsafe impl<T> AsPackedValue for rc::Weak<T> {
393            const MIN_BIT_WIDTH: usize = 48;
394
395            fn encode(zelf: Self) -> TruncatedU64<Self> {
396                let raw = rc::Weak::into_raw(zelf);
397                TruncatedU64::new(raw as u64)
398            }
399
400            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
401                // Safety:
402                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
403                unsafe { rc::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
404            }
405
406            fn is_rt_safe() -> bool {
407                assert_ptr_safety();
408                true
409            }
410        }
411
412        // Safety:
413        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
414        //
415        // WARNING: This implementation is unsound on systems using more than 48 bits
416        unsafe impl<T> AsPackedValue for sync::Weak<T> {
417            const MIN_BIT_WIDTH: usize = 48;
418
419            fn encode(zelf: Self) -> TruncatedU64<Self> {
420                let raw = sync::Weak::into_raw(zelf);
421                TruncatedU64::new(raw as u64)
422            }
423
424            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
425                // Safety:
426                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
427                unsafe { sync::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
428            }
429
430            fn is_rt_safe() -> bool {
431                assert_ptr_safety();
432                true
433            }
434        }
435    }
436}
437
438/// Cannot guarantee that all 64 bit architectures use 48bit pointers.
439#[cfg(all(
440    not(target_arch = "x86_64"),
441    not(target_arch = "aarch64"),
442    target_pointer_width = "64"
443))]
444mod full_bit64 {
445    use super::*;
446
447    // Safety:
448    // casting *const T from and to u64 is safe
449    unsafe impl<T> AsPackedValue for *const T
450    where
451        T: Sized,
452    {
453        const MIN_BIT_WIDTH: usize = 64;
454
455        fn encode(zelf: Self) -> TruncatedU64<Self> {
456            TruncatedU64::new(zelf as u64)
457        }
458
459        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
460            raw.read() as *const T
461        }
462
463        fn is_rt_safe() -> bool {
464            // it is always safe to encode self in size of self bytes
465            true
466        }
467    }
468
469    // Safety:
470    // casting *const T from and to u64 is safe
471    unsafe impl<T> AsPackedValue for *mut T
472    where
473        T: Sized,
474    {
475        const MIN_BIT_WIDTH: usize = 64;
476
477        fn encode(zelf: Self) -> TruncatedU64<Self> {
478            TruncatedU64::new(zelf as u64)
479        }
480
481        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
482            raw.read() as *mut T
483        }
484
485        fn is_rt_safe() -> bool {
486            // it is always safe to encode self in size of self bytes
487            true
488        }
489    }
490
491    // Safety:
492    // casting *const T from and to u64 is safe
493    // casting from u64 to NonNull<T> is safe, if that u64 was obtained from a NonNull<T>
494    unsafe impl<T> AsPackedValue for NonNull<T>
495    where
496        T: Sized,
497    {
498        const MIN_BIT_WIDTH: usize = 64;
499
500        fn encode(zelf: Self) -> TruncatedU64<Self> {
501            TruncatedU64::new(zelf.as_ptr() as u64)
502        }
503
504        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
505            Self::new(raw.read() as *mut T).expect("tried to recosntruct a NonNull from 0")
506        }
507
508        fn is_rt_safe() -> bool {
509            // it is always safe to encode self in size of self bytes
510            true
511        }
512    }
513
514    // Safety:
515    // casting *const T from and to u64 is safe
516    unsafe impl<T> AsPackedValue for &'static T {
517        const MIN_BIT_WIDTH: usize = 64;
518
519        fn encode(zelf: Self) -> TruncatedU64<Self> {
520            TruncatedU64::new(zelf as *const T as u64)
521        }
522
523        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
524            // Safety:
525            // The caller must ensure that the value was returned by `encode` and the reference is still valid
526            unsafe { &*(raw.read() as *const T) }
527        }
528
529        fn is_rt_safe() -> bool {
530            // it is always safe to encode self in size of self bytes
531            true
532        }
533    }
534
535    // Safety:
536    // casting *const T from and to u64 is safe
537    unsafe impl<T> AsPackedValue for &'static mut T {
538        const MIN_BIT_WIDTH: usize = 64;
539
540        fn encode(zelf: Self) -> TruncatedU64<Self> {
541            TruncatedU64::new(zelf as *mut T as u64)
542        }
543
544        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
545            // Safety:
546            // The caller must ensure that this is called only once on a value returned by `encode` and the reference is still valid
547            unsafe { &mut *(raw.read() as *mut T) }
548        }
549
550        fn is_rt_safe() -> bool {
551            // it is always safe to encode self in size of self bytes
552            true
553        }
554    }
555
556    #[cfg(any(feature = "alloc", test))]
557    mod alloc_ {
558        use alloc::{
559            boxed::Box,
560            rc::{self, Rc},
561            sync::{self, Arc},
562        };
563
564        use super::*;
565
566        // Safety:
567        // casting *const T from and to u64 is safe
568        unsafe impl<T> AsPackedValue for Box<T> {
569            const MIN_BIT_WIDTH: usize = 64;
570
571            fn encode(zelf: Self) -> TruncatedU64<Self> {
572                TruncatedU64::new(Box::into_raw(zelf) as u64)
573            }
574
575            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
576                // Safety:
577                // The caller must ensure that this is called only once on a value returned by `encode` and the allocation is still valid
578                unsafe { Box::from_raw(raw.read() as *mut T) }
579            }
580
581            fn is_rt_safe() -> bool {
582                // it is always safe to encode self in size of self bytes
583                true
584            }
585        }
586
587        // Safety:
588        // casting *const T from and to u64 is safe
589        unsafe impl<T> AsPackedValue for Rc<T> {
590            const MIN_BIT_WIDTH: usize = 64;
591
592            fn encode(zelf: Self) -> TruncatedU64<Self> {
593                let raw = Rc::into_raw(zelf);
594                TruncatedU64::new(raw as u64)
595            }
596
597            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
598                // Safety:
599                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
600                unsafe { Rc::from_raw(raw.read() as *mut T) }
601            }
602
603            fn is_rt_safe() -> bool {
604                // it is always safe to encode self in size of self bytes
605                true
606            }
607        }
608
609        // Safety:
610        // casting *const T from and to u64 is safe
611        unsafe impl<T> AsPackedValue for Arc<T> {
612            const MIN_BIT_WIDTH: usize = 64;
613
614            fn encode(zelf: Self) -> TruncatedU64<Self> {
615                let raw = Arc::into_raw(zelf);
616                TruncatedU64::new(raw as u64)
617            }
618
619            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
620                // Safety:
621                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
622                unsafe { Arc::from_raw(raw.read() as *mut T) }
623            }
624
625            fn is_rt_safe() -> bool {
626                // it is always safe to encode self in size of self bytes
627                true
628            }
629        }
630
631        // Safety:
632        // casting *const T from and to u64 is safe
633        unsafe impl<T> AsPackedValue for rc::Weak<T> {
634            const MIN_BIT_WIDTH: usize = 64;
635
636            fn encode(zelf: Self) -> TruncatedU64<Self> {
637                let raw = rc::Weak::into_raw(zelf);
638                TruncatedU64::new(raw as u64)
639            }
640
641            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
642                // Safety:
643                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
644                unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
645            }
646
647            fn is_rt_safe() -> bool {
648                // it is always safe to encode self in size of self bytes
649                true
650            }
651        }
652
653        // Safety:
654        // casting *const T from and to u64 is safe
655        unsafe impl<T> AsPackedValue for sync::Weak<T> {
656            const MIN_BIT_WIDTH: usize = 64;
657
658            fn encode(zelf: Self) -> TruncatedU64<Self> {
659                let raw = sync::Weak::into_raw(zelf);
660                TruncatedU64::new(raw as u64)
661            }
662
663            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
664                // Safety:
665                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
666                unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
667            }
668
669            fn is_rt_safe() -> bool {
670                // it is always safe to encode self in size of self bytes
671                true
672            }
673        }
674    }
675}
676
677/// if the native ptr-size is <= 48 bits, it is always safe to pack a ptr into 48 or more bits
678#[cfg(not(target_pointer_width = "64"))]
679mod bit32 {
680    use core::num::NonZeroUsize;
681
682    use super::*;
683
684    // Safety:
685    // Casting from a ptr to a usize is safe
686    unsafe impl<T> AsPackedValue for *const T
687    where
688        T: Sized,
689    {
690        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
691
692        fn encode(zelf: Self) -> TruncatedU64<Self> {
693            TruncatedU64::new(zelf as u64)
694        }
695
696        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
697            raw.read() as *const T
698        }
699
700        fn is_rt_safe() -> bool {
701            // it is always safe to encode self in size of self bytes
702            true
703        }
704    }
705
706    // Safety:
707    // Casting from a ptr to a usize is safe
708    unsafe impl<T> AsPackedValue for *mut T
709    where
710        T: Sized,
711    {
712        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
713
714        fn encode(zelf: Self) -> TruncatedU64<Self> {
715            TruncatedU64::new(zelf as u64)
716        }
717
718        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
719            raw.read() as *mut T
720        }
721
722        fn is_rt_safe() -> bool {
723            // it is always safe to encode self in size of self bytes
724            true
725        }
726    }
727
728    // Safety:
729    // Casting from a ptr to a usize is safe
730    unsafe impl<T> AsPackedValue for NonNull<T>
731    where
732        T: Sized,
733    {
734        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
735
736        fn encode(zelf: Self) -> TruncatedU64<Self> {
737            TruncatedU64::new(zelf.as_ptr() as u64)
738        }
739
740        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
741            Self::new(raw.read() as *mut T)
742                .expect("Constructing a NonNull form a null ptr wich was not obtained from encode")
743        }
744
745        fn is_rt_safe() -> bool {
746            // it is always safe to encode self in size of self bytes
747            true
748        }
749    }
750
751    // Safety:
752    // Casting from a ptr to a usize is safe
753    unsafe impl<T> AsPackedValue for &'static T {
754        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
755
756        fn encode(zelf: Self) -> TruncatedU64<Self> {
757            TruncatedU64::new(zelf as *const T as u64)
758        }
759
760        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
761            // Safety:
762            // The caller must ensure that this is called only on a value returned by `encode` and the reference is still valid
763            unsafe { &*(raw.read() as *const T) }
764        }
765
766        fn is_rt_safe() -> bool {
767            // it is always safe to encode self in size of self bytes
768            true
769        }
770    }
771
772    // Safety:
773    // Casting from a ptr to a usize is safe
774    unsafe impl<T> AsPackedValue for &'static mut T {
775        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
776
777        fn encode(zelf: Self) -> TruncatedU64<Self> {
778            TruncatedU64::new(zelf as *mut T as u64)
779        }
780
781        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
782            // Safety:
783            // The caller must ensure that this is called only once on a value returned by `encode` and the reference is still valid
784            unsafe { &mut *(raw.read() as *mut T) }
785        }
786
787        fn is_rt_safe() -> bool {
788            // it is always safe to encode self in size of self bytes
789            true
790        }
791    }
792
793    #[cfg(feature = "alloc")]
794    mod alloc_ {
795        use alloc::{
796            boxed::Box,
797            rc::{self, Rc},
798            sync::{self, Arc},
799        };
800
801        use super::*;
802
803        // Safety:
804        // Casting from a ptr to a usize is safe
805        unsafe impl<T> AsPackedValue for Box<T> {
806            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
807
808            fn encode(zelf: Self) -> TruncatedU64<Self> {
809                TruncatedU64::new(Box::into_raw(zelf) as u64)
810            }
811
812            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
813                // Safety:
814                // The caller must ensure that this is called only once on a value returned by `encode` and the allocation is still valid
815                unsafe { Box::from_raw(raw.read() as *mut T) }
816            }
817
818            fn is_rt_safe() -> bool {
819                // it is always safe to encode self in size of self bytes
820                true
821            }
822        }
823
824        // Safety:
825        // Casting from a ptr to a usize is safe
826        unsafe impl<T> AsPackedValue for Rc<T> {
827            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
828
829            fn encode(zelf: Self) -> TruncatedU64<Self> {
830                let raw = Rc::into_raw(zelf);
831                TruncatedU64::new(raw as u64)
832            }
833
834            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
835                // Safety:
836                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
837                unsafe { Rc::from_raw(raw.read() as *mut T) }
838            }
839
840            fn is_rt_safe() -> bool {
841                // it is always safe to encode self in size of self bytes
842                true
843            }
844        }
845
846        // Safety:
847        // Casting from a ptr to a usize is safe
848        unsafe impl<T> AsPackedValue for Arc<T> {
849            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
850
851            fn encode(zelf: Self) -> TruncatedU64<Self> {
852                let raw = Arc::into_raw(zelf);
853                TruncatedU64::new(raw as u64)
854            }
855
856            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
857                // Safety:
858                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
859                unsafe { Arc::from_raw(raw.read() as *mut T) }
860            }
861
862            fn is_rt_safe() -> bool {
863                // it is always safe to encode self in size of self bytes
864                true
865            }
866        }
867
868        // Safety:
869        // Casting from a ptr to a usize is safe
870        unsafe impl<T> AsPackedValue for rc::Weak<T> {
871            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
872
873            fn encode(zelf: Self) -> TruncatedU64<Self> {
874                let raw = rc::Weak::into_raw(zelf);
875                TruncatedU64::new(raw as u64)
876            }
877
878            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
879                // Safety:
880                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
881                unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
882            }
883
884            fn is_rt_safe() -> bool {
885                // it is always safe to encode self in size of self bytes
886                true
887            }
888        }
889
890        // Safety:
891        // Casting from a ptr to a usize is safe
892        unsafe impl<T> AsPackedValue for sync::Weak<T> {
893            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
894
895            fn encode(zelf: Self) -> TruncatedU64<Self> {
896                let raw = sync::Weak::into_raw(zelf);
897                TruncatedU64::new(raw as u64)
898            }
899
900            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
901                // Safety:
902                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
903                unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
904            }
905
906            fn is_rt_safe() -> bool {
907                // it is always safe to encode self in size of self bytes
908                true
909            }
910        }
911    }
912
913    atomic_encode_primitive!(usize);
914    atomic_encode_non_zero_primitive!(NonZeroUsize, usize);
915}
916
917#[cfg(test)]
918mod tests {
919    use super::*;
920
921    #[test]
922    fn truncated_trait_impls() {
923        struct NotClone;
924
925        let packed = TruncatedU64::<NotClone> {
926            v: 0,
927            _phantom: PhantomData,
928        };
929
930        #[allow(clippy::clone_on_copy)]
931        let cloned = packed.clone();
932
933        assert_eq!(packed, cloned);
934        assert_eq!(format!("{:?}", packed), format!("{:?}", cloned));
935    }
936
937    macro_rules! generate_test {
938        ($name:ident: $constructor:expr, $type:ty, $deref:expr, $drop:expr) => {
939            #[test]
940            fn $name() {
941                #[allow(dead_code)]
942                static VALUE: i32 = 42;
943                const WIDTH: usize = <$type as AsPackedValue>::MIN_BIT_WIDTH;
944
945                assert!(<$type>::is_rt_safe());
946
947                let ptr1: $type = $constructor;
948                let expected = $deref(&ptr1);
949
950                let mut encoded = AsPackedValue::encode(ptr1);
951
952                if WIDTH < 64 {
953                    let packed_encoded = pack!((!0, encoded.read()): WIDTH);
954                    encoded = TruncatedU64::new(packed_encoded);
955                }
956
957                // Safety:
958                // we just encoded this value
959                let decoded: $type = unsafe { AsPackedValue::decode(encoded) };
960
961                assert_eq!($deref(&decoded), expected);
962
963                #[allow(dropping_copy_types, dropping_references)]
964                $drop(decoded);
965            }
966        };
967        ($name:ident: $constructor:expr, $type:ty) => {
968            generate_test!($name: $constructor, $type, |x: &$type| x.clone(), drop);
969        };
970    }
971
972    generate_test!(raw: &VALUE as *const i32, *const i32);
973    generate_test!(raw_mut: &VALUE as *const i32 as *mut i32, *mut i32);
974    generate_test!(r#ref: &VALUE, &'static i32);
975    // we cannot compare two mutable borrows to the same data. Since the addrs is the same across *const T and &mut T, we simply deref to *const T.
976    generate_test!(ref_mut: Box::leak(Box::new(VALUE)), & 'static mut i32, |x: &&'static mut i32| *x as *const i32,
977        |x: &'static mut i32|
978            // Safety:
979            // drop is only called once on the decoded value
980            unsafe {Box::from_raw(x as *mut i32)}
981    );
982    generate_test!(nonnull: NonNull::new(&VALUE as *const i32 as *mut i32).unwrap(), NonNull<i32>);
983    generate_test!(primitive_u32: 42, u32);
984    generate_test!(primitive_nonzero_u32: NonZeroU32::new(42).unwrap(), NonZeroU32);
985    generate_test!(unit: (), ());
986
987    #[cfg(feature = "alloc")]
988    mod alloc_ {
989        use alloc::{
990            boxed::Box,
991            rc::{self, Rc},
992            sync::{self, Arc},
993        };
994
995        use super::*;
996
997        generate_test!(r#box: Box::new(VALUE), Box<i32>);
998        generate_test!(r#arc: Arc::new(VALUE), Arc<i32>);
999        generate_test!(r#rc: Rc::new(VALUE), Rc<i32>);
1000        generate_test!(weak_rc: Rc::downgrade(&Rc::new(VALUE)), rc::Weak<i32>, |x: &rc::Weak<i32>| x.as_ptr(), drop);
1001        generate_test!(weak_arc: Arc::downgrade(&Arc::new(VALUE)), sync::Weak<i32>, |x: &sync::Weak<i32>| x.as_ptr(), drop);
1002    }
1003}