@@ -1222,6 +1222,66 @@ impl<T: ?Sized> NonNull<T> {
1222
1222
// SAFETY: the caller must uphold the safety contract for `swap`.
1223
1223
unsafe { ptr:: swap ( self . as_ptr ( ) , with. as_ptr ( ) ) }
1224
1224
}
1225
+
1226
+ /// Computes the offset that needs to be applied to the pointer in order to make it aligned to
1227
+ /// `align`.
1228
+ ///
1229
+ /// If it is not possible to align the pointer, the implementation returns
1230
+ /// `usize::MAX`. It is permissible for the implementation to *always*
1231
+ /// return `usize::MAX`. Only your algorithm's performance can depend
1232
+ /// on getting a usable offset here, not its correctness.
1233
+ ///
1234
+ /// The offset is expressed in number of `T` elements, and not bytes.
1235
+ ///
1236
+ /// There are no guarantees whatsoever that offsetting the pointer will not overflow or go
1237
+ /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
1238
+ /// the returned offset is correct in all terms other than alignment.
1239
+ ///
1240
+ /// # Panics
1241
+ ///
1242
+ /// The function panics if `align` is not a power-of-two.
1243
+ ///
1244
+ /// # Examples
1245
+ ///
1246
+ /// Accessing adjacent `u8` as `u16`
1247
+ ///
1248
+ /// ```
1249
+ /// #![feature(non_null_convenience)]
1250
+ /// use std::mem::align_of;
1251
+ /// use std::ptr::NonNull;
1252
+ ///
1253
+ /// # unsafe {
1254
+ /// let x = [5_u8, 6, 7, 8, 9];
1255
+ /// let ptr = NonNull::new(x.as_ptr() as *mut u8).unwrap();
1256
+ /// let offset = ptr.align_offset(align_of::<u16>());
1257
+ ///
1258
+ /// if offset < x.len() - 1 {
1259
+ /// let u16_ptr = ptr.add(offset).cast::<u16>();
1260
+ /// assert!(u16_ptr.read() == u16::from_ne_bytes([5, 6]) || u16_ptr.read() == u16::from_ne_bytes([6, 7]));
1261
+ /// } else {
1262
+ /// // while the pointer can be aligned via `offset`, it would point
1263
+ /// // outside the allocation
1264
+ /// }
1265
+ /// # }
1266
+ /// ```
1267
+ #[ unstable( feature = "non_null_convenience" , issue = "117691" ) ]
1268
+ #[ rustc_const_unstable( feature = "non_null_convenience" , issue = "117691" ) ]
1269
+ //#[rustc_const_unstable(feature = "const_align_offset", issue = "90962")]
1270
+ #[ must_use]
1271
+ #[ inline]
1272
+ pub const fn align_offset ( self , align : usize ) -> usize
1273
+ where
1274
+ T : Sized ,
1275
+ {
1276
+ if !align. is_power_of_two ( ) {
1277
+ panic ! ( "align_offset: align is not a power-of-two" ) ;
1278
+ }
1279
+
1280
+ {
1281
+ // SAFETY: `align` has been checked to be a power of 2 above.
1282
+ unsafe { ptr:: align_offset ( self . pointer , align) }
1283
+ }
1284
+ }
1225
1285
}
1226
1286
1227
1287
impl < T > NonNull < [ T ] > {
0 commit comments