nblf_queue/core/
packed.rs1use core::{
2 marker::PhantomData,
3 num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32},
4 ptr::NonNull,
5};
6
7pub unsafe trait AsPackedValue: Sized {
18 const MIN_BIT_WIDTH: usize;
20 fn encode(zelf: Self) -> TruncatedU64<Self>;
23
24 unsafe fn decode(raw: TruncatedU64<Self>) -> Self;
28
29 fn is_rt_safe() -> bool {
31 true
32 }
33}
34
35#[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 pub fn read(&self) -> u64 {
54 self.v
55 }
56}
57
58impl<T: AsPackedValue> TruncatedU64<T> {
59 pub fn new(mut value: u64) -> Self {
62 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 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 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
124unsafe 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 unsafe fn decode(_raw: TruncatedU64<Self>) -> Self {}
136}
137
138#[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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#[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 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 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 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 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 unsafe { &*(raw.read() as *const T) }
485 }
486 }
487
488 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 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 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 unsafe { Box::from_raw(raw.read() as *mut T) }
527 }
528 }
529
530 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 unsafe { Rc::from_raw(raw.read() as *mut T) }
544 }
545 }
546
547 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 unsafe { Arc::from_raw(raw.read() as *mut T) }
561 }
562 }
563
564 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 unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
578 }
579 }
580
581 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 unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
595 }
596 }
597 }
598}
599
600#[cfg(not(target_pointer_width = "64"))]
602mod bit32 {
603 use core::num::NonZeroUsize;
604
605 use super::*;
606
607 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 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 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 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 unsafe { &*(raw.read() as *const T) }
672 }
673 }
674
675 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 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 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 unsafe { Box::from_raw(raw.read() as *mut T) }
714 }
715 }
716
717 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 unsafe { Rc::from_raw(raw.read() as *mut T) }
731 }
732 }
733
734 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 unsafe { Arc::from_raw(raw.read() as *mut T) }
748 }
749 }
750
751 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 unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
765 }
766 }
767
768 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 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 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}