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 {raw: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        );
184    }
185
186    // Safety:
187    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
188    //
189    // WARNING: This implementation is unsound on systems using more than 48 bits
190    unsafe impl<T> AsPackedValue for *const T
191    where
192        T: Sized,
193    {
194        const MIN_BIT_WIDTH: usize = 48;
195
196        fn encode(zelf: Self) -> TruncatedU64<Self> {
197            TruncatedU64::new(zelf as u64)
198        }
199
200        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
201            crate::utils::sign_extend(raw.read()) as *const T
202        }
203
204        fn is_rt_safe() -> bool {
205            assert_ptr_safety();
206            true
207        }
208    }
209
210    // Safety:
211    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
212    //
213    // WARNING: This implementation is unsound on systems using more than 48 bits
214    unsafe impl<T> AsPackedValue for *mut T
215    where
216        T: Sized,
217    {
218        const MIN_BIT_WIDTH: usize = 48;
219
220        fn encode(zelf: Self) -> TruncatedU64<Self> {
221            TruncatedU64::new(zelf as u64)
222        }
223
224        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
225            crate::utils::sign_extend(raw.read()) as *mut T
226        }
227
228        fn is_rt_safe() -> bool {
229            assert_ptr_safety();
230            true
231        }
232    }
233
234    // Safety:
235    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
236    //
237    // WARNING: This implementation is unsound on systems using more than 48 bits
238    unsafe impl<T> AsPackedValue for NonNull<T>
239    where
240        T: Sized,
241    {
242        const MIN_BIT_WIDTH: usize = 48;
243
244        fn encode(zelf: Self) -> TruncatedU64<Self> {
245            TruncatedU64::new(zelf.as_ptr() as u64)
246        }
247
248        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
249            Self::new(crate::utils::sign_extend(raw.read()) as *mut T)
250                .expect("tried to recosntruct a NonNull from 0")
251        }
252
253        fn is_rt_safe() -> bool {
254            assert_ptr_safety();
255            true
256        }
257    }
258
259    // Safety:
260    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
261    //
262    // WARNING: This implementation is unsound on systems using more than 48 bits
263    unsafe impl<T> AsPackedValue for &'static T {
264        const MIN_BIT_WIDTH: usize = 48;
265
266        fn encode(zelf: Self) -> TruncatedU64<Self> {
267            TruncatedU64::new(zelf as *const T as u64)
268        }
269
270        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
271            // Safety:
272            // The caller must ensure that this is called on a value created by `encode` and the reference is still valid
273            unsafe { &*(crate::utils::sign_extend(raw.read()) as *const T) }
274        }
275
276        fn is_rt_safe() -> bool {
277            assert_ptr_safety();
278            true
279        }
280    }
281
282    // Safety:
283    // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
284    //
285    // WARNING: This implementation is unsound on systems using more than 48 bits
286    unsafe impl<T> AsPackedValue for &'static mut T {
287        const MIN_BIT_WIDTH: usize = 48;
288
289        fn encode(zelf: Self) -> TruncatedU64<Self> {
290            TruncatedU64::new(zelf as *mut T as u64)
291        }
292
293        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
294            // Safety:
295            // The caller must ensure that this is called only once on a value created by `encode` and the reference is still valid
296            unsafe { &mut *(crate::utils::sign_extend(raw.read()) as *mut T) }
297        }
298
299        fn is_rt_safe() -> bool {
300            assert_ptr_safety();
301            true
302        }
303    }
304
305    #[cfg(any(feature = "alloc", test))]
306    mod alloc_ {
307        use alloc::{
308            boxed::Box,
309            rc::{self, Rc},
310            sync::{self, Arc},
311        };
312
313        use super::*;
314
315        // Safety:
316        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
317        //
318        // WARNING: This implementation is unsound on systems using more than 48 bits
319        unsafe impl<T> AsPackedValue for Box<T> {
320            const MIN_BIT_WIDTH: usize = 48;
321
322            fn encode(zelf: Self) -> TruncatedU64<Self> {
323                let raw = Box::into_raw(zelf);
324                TruncatedU64::new(raw as u64)
325            }
326
327            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
328                // Safety:
329                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
330                unsafe { Box::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
331            }
332
333            fn is_rt_safe() -> bool {
334                assert_ptr_safety();
335                true
336            }
337        }
338
339        // Safety:
340        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
341        //
342        // WARNING: This implementation is unsound on systems using more than 48 bits
343        unsafe impl<T> AsPackedValue for Rc<T> {
344            const MIN_BIT_WIDTH: usize = 48;
345
346            fn encode(zelf: Self) -> TruncatedU64<Self> {
347                let raw = Rc::into_raw(zelf);
348                TruncatedU64::new(raw as u64)
349            }
350
351            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
352                // Safety:
353                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
354                unsafe { Rc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
355            }
356
357            fn is_rt_safe() -> bool {
358                assert_ptr_safety();
359                true
360            }
361        }
362
363        // Safety:
364        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
365        //
366        // WARNING: This implementation is unsound on systems using more than 48 bits
367        unsafe impl<T> AsPackedValue for Arc<T> {
368            const MIN_BIT_WIDTH: usize = 48;
369
370            fn encode(zelf: Self) -> TruncatedU64<Self> {
371                let raw = Arc::into_raw(zelf);
372                TruncatedU64::new(raw as u64)
373            }
374
375            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
376                // Safety:
377                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
378                unsafe { Arc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
379            }
380
381            fn is_rt_safe() -> bool {
382                assert_ptr_safety();
383                true
384            }
385        }
386
387        // Safety:
388        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
389        //
390        // WARNING: This implementation is unsound on systems using more than 48 bits
391        unsafe impl<T> AsPackedValue for rc::Weak<T> {
392            const MIN_BIT_WIDTH: usize = 48;
393
394            fn encode(zelf: Self) -> TruncatedU64<Self> {
395                let raw = rc::Weak::into_raw(zelf);
396                TruncatedU64::new(raw as u64)
397            }
398
399            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
400                // Safety:
401                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
402                unsafe { rc::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
403            }
404
405            fn is_rt_safe() -> bool {
406                assert_ptr_safety();
407                true
408            }
409        }
410
411        // Safety:
412        // This implementation assumes that pointers may be reconstructed from 48-bits using sign extenion.
413        //
414        // WARNING: This implementation is unsound on systems using more than 48 bits
415        unsafe impl<T> AsPackedValue for sync::Weak<T> {
416            const MIN_BIT_WIDTH: usize = 48;
417
418            fn encode(zelf: Self) -> TruncatedU64<Self> {
419                let raw = sync::Weak::into_raw(zelf);
420                TruncatedU64::new(raw as u64)
421            }
422
423            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
424                // Safety:
425                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
426                unsafe { sync::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
427            }
428
429            fn is_rt_safe() -> bool {
430                assert_ptr_safety();
431                true
432            }
433        }
434    }
435}
436
437/// Cannot guarantee that all 64 bit architectures use 48bit pointers.
438#[cfg(all(
439    not(target_arch = "x86_64"),
440    not(target_arch = "aarch64"),
441    target_pointer_width = "64"
442))]
443mod full_bit64 {
444    use super::*;
445
446    // Safety:
447    // casting *const T from and to u64 is safe
448    unsafe impl<T> AsPackedValue for *const T
449    where
450        T: Sized,
451    {
452        const MIN_BIT_WIDTH: usize = 64;
453
454        fn encode(zelf: Self) -> TruncatedU64<Self> {
455            TruncatedU64::new(zelf as u64)
456        }
457
458        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
459            raw.read() as *const T
460        }
461
462        fn is_rt_safe() -> bool {
463            // it is always safe to encode self in size of self bytes
464            true
465        }
466    }
467
468    // Safety:
469    // casting *const T from and to u64 is safe
470    unsafe impl<T> AsPackedValue for *mut T
471    where
472        T: Sized,
473    {
474        const MIN_BIT_WIDTH: usize = 64;
475
476        fn encode(zelf: Self) -> TruncatedU64<Self> {
477            TruncatedU64::new(zelf as u64)
478        }
479
480        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
481            raw.read() as *mut T
482        }
483
484        fn is_rt_safe() -> bool {
485            // it is always safe to encode self in size of self bytes
486            true
487        }
488    }
489
490    // Safety:
491    // casting *const T from and to u64 is safe
492    // casting from u64 to NonNull<T> is safe, if that u64 was obtained from a NonNull<T>
493    unsafe impl<T> AsPackedValue for NonNull<T>
494    where
495        T: Sized,
496    {
497        const MIN_BIT_WIDTH: usize = 64;
498
499        fn encode(zelf: Self) -> TruncatedU64<Self> {
500            TruncatedU64::new(zelf.as_ptr() as u64)
501        }
502
503        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
504            Self::new(raw.read() as *mut T).expect("tried to recosntruct a NonNull from 0")
505        }
506
507        fn is_rt_safe() -> bool {
508            // it is always safe to encode self in size of self bytes
509            true
510        }
511    }
512
513    // Safety:
514    // casting *const T from and to u64 is safe
515    unsafe impl<T> AsPackedValue for &'static T {
516        const MIN_BIT_WIDTH: usize = 64;
517
518        fn encode(zelf: Self) -> TruncatedU64<Self> {
519            TruncatedU64::new(zelf as *const T as u64)
520        }
521
522        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
523            // Safety:
524            // The caller must ensure that the value was returned by `encode` and the reference is still valid
525            unsafe { &*(raw.read() as *const T) }
526        }
527
528        fn is_rt_safe() -> bool {
529            // it is always safe to encode self in size of self bytes
530            true
531        }
532    }
533
534    // Safety:
535    // casting *const T from and to u64 is safe
536    unsafe impl<T> AsPackedValue for &'static mut T {
537        const MIN_BIT_WIDTH: usize = 64;
538
539        fn encode(zelf: Self) -> TruncatedU64<Self> {
540            TruncatedU64::new(zelf as *mut T as u64)
541        }
542
543        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
544            // Safety:
545            // The caller must ensure that this is called only once on a value returned by `encode` and the reference is still valid
546            unsafe { &mut *(raw.read() as *mut T) }
547        }
548
549        fn is_rt_safe() -> bool {
550            // it is always safe to encode self in size of self bytes
551            true
552        }
553    }
554
555    #[cfg(any(feature = "alloc", test))]
556    mod alloc_ {
557        use alloc::{
558            boxed::Box,
559            rc::{self, Rc},
560            sync::{self, Arc},
561        };
562
563        use super::*;
564
565        // Safety:
566        // casting *const T from and to u64 is safe
567        unsafe impl<T> AsPackedValue for Box<T> {
568            const MIN_BIT_WIDTH: usize = 64;
569
570            fn encode(zelf: Self) -> TruncatedU64<Self> {
571                TruncatedU64::new(Box::into_raw(zelf) as u64)
572            }
573
574            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
575                // Safety:
576                // The caller must ensure that this is called only once on a value returned by `encode` and the allocation is still valid
577                unsafe { Box::from_raw(raw.read() as *mut T) }
578            }
579
580            fn is_rt_safe() -> bool {
581                // it is always safe to encode self in size of self bytes
582                true
583            }
584        }
585
586        // Safety:
587        // casting *const T from and to u64 is safe
588        unsafe impl<T> AsPackedValue for Rc<T> {
589            const MIN_BIT_WIDTH: usize = 64;
590
591            fn encode(zelf: Self) -> TruncatedU64<Self> {
592                let raw = Rc::into_raw(zelf);
593                TruncatedU64::new(raw as u64)
594            }
595
596            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
597                // Safety:
598                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
599                unsafe { Rc::from_raw(raw.read() as *mut T) }
600            }
601
602            fn is_rt_safe() -> bool {
603                // it is always safe to encode self in size of self bytes
604                true
605            }
606        }
607
608        // Safety:
609        // casting *const T from and to u64 is safe
610        unsafe impl<T> AsPackedValue for Arc<T> {
611            const MIN_BIT_WIDTH: usize = 64;
612
613            fn encode(zelf: Self) -> TruncatedU64<Self> {
614                let raw = Arc::into_raw(zelf);
615                TruncatedU64::new(raw as u64)
616            }
617
618            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
619                // Safety:
620                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
621                unsafe { Arc::from_raw(raw.read() as *mut T) }
622            }
623
624            fn is_rt_safe() -> bool {
625                // it is always safe to encode self in size of self bytes
626                true
627            }
628        }
629
630        // Safety:
631        // casting *const T from and to u64 is safe
632        unsafe impl<T> AsPackedValue for rc::Weak<T> {
633            const MIN_BIT_WIDTH: usize = 64;
634
635            fn encode(zelf: Self) -> TruncatedU64<Self> {
636                let raw = rc::Weak::into_raw(zelf);
637                TruncatedU64::new(raw as u64)
638            }
639
640            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
641                // Safety:
642                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
643                unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
644            }
645
646            fn is_rt_safe() -> bool {
647                // it is always safe to encode self in size of self bytes
648                true
649            }
650        }
651
652        // Safety:
653        // casting *const T from and to u64 is safe
654        unsafe impl<T> AsPackedValue for sync::Weak<T> {
655            const MIN_BIT_WIDTH: usize = 64;
656
657            fn encode(zelf: Self) -> TruncatedU64<Self> {
658                let raw = sync::Weak::into_raw(zelf);
659                TruncatedU64::new(raw as u64)
660            }
661
662            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
663                // Safety:
664                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
665                unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
666            }
667
668            fn is_rt_safe() -> bool {
669                // it is always safe to encode self in size of self bytes
670                true
671            }
672        }
673    }
674}
675
676/// if the native ptr-size is <= 48 bits, it is always safe to pack a ptr into 48 or more bits
677#[cfg(not(target_pointer_width = "64"))]
678mod bit32 {
679    use core::num::NonZeroUsize;
680
681    use super::*;
682
683    // Safety:
684    // Casting from a ptr to a usize is safe
685    unsafe impl<T> AsPackedValue for *const T
686    where
687        T: Sized,
688    {
689        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
690
691        fn encode(zelf: Self) -> TruncatedU64<Self> {
692            TruncatedU64::new(zelf as u64)
693        }
694
695        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
696            raw.read() as *const T
697        }
698
699        fn is_rt_safe() -> bool {
700            // it is always safe to encode self in size of self bytes
701            true
702        }
703    }
704
705    // Safety:
706    // Casting from a ptr to a usize is safe
707    unsafe impl<T> AsPackedValue for *mut T
708    where
709        T: Sized,
710    {
711        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
712
713        fn encode(zelf: Self) -> TruncatedU64<Self> {
714            TruncatedU64::new(zelf as u64)
715        }
716
717        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
718            raw.read() as *mut T
719        }
720
721        fn is_rt_safe() -> bool {
722            // it is always safe to encode self in size of self bytes
723            true
724        }
725    }
726
727    // Safety:
728    // Casting from a ptr to a usize is safe
729    unsafe impl<T> AsPackedValue for NonNull<T>
730    where
731        T: Sized,
732    {
733        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
734
735        fn encode(zelf: Self) -> TruncatedU64<Self> {
736            TruncatedU64::new(zelf.as_ptr() as u64)
737        }
738
739        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
740            Self::new(raw.read() as *mut T)
741                .expect("Constructing a NonNull form a null ptr wich was not obtained from encode")
742        }
743
744        fn is_rt_safe() -> bool {
745            // it is always safe to encode self in size of self bytes
746            true
747        }
748    }
749
750    // Safety:
751    // Casting from a ptr to a usize is safe
752    unsafe impl<T> AsPackedValue for &'static T {
753        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
754
755        fn encode(zelf: Self) -> TruncatedU64<Self> {
756            TruncatedU64::new(zelf as *const T as u64)
757        }
758
759        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
760            // Safety:
761            // The caller must ensure that this is called only on a value returned by `encode` and the reference is still valid
762            unsafe { &*(raw.read() as *const T) }
763        }
764
765        fn is_rt_safe() -> bool {
766            // it is always safe to encode self in size of self bytes
767            true
768        }
769    }
770
771    // Safety:
772    // Casting from a ptr to a usize is safe
773    unsafe impl<T> AsPackedValue for &'static mut T {
774        const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
775
776        fn encode(zelf: Self) -> TruncatedU64<Self> {
777            TruncatedU64::new(zelf as *mut T as u64)
778        }
779
780        unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
781            // Safety:
782            // The caller must ensure that this is called only once on a value returned by `encode` and the reference is still valid
783            unsafe { &mut *(raw.read() as *mut T) }
784        }
785
786        fn is_rt_safe() -> bool {
787            // it is always safe to encode self in size of self bytes
788            true
789        }
790    }
791
792    #[cfg(feature = "alloc")]
793    mod alloc_ {
794        use alloc::{
795            boxed::Box,
796            rc::{self, Rc},
797            sync::{self, Arc},
798        };
799
800        use super::*;
801
802        // Safety:
803        // Casting from a ptr to a usize is safe
804        unsafe impl<T> AsPackedValue for Box<T> {
805            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
806
807            fn encode(zelf: Self) -> TruncatedU64<Self> {
808                TruncatedU64::new(Box::into_raw(zelf) as u64)
809            }
810
811            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
812                // Safety:
813                // The caller must ensure that this is called only once on a value returned by `encode` and the allocation is still valid
814                unsafe { Box::from_raw(raw.read() as *mut T) }
815            }
816
817            fn is_rt_safe() -> bool {
818                // it is always safe to encode self in size of self bytes
819                true
820            }
821        }
822
823        // Safety:
824        // Casting from a ptr to a usize is safe
825        unsafe impl<T> AsPackedValue for Rc<T> {
826            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
827
828            fn encode(zelf: Self) -> TruncatedU64<Self> {
829                let raw = Rc::into_raw(zelf);
830                TruncatedU64::new(raw as u64)
831            }
832
833            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
834                // Safety:
835                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
836                unsafe { Rc::from_raw(raw.read() as *mut T) }
837            }
838
839            fn is_rt_safe() -> bool {
840                // it is always safe to encode self in size of self bytes
841                true
842            }
843        }
844
845        // Safety:
846        // Casting from a ptr to a usize is safe
847        unsafe impl<T> AsPackedValue for Arc<T> {
848            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
849
850            fn encode(zelf: Self) -> TruncatedU64<Self> {
851                let raw = Arc::into_raw(zelf);
852                TruncatedU64::new(raw as u64)
853            }
854
855            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
856                // Safety:
857                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
858                unsafe { Arc::from_raw(raw.read() as *mut T) }
859            }
860
861            fn is_rt_safe() -> bool {
862                // it is always safe to encode self in size of self bytes
863                true
864            }
865        }
866
867        // Safety:
868        // Casting from a ptr to a usize is safe
869        unsafe impl<T> AsPackedValue for rc::Weak<T> {
870            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
871
872            fn encode(zelf: Self) -> TruncatedU64<Self> {
873                let raw = rc::Weak::into_raw(zelf);
874                TruncatedU64::new(raw as u64)
875            }
876
877            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
878                // Safety:
879                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
880                unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
881            }
882
883            fn is_rt_safe() -> bool {
884                // it is always safe to encode self in size of self bytes
885                true
886            }
887        }
888
889        // Safety:
890        // Casting from a ptr to a usize is safe
891        unsafe impl<T> AsPackedValue for sync::Weak<T> {
892            const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
893
894            fn encode(zelf: Self) -> TruncatedU64<Self> {
895                let raw = sync::Weak::into_raw(zelf);
896                TruncatedU64::new(raw as u64)
897            }
898
899            unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
900                // Safety:
901                // The caller must ensure that this is called only once on a value created by `encode` and the underlying allocation is still valid
902                unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
903            }
904
905            fn is_rt_safe() -> bool {
906                // it is always safe to encode self in size of self bytes
907                true
908            }
909        }
910    }
911
912    atomic_encode_primitive!(usize);
913    atomic_encode_non_zero_primitive!(NonZeroUsize, usize);
914}
915
916#[cfg(test)]
917mod tests {
918    use super::*;
919
920    #[test]
921    fn truncated_trait_impls() {
922        struct NotClone;
923
924        let packed = TruncatedU64::<NotClone> {
925            v: 0,
926            _phantom: PhantomData,
927        };
928
929        #[allow(clippy::clone_on_copy)]
930        let cloned = packed.clone();
931
932        assert_eq!(packed, cloned);
933        assert_eq!(format!("{packed:?}"), format!("{cloned:?}"));
934    }
935
936    macro_rules! generate_test {
937        ($name:ident: $constructor:expr, $type:ty, $deref:expr, $drop:expr) => {
938            #[test]
939            fn $name() {
940                #[allow(dead_code)]
941                static VALUE: i32 = 42;
942                const WIDTH: usize = <$type as AsPackedValue>::MIN_BIT_WIDTH;
943
944                assert!(<$type>::is_rt_safe());
945
946                let ptr1: $type = $constructor;
947                let expected = $deref(&ptr1);
948
949                let mut encoded = AsPackedValue::encode(ptr1);
950
951                if WIDTH < 64 {
952                    let packed_encoded = pack!((!0, encoded.read()): WIDTH);
953                    encoded = TruncatedU64::new(packed_encoded);
954                }
955
956                // Safety:
957                // we just encoded this value
958                let decoded: $type = unsafe { AsPackedValue::decode(encoded) };
959
960                assert_eq!($deref(&decoded), expected);
961
962                #[allow(dropping_copy_types, dropping_references)]
963                $drop(decoded);
964            }
965        };
966        ($name:ident: $constructor:expr, $type:ty) => {
967            generate_test!($name: $constructor, $type, |x: &$type| x.clone(), drop);
968        };
969    }
970
971    generate_test!(raw: &VALUE as *const i32, *const i32);
972    generate_test!(raw_mut: &VALUE as *const i32 as *mut i32, *mut i32);
973    generate_test!(r#ref: &VALUE, &'static i32);
974    // 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.
975    generate_test!(ref_mut: Box::leak(Box::new(VALUE)), & 'static mut i32, |x: &&'static mut i32| *x as *const i32,
976        |x: &'static mut i32|
977            // Safety:
978            // drop is only called once on the decoded value
979            unsafe {Box::from_raw(x as *mut i32)}
980    );
981    generate_test!(nonnull: NonNull::new(&VALUE as *const i32 as *mut i32).unwrap(), NonNull<i32>);
982    generate_test!(primitive_u32: 42, u32);
983    generate_test!(primitive_nonzero_u32: NonZeroU32::new(42).unwrap(), NonZeroU32);
984    generate_test!(unit: (), ());
985
986    #[cfg(feature = "alloc")]
987    mod alloc_ {
988        use alloc::{
989            boxed::Box,
990            rc::{self, Rc},
991            sync::{self, Arc},
992        };
993
994        use super::*;
995
996        generate_test!(r#box: Box::new(VALUE), Box<i32>);
997        generate_test!(r#arc: Arc::new(VALUE), Arc<i32>);
998        generate_test!(r#rc: Rc::new(VALUE), Rc<i32>);
999        generate_test!(weak_rc: Rc::downgrade(&Rc::new(VALUE)), rc::Weak<i32>, |x: &rc::Weak<i32>| x.as_ptr(), drop);
1000        generate_test!(weak_arc: Arc::downgrade(&Arc::new(VALUE)), sync::Weak<i32>, |x: &sync::Weak<i32>| x.as_ptr(), drop);
1001    }
1002}