Skip to main content

nblf_queue/core/
packed.rs

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