1
1
use crate :: convert:: { TryFrom , TryInto } ;
2
2
use crate :: intrinsics:: assert_unsafe_precondition;
3
3
use crate :: num:: NonZeroUsize ;
4
- use crate :: { cmp, fmt, hash, mem, num} ;
4
+ use crate :: { cmp, fmt, hash, mem, num, str } ;
5
5
6
6
/// A type storing a `usize` which is a power of two, and thus
7
7
/// represents a possible alignment in the rust abstract machine.
@@ -42,6 +42,7 @@ impl Alignment {
42
42
/// This provides the same numerical value as [`mem::align_of`],
43
43
/// but in an `Alignment` instead of a `usize`.
44
44
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
45
+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
45
46
#[ inline]
46
47
pub const fn of < T > ( ) -> Self {
47
48
// SAFETY: rustc ensures that type alignment is always a power of two.
@@ -53,6 +54,7 @@ impl Alignment {
53
54
///
54
55
/// Note that `0` is not a power of two, nor a valid alignment.
55
56
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
57
+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
56
58
#[ inline]
57
59
pub const fn new ( align : usize ) -> Option < Self > {
58
60
if align. is_power_of_two ( ) {
@@ -98,6 +100,7 @@ impl Alignment {
98
100
99
101
/// Returns the alignment as a [`NonZeroUsize`]
100
102
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
103
+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
101
104
#[ inline]
102
105
pub const fn as_nonzero ( self ) -> NonZeroUsize {
103
106
// SAFETY: All the discriminants are non-zero.
@@ -118,10 +121,39 @@ impl Alignment {
118
121
/// assert_eq!(Alignment::new(1024).unwrap().log2(), 10);
119
122
/// ```
120
123
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
124
+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
121
125
#[ inline]
122
- pub fn log2 ( self ) -> u32 {
126
+ pub const fn log2 ( self ) -> u32 {
123
127
self . as_nonzero ( ) . trailing_zeros ( )
124
128
}
129
+
130
+ /// Returns a bit mask that can be used to match this alignment.
131
+ ///
132
+ /// This is equivalent to `!(self.as_usize() - 1)`.
133
+ ///
134
+ /// # Examples
135
+ ///
136
+ /// ```
137
+ /// #![feature(ptr_alignment_type)]
138
+ /// #![feature(ptr_mask)]
139
+ /// use std::ptr::{Alignment, NonNull};
140
+ ///
141
+ /// let one = <NonNull<u8>>::dangling().as_ptr();
142
+ /// let four = <NonNull<u32>>::dangling().as_ptr();
143
+ ///
144
+ /// assert_eq!(four.mask(Alignment::of::<u8>().mask()), four);
145
+ /// assert_eq!(four.mask(Alignment::of::<u16>().mask()), four);
146
+ /// assert_eq!(four.mask(Alignment::of::<u32>().mask()), four);
147
+ /// assert_ne!(four.mask(Alignment::of::<u64>().mask()), four);
148
+ /// assert_ne!(one.mask(Alignment::of::<u64>().mask()), one);
149
+ /// ```
150
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
151
+ #[ rustc_const_unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
152
+ #[ inline]
153
+ pub const fn mask ( self ) -> usize {
154
+ // SAFETY: The alignment is always nonzero, and therefore decrementing won't overflow.
155
+ !( unsafe { self . as_usize ( ) . unchecked_sub ( 1 ) } )
156
+ }
125
157
}
126
158
127
159
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
@@ -131,6 +163,92 @@ impl fmt::Debug for Alignment {
131
163
}
132
164
}
133
165
166
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
167
+ impl fmt:: Display for Alignment {
168
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
169
+ fmt:: Display :: fmt ( & self . as_nonzero ( ) , f)
170
+ }
171
+ }
172
+
173
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
174
+ impl fmt:: Binary for Alignment {
175
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
176
+ fmt:: Binary :: fmt ( & self . as_nonzero ( ) , f)
177
+ }
178
+ }
179
+
180
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
181
+ impl fmt:: Octal for Alignment {
182
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
183
+ fmt:: Octal :: fmt ( & self . as_nonzero ( ) , f)
184
+ }
185
+ }
186
+
187
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
188
+ impl fmt:: LowerHex for Alignment {
189
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
190
+ fmt:: LowerHex :: fmt ( & self . as_nonzero ( ) , f)
191
+ }
192
+ }
193
+
194
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
195
+ impl fmt:: UpperHex for Alignment {
196
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
197
+ fmt:: UpperHex :: fmt ( & self . as_nonzero ( ) , f)
198
+ }
199
+ }
200
+
201
+ impl Alignment {
202
+ // longest string: 1p-128
203
+ fn fmt_exp ( self , buf : & mut [ u8 ; 6 ] , p : u8 ) -> & [ u8 ] {
204
+ buf[ 0 ] = b'1' ;
205
+ buf[ 1 ] = p;
206
+
207
+ let mut shl = self . log2 ( ) as u8 ;
208
+ if shl == 0 {
209
+ buf[ 2 ] = b'0' ;
210
+ return & buf[ ..3 ] ;
211
+ }
212
+
213
+ buf[ 2 ] = b'-' ;
214
+ if shl > 100 {
215
+ buf[ 5 ] = b'0' + shl % 10 ;
216
+ shl /= 10 ;
217
+ buf[ 4 ] = b'0' + shl % 10 ;
218
+ shl /= 10 ;
219
+ buf[ 3 ] = b'0' + shl % 10 ;
220
+ & buf[ ..6 ]
221
+ } else if shl > 10 {
222
+ buf[ 4 ] = b'0' + shl % 10 ;
223
+ shl /= 10 ;
224
+ buf[ 3 ] = b'0' + shl % 10 ;
225
+ & buf[ ..5 ]
226
+ } else {
227
+ buf[ 3 ] = b'0' + shl % 10 ;
228
+ & buf[ ..4 ]
229
+ }
230
+ }
231
+ }
232
+
233
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
234
+ impl fmt:: LowerExp for Alignment {
235
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
236
+ let mut buf = [ 0 ; 6 ] ;
237
+
238
+ // SAFETY: We generate an ASCII string, which is valid UTF-8.
239
+ f. pad ( unsafe { str:: from_utf8_unchecked ( self . fmt_exp ( & mut buf, b'p' ) ) } )
240
+ }
241
+ }
242
+
243
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
244
+ impl fmt:: UpperExp for Alignment {
245
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
246
+ let mut buf = [ 0 ; 6 ] ;
247
+ // SAFETY: We generate an ASCII string, which is valid UTF-8.
248
+ f. pad ( unsafe { str:: from_utf8_unchecked ( self . fmt_exp ( & mut buf, b'P' ) ) } )
249
+ }
250
+ }
251
+
134
252
#[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
135
253
impl TryFrom < NonZeroUsize > for Alignment {
136
254
type Error = num:: TryFromIntError ;
@@ -193,6 +311,13 @@ impl hash::Hash for Alignment {
193
311
}
194
312
}
195
313
314
+ #[ unstable( feature = "ptr_alignment_type" , issue = "102070" ) ]
315
+ impl Default for Alignment {
316
+ fn default ( ) -> Alignment {
317
+ Alignment :: MIN
318
+ }
319
+ }
320
+
196
321
#[ cfg( target_pointer_width = "16" ) ]
197
322
type AlignmentEnum = AlignmentEnum16 ;
198
323
#[ cfg( target_pointer_width = "32" ) ]
0 commit comments