50
50
P : Pointer ,
51
51
T : Tag ,
52
52
{
53
+ pub fn new ( pointer : P , tag : T ) -> Self {
54
+ Self { packed : Self :: pack ( P :: into_ptr ( pointer) , tag) , data : PhantomData }
55
+ }
56
+
53
57
const TAG_BIT_SHIFT : usize = usize:: BITS as usize - T :: BITS ;
54
58
const ASSERTION : ( ) = {
55
59
assert ! ( T :: BITS <= P :: BITS ) ;
@@ -58,28 +62,28 @@ where
58
62
assert ! ( std:: mem:: size_of:: <& P :: Target >( ) == std:: mem:: size_of:: <usize >( ) ) ;
59
63
} ;
60
64
61
- pub fn new ( pointer : P , tag : T ) -> Self {
65
+ /// Pack pointer `ptr` that comes from [`P::into_ptr`] with a `tag`.
66
+ ///
67
+ /// [`P::into_ptr`]: Pointer::into_ptr
68
+ fn pack ( ptr : NonNull < P :: Target > , tag : T ) -> NonNull < P :: Target > {
62
69
// Trigger assert!
63
70
let ( ) = Self :: ASSERTION ;
64
71
65
72
let packed_tag = tag. into_usize ( ) << Self :: TAG_BIT_SHIFT ;
66
73
67
- Self {
68
- packed : P :: into_ptr ( pointer) . map_addr ( |addr| {
69
- // SAFETY:
70
- // - The pointer is `NonNull` => it's address is `NonZeroUsize`
71
- // - `P::BITS` least significant bits are always zero (`Pointer` contract)
72
- // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
73
- //
74
- // Thus `addr >> T::BITS` is guaranteed to be non-zero.
75
- //
76
- // `{non_zero} | packed_tag` can't make the value zero.
77
-
78
- let packed = ( addr. get ( ) >> T :: BITS ) | packed_tag;
79
- unsafe { NonZeroUsize :: new_unchecked ( packed) }
80
- } ) ,
81
- data : PhantomData ,
82
- }
74
+ ptr. map_addr ( |addr| {
75
+ // SAFETY:
76
+ // - The pointer is `NonNull` => it's address is `NonZeroUsize`
77
+ // - `P::BITS` least significant bits are always zero (`Pointer` contract)
78
+ // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
79
+ //
80
+ // Thus `addr >> T::BITS` is guaranteed to be non-zero.
81
+ //
82
+ // `{non_zero} | packed_tag` can't make the value zero.
83
+
84
+ let packed = ( addr. get ( ) >> T :: BITS ) | packed_tag;
85
+ unsafe { NonZeroUsize :: new_unchecked ( packed) }
86
+ } )
83
87
}
84
88
85
89
pub ( super ) fn pointer_raw ( & self ) -> NonNull < P :: Target > {
@@ -117,12 +121,7 @@ where
117
121
118
122
#[ inline]
119
123
pub fn set_tag ( & mut self , tag : T ) {
120
- // TODO: refactor packing into a function and reuse it here
121
- let new_tag = T :: into_usize ( tag) << Self :: TAG_BIT_SHIFT ;
122
- let tag_mask = ( 1 << T :: BITS ) - 1 ;
123
- self . packed = self . packed . map_addr ( |addr| unsafe {
124
- NonZeroUsize :: new_unchecked ( addr. get ( ) & !( tag_mask << Self :: TAG_BIT_SHIFT ) | new_tag)
125
- } ) ;
124
+ self . packed = Self :: pack ( self . pointer_raw ( ) , tag) ;
126
125
}
127
126
}
128
127
0 commit comments