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(all(target_arch = "x86_64", target_pointer_width = "64"))]
142mod x86_64 {
143 use super::*;
144
145 fn assert_ptr_safety() {
146 let dummy = 42;
147 let raw = &dummy as *const i32;
148 let addr = raw as u64;
149 let top_16 = addr >> 48;
150 let bit_47 = (addr >> 47) & 1;
151
152 assert!(
153 (bit_47 == 0 && top_16 == 0) || (bit_47 == 1 && top_16 == 0xFFFF),
154 "Pointer {:p} exceeds 48-bit address space! AsPackedValue is unsafe here. Consider using a PooledQueue or a Tagged128 Slot.",
155 raw
156 );
157 }
158
159 unsafe impl<T> AsPackedValue for *const T
164 where
165 T: Sized,
166 {
167 const MIN_BIT_WIDTH: usize = 48;
168
169 fn encode(zelf: Self) -> TruncatedU64<Self> {
170 TruncatedU64::new(zelf as u64)
171 }
172
173 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
174 crate::utils::sign_extend(raw.read()) as *const T
175 }
176
177 fn is_rt_safe() -> bool {
178 assert_ptr_safety();
179 true
180 }
181 }
182
183 unsafe impl<T> AsPackedValue for *mut T
188 where
189 T: Sized,
190 {
191 const MIN_BIT_WIDTH: usize = 48;
192
193 fn encode(zelf: Self) -> TruncatedU64<Self> {
194 TruncatedU64::new(zelf as u64)
195 }
196
197 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
198 crate::utils::sign_extend(raw.read()) as *mut T
199 }
200
201 fn is_rt_safe() -> bool {
202 assert_ptr_safety();
203 true
204 }
205 }
206
207 unsafe impl<T> AsPackedValue for NonNull<T>
212 where
213 T: Sized,
214 {
215 const MIN_BIT_WIDTH: usize = 48;
216
217 fn encode(zelf: Self) -> TruncatedU64<Self> {
218 TruncatedU64::new(zelf.as_ptr() as u64)
219 }
220
221 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
222 Self::new(crate::utils::sign_extend(raw.read()) as *mut T)
223 .expect("tried to recosntruct a NonNull from 0")
224 }
225
226 fn is_rt_safe() -> bool {
227 assert_ptr_safety();
228 true
229 }
230 }
231
232 unsafe impl<T> AsPackedValue for &'static T {
237 const MIN_BIT_WIDTH: usize = 48;
238
239 fn encode(zelf: Self) -> TruncatedU64<Self> {
240 TruncatedU64::new(zelf as *const T as u64)
241 }
242
243 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
244 unsafe { &*(crate::utils::sign_extend(raw.read()) as *const T) }
247 }
248
249 fn is_rt_safe() -> bool {
250 assert_ptr_safety();
251 true
252 }
253 }
254
255 unsafe impl<T> AsPackedValue for &'static mut T {
260 const MIN_BIT_WIDTH: usize = 48;
261
262 fn encode(zelf: Self) -> TruncatedU64<Self> {
263 TruncatedU64::new(zelf as *mut T as u64)
264 }
265
266 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
267 unsafe { &mut *(crate::utils::sign_extend(raw.read()) as *mut T) }
270 }
271
272 fn is_rt_safe() -> bool {
273 assert_ptr_safety();
274 true
275 }
276 }
277
278 #[cfg(any(feature = "alloc", test))]
279 mod alloc_ {
280 use alloc::{
281 boxed::Box,
282 rc::{self, Rc},
283 sync::{self, Arc},
284 };
285
286 use super::*;
287
288 unsafe impl<T> AsPackedValue for Box<T> {
293 const MIN_BIT_WIDTH: usize = 48;
294
295 fn encode(zelf: Self) -> TruncatedU64<Self> {
296 let raw = Box::into_raw(zelf);
297 TruncatedU64::new(raw as u64)
298 }
299
300 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
301 unsafe { Box::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
304 }
305
306 fn is_rt_safe() -> bool {
307 assert_ptr_safety();
308 true
309 }
310 }
311
312 unsafe impl<T> AsPackedValue for Rc<T> {
317 const MIN_BIT_WIDTH: usize = 48;
318
319 fn encode(zelf: Self) -> TruncatedU64<Self> {
320 let raw = Rc::into_raw(zelf);
321 TruncatedU64::new(raw as u64)
322 }
323
324 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
325 unsafe { Rc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
328 }
329
330 fn is_rt_safe() -> bool {
331 assert_ptr_safety();
332 true
333 }
334 }
335
336 unsafe impl<T> AsPackedValue for Arc<T> {
341 const MIN_BIT_WIDTH: usize = 48;
342
343 fn encode(zelf: Self) -> TruncatedU64<Self> {
344 let raw = Arc::into_raw(zelf);
345 TruncatedU64::new(raw as u64)
346 }
347
348 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
349 unsafe { Arc::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
352 }
353
354 fn is_rt_safe() -> bool {
355 assert_ptr_safety();
356 true
357 }
358 }
359
360 unsafe impl<T> AsPackedValue for rc::Weak<T> {
365 const MIN_BIT_WIDTH: usize = 48;
366
367 fn encode(zelf: Self) -> TruncatedU64<Self> {
368 let raw = rc::Weak::into_raw(zelf);
369 TruncatedU64::new(raw as u64)
370 }
371
372 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
373 unsafe { rc::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
376 }
377
378 fn is_rt_safe() -> bool {
379 assert_ptr_safety();
380 true
381 }
382 }
383
384 unsafe impl<T> AsPackedValue for sync::Weak<T> {
389 const MIN_BIT_WIDTH: usize = 48;
390
391 fn encode(zelf: Self) -> TruncatedU64<Self> {
392 let raw = sync::Weak::into_raw(zelf);
393 TruncatedU64::new(raw as u64)
394 }
395
396 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
397 unsafe { sync::Weak::from_raw(crate::utils::sign_extend(raw.read()) as *mut T) }
400 }
401
402 fn is_rt_safe() -> bool {
403 assert_ptr_safety();
404 true
405 }
406 }
407 }
408}
409
410#[cfg(all(not(target_arch = "x86_64"), target_pointer_width = "64"))]
411mod full_bit64 {
412 use super::*;
413
414 unsafe impl<T> AsPackedValue for *const T
417 where
418 T: Sized,
419 {
420 const MIN_BIT_WIDTH: usize = 64;
421
422 fn encode(zelf: Self) -> TruncatedU64<Self> {
423 TruncatedU64::new(zelf as u64)
424 }
425
426 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
427 raw.read() as *const T
428 }
429 }
430
431 unsafe impl<T> AsPackedValue for *mut T
434 where
435 T: Sized,
436 {
437 const MIN_BIT_WIDTH: usize = 64;
438
439 fn encode(zelf: Self) -> TruncatedU64<Self> {
440 TruncatedU64::new(zelf as u64)
441 }
442
443 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
444 raw.read() as *mut T
445 }
446 }
447
448 unsafe impl<T> AsPackedValue for NonNull<T>
452 where
453 T: Sized,
454 {
455 const MIN_BIT_WIDTH: usize = 64;
456
457 fn encode(zelf: Self) -> TruncatedU64<Self> {
458 TruncatedU64::new(zelf.as_ptr() as u64)
459 }
460
461 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
462 Self::new(raw.read() as *mut T).expect("tried to recosntruct a NonNull from 0")
463 }
464 }
465
466 unsafe impl<T> AsPackedValue for &'static T {
469 const MIN_BIT_WIDTH: usize = 64;
470
471 fn encode(zelf: Self) -> TruncatedU64<Self> {
472 TruncatedU64::new(zelf as *const T as u64)
473 }
474
475 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
476 unsafe { &*(raw.read() as *const T) }
479 }
480 }
481
482 unsafe impl<T> AsPackedValue for &'static mut T {
485 const MIN_BIT_WIDTH: usize = 64;
486
487 fn encode(zelf: Self) -> TruncatedU64<Self> {
488 TruncatedU64::new(zelf as *mut T as u64)
489 }
490
491 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
492 unsafe { &mut *(raw.read() as *mut T) }
495 }
496 }
497
498 #[cfg(any(feature = "alloc", test))]
499 mod alloc_ {
500 use alloc::{
501 boxed::Box,
502 rc::{self, Rc},
503 sync::{self, Arc},
504 };
505
506 use super::*;
507
508 unsafe impl<T> AsPackedValue for Box<T> {
511 const MIN_BIT_WIDTH: usize = 64;
512
513 fn encode(zelf: Self) -> TruncatedU64<Self> {
514 TruncatedU64::new(Box::into_raw(zelf) as u64)
515 }
516
517 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
518 unsafe { Box::from_raw(raw.read() as *mut T) }
521 }
522 }
523
524 unsafe impl<T> AsPackedValue for Rc<T> {
527 const MIN_BIT_WIDTH: usize = 64;
528
529 fn encode(zelf: Self) -> TruncatedU64<Self> {
530 let raw = Rc::into_raw(zelf);
531 TruncatedU64::new(raw as u64)
532 }
533
534 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
535 unsafe { Rc::from_raw(raw.read() as *mut T) }
538 }
539 }
540
541 unsafe impl<T> AsPackedValue for Arc<T> {
544 const MIN_BIT_WIDTH: usize = 64;
545
546 fn encode(zelf: Self) -> TruncatedU64<Self> {
547 let raw = Arc::into_raw(zelf);
548 TruncatedU64::new(raw as u64)
549 }
550
551 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
552 unsafe { Arc::from_raw(raw.read() as *mut T) }
555 }
556 }
557
558 unsafe impl<T> AsPackedValue for rc::Weak<T> {
561 const MIN_BIT_WIDTH: usize = 64;
562
563 fn encode(zelf: Self) -> TruncatedU64<Self> {
564 let raw = rc::Weak::into_raw(zelf);
565 TruncatedU64::new(raw as u64)
566 }
567
568 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
569 unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
572 }
573 }
574
575 unsafe impl<T> AsPackedValue for sync::Weak<T> {
578 const MIN_BIT_WIDTH: usize = 64;
579
580 fn encode(zelf: Self) -> TruncatedU64<Self> {
581 let raw = sync::Weak::into_raw(zelf);
582 TruncatedU64::new(raw as u64)
583 }
584
585 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
586 unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
589 }
590 }
591 }
592}
593
594#[cfg(not(target_pointer_width = "64"))]
595mod bit32 {
596 use core::num::NonZeroUsize;
597
598 use super::*;
599
600 unsafe impl<T> AsPackedValue for *const T
603 where
604 T: Sized,
605 {
606 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
607
608 fn encode(zelf: Self) -> TruncatedU64<Self> {
609 TruncatedU64::new(zelf as u64)
610 }
611
612 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
613 raw.read() as *const T
614 }
615 }
616
617 unsafe impl<T> AsPackedValue for *mut T
620 where
621 T: Sized,
622 {
623 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
624
625 fn encode(zelf: Self) -> TruncatedU64<Self> {
626 TruncatedU64::new(zelf as u64)
627 }
628
629 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
630 raw.read() as *mut T
631 }
632 }
633
634 unsafe impl<T> AsPackedValue for NonNull<T>
637 where
638 T: Sized,
639 {
640 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
641
642 fn encode(zelf: Self) -> TruncatedU64<Self> {
643 TruncatedU64::new(zelf.as_ptr() as u64)
644 }
645
646 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
647 Self::new(raw.read() as *mut T)
648 .expect("Constructing a NonNull form a null ptr wich was not obtained from encode")
649 }
650 }
651
652 unsafe impl<T> AsPackedValue for &'static T {
655 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
656
657 fn encode(zelf: Self) -> TruncatedU64<Self> {
658 TruncatedU64::new(zelf as *const T as u64)
659 }
660
661 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
662 unsafe { &*(raw.read() as *const T) }
665 }
666 }
667
668 unsafe impl<T> AsPackedValue for &'static mut T {
671 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
672
673 fn encode(zelf: Self) -> TruncatedU64<Self> {
674 TruncatedU64::new(zelf as *mut T as u64)
675 }
676
677 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
678 unsafe { &mut *(raw.read() as *mut T) }
681 }
682 }
683
684 #[cfg(feature = "alloc")]
685 mod alloc_ {
686 use alloc::{
687 boxed::Box,
688 rc::{self, Rc},
689 sync::{self, Arc},
690 };
691
692 use super::*;
693
694 unsafe impl<T> AsPackedValue for Box<T> {
697 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
698
699 fn encode(zelf: Self) -> TruncatedU64<Self> {
700 TruncatedU64::new(Box::into_raw(zelf) as u64)
701 }
702
703 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
704 unsafe { Box::from_raw(raw.read() as *mut T) }
707 }
708 }
709
710 unsafe impl<T> AsPackedValue for Rc<T> {
713 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
714
715 fn encode(zelf: Self) -> TruncatedU64<Self> {
716 let raw = Rc::into_raw(zelf);
717 TruncatedU64::new(raw as u64)
718 }
719
720 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
721 unsafe { Rc::from_raw(raw.read() as *mut T) }
724 }
725 }
726
727 unsafe impl<T> AsPackedValue for Arc<T> {
730 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
731
732 fn encode(zelf: Self) -> TruncatedU64<Self> {
733 let raw = Arc::into_raw(zelf);
734 TruncatedU64::new(raw as u64)
735 }
736
737 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
738 unsafe { Arc::from_raw(raw.read() as *mut T) }
741 }
742 }
743
744 unsafe impl<T> AsPackedValue for rc::Weak<T> {
747 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
748
749 fn encode(zelf: Self) -> TruncatedU64<Self> {
750 let raw = rc::Weak::into_raw(zelf);
751 TruncatedU64::new(raw as u64)
752 }
753
754 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
755 unsafe { rc::Weak::from_raw(raw.read() as *mut T) }
758 }
759 }
760
761 unsafe impl<T> AsPackedValue for sync::Weak<T> {
764 const MIN_BIT_WIDTH: usize = size_of::<usize>() * 8;
765
766 fn encode(zelf: Self) -> TruncatedU64<Self> {
767 let raw = sync::Weak::into_raw(zelf);
768 TruncatedU64::new(raw as u64)
769 }
770
771 unsafe fn decode(raw: TruncatedU64<Self>) -> Self {
772 unsafe { sync::Weak::from_raw(raw.read() as *mut T) }
775 }
776 }
777 }
778
779 atomic_encode_primitive!(usize);
780 atomic_encode_non_zero_primitive!(NonZeroUsize, usize);
781}
782
783#[cfg(test)]
784mod tests {
785 use super::*;
786
787 macro_rules! generate_test {
788 ($name:ident: $constructor:expr, $type:ty, $deref:expr) => {
789 #[test]
790 fn $name() {
791 #[allow(dead_code)]
792 static VALUE: i32 = 42;
793 const WIDTH: usize = <$type as AsPackedValue>::MIN_BIT_WIDTH;
794
795 let ptr1 = $constructor;
796 let expected = $deref(&ptr1);
797
798 let mut encoded = AsPackedValue::encode(ptr1);
799
800 if WIDTH < 64 {
801 let packed_encoded = pack!((!0, encoded.read()): WIDTH);
802 encoded = TruncatedU64::new(packed_encoded);
803 }
804
805 let decoded = unsafe { AsPackedValue::decode(encoded) };
808
809 assert_eq!($deref(&decoded), expected);
810 }
811 };
812 ($name:ident: $constructor:expr, $type:ty) => {
813 generate_test!($name: $constructor, $type, |x: &$type| x.clone());
814 };
815 }
816
817 generate_test!(raw: &VALUE as *const i32, *const i32);
818 generate_test!(raw_mut: &VALUE as *const i32 as *mut i32, *mut i32);
819 generate_test!(r#ref: &VALUE, &'static i32);
820 generate_test!(nonnull: NonNull::new(&VALUE as *const i32 as *mut i32).unwrap(), NonNull<i32>);
821 generate_test!(primitive_u32: 42, u32);
822 generate_test!(primitive_nonzero_u32: NonZeroU32::new(42).unwrap(), NonZeroU32);
823 generate_test!(unit: (), ());
824
825 #[cfg(feature = "alloc")]
826 mod alloc_ {
827 use alloc::{
828 boxed::Box,
829 rc::{self, Rc},
830 sync::{self, Arc},
831 };
832
833 use super::*;
834
835 generate_test!(r#box: Box::new(VALUE), Box<i32>);
836 generate_test!(r#arc: Arc::new(VALUE), Arc<i32>);
837 generate_test!(r#rc: Rc::new(VALUE), Rc<i32>);
838 generate_test!(weak_rc: Rc::downgrade(&Rc::new(VALUE)), rc::Weak<i32>, |x: &rc::Weak<i32>| x.as_ptr());
839 generate_test!(weak_arc: Arc::downgrade(&Arc::new(VALUE)), sync::Weak<i32>, |x: &sync::Weak<i32>| x.as_ptr());
840 }
841}