zerocopy/util/mod.rs
1// Copyright 2023 The Fuchsia Authors
2//
3// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6// This file may not be copied, modified, or distributed except according to
7// those terms.
8
9#[macro_use]
10pub(crate) mod macros;
11
12#[doc(hidden)]
13pub mod macro_util;
14
15use core::{
16 marker::PhantomData,
17 mem::{self, ManuallyDrop},
18 num::NonZeroUsize,
19 ptr::NonNull,
20};
21
22use super::*;
23
24/// Like [`PhantomData`], but [`Send`] and [`Sync`] regardless of whether the
25/// wrapped `T` is.
26pub(crate) struct SendSyncPhantomData<T: ?Sized>(PhantomData<T>);
27
28// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
29// to be called from multiple threads.
30unsafe impl<T: ?Sized> Send for SendSyncPhantomData<T> {}
31// SAFETY: `SendSyncPhantomData` does not enable any behavior which isn't sound
32// to be called from multiple threads.
33unsafe impl<T: ?Sized> Sync for SendSyncPhantomData<T> {}
34
35impl<T: ?Sized> Default for SendSyncPhantomData<T> {
36 fn default() -> SendSyncPhantomData<T> {
37 SendSyncPhantomData(PhantomData)
38 }
39}
40
41impl<T: ?Sized> PartialEq for SendSyncPhantomData<T> {
42 fn eq(&self, other: &Self) -> bool {
43 self.0.eq(&other.0)
44 }
45}
46
47impl<T: ?Sized> Eq for SendSyncPhantomData<T> {}
48
49pub(crate) trait AsAddress {
50 fn addr(self) -> usize;
51}
52
53impl<T: ?Sized> AsAddress for &T {
54 #[inline(always)]
55 fn addr(self) -> usize {
56 let ptr: *const T = self;
57 AsAddress::addr(ptr)
58 }
59}
60
61impl<T: ?Sized> AsAddress for &mut T {
62 #[inline(always)]
63 fn addr(self) -> usize {
64 let ptr: *const T = self;
65 AsAddress::addr(ptr)
66 }
67}
68
69impl<T: ?Sized> AsAddress for NonNull<T> {
70 #[inline(always)]
71 fn addr(self) -> usize {
72 AsAddress::addr(self.as_ptr())
73 }
74}
75
76impl<T: ?Sized> AsAddress for *const T {
77 #[inline(always)]
78 fn addr(self) -> usize {
79 // FIXME(#181), FIXME(https://github.com/rust-lang/rust/issues/95228):
80 // Use `.addr()` instead of `as usize` once it's stable, and get rid of
81 // this `allow`. Currently, `as usize` is the only way to accomplish
82 // this.
83 #[allow(clippy::as_conversions)]
84 #[cfg_attr(
85 __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS,
86 allow(lossy_provenance_casts)
87 )]
88 return self.cast::<()>() as usize;
89 }
90}
91
92impl<T: ?Sized> AsAddress for *mut T {
93 #[inline(always)]
94 fn addr(self) -> usize {
95 let ptr: *const T = self;
96 AsAddress::addr(ptr)
97 }
98}
99
100/// Validates that `t` is aligned to `align_of::<U>()`.
101#[inline(always)]
102pub(crate) fn validate_aligned_to<T: AsAddress, U>(t: T) -> Result<(), AlignmentError<(), U>> {
103 // `mem::align_of::<U>()` is guaranteed to return a non-zero value, which in
104 // turn guarantees that this mod operation will not panic.
105 #[allow(clippy::arithmetic_side_effects)]
106 let remainder = t.addr() % mem::align_of::<U>();
107 if remainder == 0 {
108 Ok(())
109 } else {
110 // SAFETY: We just confirmed that `t.addr() % align_of::<U>() != 0`.
111 // That's only possible if `align_of::<U>() > 1`.
112 Err(unsafe { AlignmentError::new_unchecked(()) })
113 }
114}
115
116/// Returns the bytes needed to pad `len` to the next multiple of `align`.
117///
118/// This function assumes that align is a power of two; there are no guarantees
119/// on the answer it gives if this is not the case.
120#[cfg_attr(
121 kani,
122 kani::requires(len <= isize::MAX as usize),
123 kani::requires(align.is_power_of_two()),
124 kani::ensures(|&p| (len + p) % align.get() == 0),
125 // Ensures that we add the minimum required padding.
126 kani::ensures(|&p| p < align.get()),
127)]
128pub(crate) const fn padding_needed_for(len: usize, align: NonZeroUsize) -> usize {
129 #[cfg(kani)]
130 #[kani::proof_for_contract(padding_needed_for)]
131 fn proof() {
132 padding_needed_for(kani::any(), kani::any());
133 }
134
135 // Abstractly, we want to compute:
136 // align - (len % align).
137 // Handling the case where len%align is 0.
138 // Because align is a power of two, len % align = len & (align-1).
139 // Guaranteed not to underflow as align is nonzero.
140 #[allow(clippy::arithmetic_side_effects)]
141 let mask = align.get() - 1;
142
143 // To efficiently subtract this value from align, we can use the bitwise complement.
144 // Note that ((!len) & (align-1)) gives us a number that with (len &
145 // (align-1)) sums to align-1. So subtracting 1 from x before taking the
146 // complement subtracts `len` from `align`. Some quick inspection of
147 // cases shows that this also handles the case where `len % align = 0`
148 // correctly too: len-1 % align then equals align-1, so the complement mod
149 // align will be 0, as desired.
150 //
151 // The following reasoning can be verified quickly by an SMT solver
152 // supporting the theory of bitvectors:
153 // ```smtlib
154 // ; Naive implementation of padding
155 // (define-fun padding1 (
156 // (len (_ BitVec 32))
157 // (align (_ BitVec 32))) (_ BitVec 32)
158 // (ite
159 // (= (_ bv0 32) (bvand len (bvsub align (_ bv1 32))))
160 // (_ bv0 32)
161 // (bvsub align (bvand len (bvsub align (_ bv1 32))))))
162 //
163 // ; The implementation below
164 // (define-fun padding2 (
165 // (len (_ BitVec 32))
166 // (align (_ BitVec 32))) (_ BitVec 32)
167 // (bvand (bvnot (bvsub len (_ bv1 32))) (bvsub align (_ bv1 32))))
168 //
169 // (define-fun is-power-of-two ((x (_ BitVec 32))) Bool
170 // (= (_ bv0 32) (bvand x (bvsub x (_ bv1 32)))))
171 //
172 // (declare-const len (_ BitVec 32))
173 // (declare-const align (_ BitVec 32))
174 // ; Search for a case where align is a power of two and padding2 disagrees with padding1
175 // (assert (and (is-power-of-two align)
176 // (not (= (padding1 len align) (padding2 len align)))))
177 // (simplify (padding1 (_ bv300 32) (_ bv32 32))) ; 20
178 // (simplify (padding2 (_ bv300 32) (_ bv32 32))) ; 20
179 // (simplify (padding1 (_ bv322 32) (_ bv32 32))) ; 30
180 // (simplify (padding2 (_ bv322 32) (_ bv32 32))) ; 30
181 // (simplify (padding1 (_ bv8 32) (_ bv8 32))) ; 0
182 // (simplify (padding2 (_ bv8 32) (_ bv8 32))) ; 0
183 // (check-sat) ; unsat, also works for 64-bit bitvectors
184 // ```
185 !(len.wrapping_sub(1)) & mask
186}
187
188/// Rounds `n` down to the largest value `m` such that `m <= n` and `m % align
189/// == 0`.
190///
191/// # Panics
192///
193/// May panic if `align` is not a power of two. Even if it doesn't panic in this
194/// case, it will produce nonsense results.
195#[inline(always)]
196#[cfg_attr(
197 kani,
198 kani::requires(align.is_power_of_two()),
199 kani::ensures(|&m| m <= n && m % align.get() == 0),
200 // Guarantees that `m` is the *largest* value such that `m % align == 0`.
201 kani::ensures(|&m| {
202 // If this `checked_add` fails, then the next multiple would wrap
203 // around, which trivially satisfies the "largest value" requirement.
204 m.checked_add(align.get()).map(|next_mul| next_mul > n).unwrap_or(true)
205 })
206)]
207pub(crate) const fn round_down_to_next_multiple_of_alignment(
208 n: usize,
209 align: NonZeroUsize,
210) -> usize {
211 #[cfg(kani)]
212 #[kani::proof_for_contract(round_down_to_next_multiple_of_alignment)]
213 fn proof() {
214 round_down_to_next_multiple_of_alignment(kani::any(), kani::any());
215 }
216
217 let align = align.get();
218 #[cfg(zerocopy_panic_in_const_and_vec_try_reserve_1_57_0)]
219 debug_assert!(align.is_power_of_two());
220
221 // Subtraction can't underflow because `align.get() >= 1`.
222 #[allow(clippy::arithmetic_side_effects)]
223 let mask = !(align - 1);
224 n & mask
225}
226
227pub(crate) const fn max(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
228 if a.get() < b.get() {
229 b
230 } else {
231 a
232 }
233}
234
235pub(crate) const fn min(a: NonZeroUsize, b: NonZeroUsize) -> NonZeroUsize {
236 if a.get() > b.get() {
237 b
238 } else {
239 a
240 }
241}
242
243/// Copies `src` into the prefix of `dst`.
244///
245/// # Safety
246///
247/// The caller guarantees that `src.len() <= dst.len()`.
248#[inline(always)]
249pub(crate) unsafe fn copy_unchecked(src: &[u8], dst: &mut [u8]) {
250 debug_assert!(src.len() <= dst.len());
251 // SAFETY: This invocation satisfies the safety contract of
252 // copy_nonoverlapping [1]:
253 // - `src.as_ptr()` is trivially valid for reads of `src.len()` bytes
254 // - `dst.as_ptr()` is valid for writes of `src.len()` bytes, because the
255 // caller has promised that `src.len() <= dst.len()`
256 // - `src` and `dst` are, trivially, properly aligned
257 // - the region of memory beginning at `src` with a size of `src.len()`
258 // bytes does not overlap with the region of memory beginning at `dst`
259 // with the same size, because `dst` is derived from an exclusive
260 // reference.
261 unsafe {
262 core::ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
263 };
264}
265
266/// Unsafely transmutes the given `src` into a type `Dst`.
267///
268/// # Safety
269///
270/// The value `src` must be a valid instance of `Dst`.
271#[inline(always)]
272pub(crate) const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
273 static_assert!(Src, Dst => core::mem::size_of::<Src>() == core::mem::size_of::<Dst>());
274
275 #[repr(C)]
276 union Transmute<Src, Dst> {
277 src: ManuallyDrop<Src>,
278 dst: ManuallyDrop<Dst>,
279 }
280
281 // SAFETY: Since `Transmute<Src, Dst>` is `#[repr(C)]`, its `src` and `dst`
282 // fields both start at the same offset and the types of those fields are
283 // transparent wrappers around `Src` and `Dst` [1]. Consequently,
284 // initializng `Transmute` with with `src` and then reading out `dst` is
285 // equivalent to transmuting from `Src` to `Dst` [2]. Transmuting from `src`
286 // to `Dst` is valid because — by contract on the caller — `src` is a valid
287 // instance of `Dst`.
288 //
289 // [1] Per https://doc.rust-lang.org/1.82.0/std/mem/struct.ManuallyDrop.html:
290 //
291 // `ManuallyDrop<T>` is guaranteed to have the same layout and bit
292 // validity as `T`, and is subject to the same layout optimizations as
293 // `T`.
294 //
295 // [2] Per https://doc.rust-lang.org/1.82.0/reference/items/unions.html#reading-and-writing-union-fields:
296 //
297 // Effectively, writing to and then reading from a union with the C
298 // representation is analogous to a transmute from the type used for
299 // writing to the type used for reading.
300 unsafe { ManuallyDrop::into_inner(Transmute { src: ManuallyDrop::new(src) }.dst) }
301}
302
303/// Uses `allocate` to create a `Box<T>`.
304///
305/// # Errors
306///
307/// Returns an error on allocation failure. Allocation failure is guaranteed
308/// never to cause a panic or an abort.
309///
310/// # Safety
311///
312/// `allocate` must be either `alloc::alloc::alloc` or
313/// `alloc::alloc::alloc_zeroed`. The referent of the box returned by `new_box`
314/// has the same bit-validity as the referent of the pointer returned by the
315/// given `allocate` and sufficient size to store `T` with `meta`.
316#[must_use = "has no side effects (other than allocation)"]
317#[cfg(feature = "alloc")]
318#[inline]
319pub(crate) unsafe fn new_box<T>(
320 meta: T::PointerMetadata,
321 allocate: unsafe fn(core::alloc::Layout) -> *mut u8,
322) -> Result<alloc::boxed::Box<T>, AllocError>
323where
324 T: ?Sized + crate::KnownLayout,
325{
326 let size = match meta.size_for_metadata(T::LAYOUT) {
327 Some(size) => size,
328 None => return Err(AllocError),
329 };
330
331 let align = T::LAYOUT.align.get();
332 // On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a bug in
333 // which sufficiently-large allocations (those which, when rounded up to the
334 // alignment, overflow `isize`) are not rejected, which can cause undefined
335 // behavior. See #64 for details.
336 //
337 // FIXME(#67): Once our MSRV is > 1.64.0, remove this assertion.
338 #[allow(clippy::as_conversions)]
339 let max_alloc = (isize::MAX as usize).saturating_sub(align);
340 if size > max_alloc {
341 return Err(AllocError);
342 }
343
344 // FIXME(https://github.com/rust-lang/rust/issues/55724): Use
345 // `Layout::repeat` once it's stabilized.
346 let layout = Layout::from_size_align(size, align).or(Err(AllocError))?;
347
348 let ptr = if layout.size() != 0 {
349 // SAFETY: By contract on the caller, `allocate` is either
350 // `alloc::alloc::alloc` or `alloc::alloc::alloc_zeroed`. The above
351 // check ensures their shared safety precondition: that the supplied
352 // layout is not zero-sized type [1].
353 //
354 // [1] Per https://doc.rust-lang.org/stable/std/alloc/trait.GlobalAlloc.html#tymethod.alloc:
355 //
356 // This function is unsafe because undefined behavior can result if
357 // the caller does not ensure that layout has non-zero size.
358 let ptr = unsafe { allocate(layout) };
359 match NonNull::new(ptr) {
360 Some(ptr) => ptr,
361 None => return Err(AllocError),
362 }
363 } else {
364 let align = T::LAYOUT.align.get();
365 // We use `transmute` instead of an `as` cast since Miri (with strict
366 // provenance enabled) notices and complains that an `as` cast creates a
367 // pointer with no provenance. Miri isn't smart enough to realize that
368 // we're only executing this branch when we're constructing a zero-sized
369 // `Box`, which doesn't require provenance.
370 //
371 // SAFETY: any initialized bit sequence is a bit-valid `*mut u8`. All
372 // bits of a `usize` are initialized.
373 #[allow(clippy::useless_transmute)]
374 let dangling = unsafe { mem::transmute::<usize, *mut u8>(align) };
375 // SAFETY: `dangling` is constructed from `T::LAYOUT.align`, which is a
376 // `NonZeroUsize`, which is guaranteed to be non-zero.
377 //
378 // `Box<[T]>` does not allocate when `T` is zero-sized or when `len` is
379 // zero, but it does require a non-null dangling pointer for its
380 // allocation.
381 //
382 // FIXME(https://github.com/rust-lang/rust/issues/95228): Use
383 // `std::ptr::without_provenance` once it's stable. That may optimize
384 // better. As written, Rust may assume that this consumes "exposed"
385 // provenance, and thus Rust may have to assume that this may consume
386 // provenance from any pointer whose provenance has been exposed.
387 unsafe { NonNull::new_unchecked(dangling) }
388 };
389
390 let ptr = T::raw_from_ptr_len(ptr, meta);
391
392 // FIXME(#429): Add a "SAFETY" comment and remove this `allow`. Make sure to
393 // include a justification that `ptr.as_ptr()` is validly-aligned in the ZST
394 // case (in which we manually construct a dangling pointer) and to justify
395 // why `Box` is safe to drop (it's because `allocate` uses the system
396 // allocator).
397 #[allow(clippy::undocumented_unsafe_blocks)]
398 Ok(unsafe { alloc::boxed::Box::from_raw(ptr.as_ptr()) })
399}
400
401mod len_of {
402 use super::*;
403
404 /// A witness type for metadata of a valid instance of `&T`.
405 pub(crate) struct MetadataOf<T: ?Sized + KnownLayout> {
406 /// # Safety
407 ///
408 /// The size of an instance of `&T` with the given metadata is not
409 /// larger than `isize::MAX`.
410 meta: T::PointerMetadata,
411 _p: PhantomData<T>,
412 }
413
414 impl<T: ?Sized + KnownLayout> Copy for MetadataOf<T> {}
415 impl<T: ?Sized + KnownLayout> Clone for MetadataOf<T> {
416 fn clone(&self) -> Self {
417 *self
418 }
419 }
420
421 impl<T: ?Sized> MetadataOf<T>
422 where
423 T: KnownLayout,
424 {
425 /// Returns `None` if `meta` is greater than `t`'s metadata.
426 #[inline(always)]
427 pub(crate) fn new_in_bounds(t: &T, meta: usize) -> Option<Self>
428 where
429 T: KnownLayout<PointerMetadata = usize>,
430 {
431 if meta <= Ptr::from_ref(t).len() {
432 // SAFETY: We have checked that `meta` is not greater than `t`'s
433 // metadata, which, by invariant on `&T`, addresses no more than
434 // `isize::MAX` bytes [1][2].
435 //
436 // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety:
437 //
438 // For all types, `T: ?Sized`, and for all `t: &T` or `t:
439 // &mut T`, when such values cross an API boundary, the
440 // following invariants must generally be upheld:
441 //
442 // * `t` is non-null
443 // * `t` is aligned to `align_of_val(t)`
444 // * if `size_of_val(t) > 0`, then `t` is dereferenceable for
445 // `size_of_val(t)` many bytes
446 //
447 // If `t` points at address `a`, being "dereferenceable" for
448 // N bytes means that the memory range `[a, a + N)` is all
449 // contained within a single allocated object.
450 //
451 // [2] Per https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object:
452 //
453 // For any allocated object with `base` address, `size`, and
454 // a set of `addresses`, the following are guaranteed:
455 // - For all addresses `a` in `addresses`, `a` is in the
456 // range `base .. (base + size)` (note that this requires
457 // `a < base + size`, not `a <= base + size`)
458 // - `base` is not equal to [`null()`] (i.e., the address
459 // with the numerical value 0)
460 // - `base + size <= usize::MAX`
461 // - `size <= isize::MAX`
462 Some(unsafe { Self::new_unchecked(meta) })
463 } else {
464 None
465 }
466 }
467
468 /// # Safety
469 ///
470 /// The size of an instance of `&T` with the given metadata is not
471 /// larger than `isize::MAX`.
472 pub(crate) unsafe fn new_unchecked(meta: T::PointerMetadata) -> Self {
473 // SAFETY: The caller has promised that the size of an instance of
474 // `&T` with the given metadata is not larger than `isize::MAX`.
475 Self { meta, _p: PhantomData }
476 }
477
478 pub(crate) fn get(&self) -> T::PointerMetadata
479 where
480 T::PointerMetadata: Copy,
481 {
482 self.meta
483 }
484
485 #[inline]
486 pub(crate) fn padding_needed_for(&self) -> usize
487 where
488 T: KnownLayout<PointerMetadata = usize>,
489 {
490 let trailing_slice_layout = crate::trailing_slice_layout::<T>();
491 // SAFETY: By invariant on `self`, a `&T` with metadata `self.meta`
492 // describes an object of size `<= isize::MAX`. This computes the
493 // size of such a `&T` without any trailing padding, and so neither
494 // the multiplication nor the addition will overflow.
495 //
496 // FIXME(#67): Remove this allow. See NumExt for more details.
497 #[allow(unstable_name_collisions, clippy::incompatible_msrv)]
498 let unpadded_size = unsafe {
499 let trailing_size = self.meta.unchecked_mul(trailing_slice_layout.elem_size);
500 trailing_size.unchecked_add(trailing_slice_layout.offset)
501 };
502
503 util::padding_needed_for(unpadded_size, T::LAYOUT.align)
504 }
505
506 #[inline(always)]
507 pub(crate) fn validate_cast_and_convert_metadata(
508 addr: usize,
509 bytes_len: MetadataOf<[u8]>,
510 cast_type: CastType,
511 meta: Option<T::PointerMetadata>,
512 ) -> Result<(MetadataOf<T>, MetadataOf<[u8]>), MetadataCastError> {
513 let layout = match meta {
514 None => T::LAYOUT,
515 // This can return `None` if the metadata describes an object
516 // which can't fit in an `isize`.
517 Some(meta) => {
518 let size = match meta.size_for_metadata(T::LAYOUT) {
519 Some(size) => size,
520 None => return Err(MetadataCastError::Size),
521 };
522 DstLayout { align: T::LAYOUT.align, size_info: crate::SizeInfo::Sized { size } }
523 }
524 };
525 // Lemma 0: By contract on `validate_cast_and_convert_metadata`, if
526 // the result is `Ok(..)`, then a `&T` with `elems` trailing slice
527 // elements is no larger in size than `bytes_len.get()`.
528 let (elems, split_at) =
529 layout.validate_cast_and_convert_metadata(addr, bytes_len.get(), cast_type)?;
530 let elems = T::PointerMetadata::from_elem_count(elems);
531
532 // For a slice DST type, if `meta` is `Some(elems)`, then we
533 // synthesize `layout` to describe a sized type whose size is equal
534 // to the size of the instance that we are asked to cast. For sized
535 // types, `validate_cast_and_convert_metadata` returns `elems == 0`.
536 // Thus, in this case, we need to use the `elems` passed by the
537 // caller, not the one returned by
538 // `validate_cast_and_convert_metadata`.
539 //
540 // Lemma 1: A `&T` with `elems` trailing slice elements is no larger
541 // in size than `bytes_len.get()`. Proof:
542 // - If `meta` is `None`, then `elems` satisfies this condition by
543 // Lemma 0.
544 // - If `meta` is `Some(meta)`, then `layout` describes an object
545 // whose size is equal to the size of an `&T` with `meta`
546 // metadata. By Lemma 0, that size is not larger than
547 // `bytes_len.get()`.
548 //
549 // Lemma 2: A `&T` with `elems` trailing slice elements is no larger
550 // than `isize::MAX` bytes. Proof: By Lemma 1, a `&T` with metadata
551 // `elems` is not larger in size than `bytes_len.get()`. By
552 // invariant on `MetadataOf<[u8]>`, a `&[u8]` with metadata
553 // `bytes_len` is not larger than `isize::MAX`. Because
554 // `size_of::<u8>()` is `1`, a `&[u8]` with metadata `bytes_len` has
555 // size `bytes_len.get()` bytes. Therefore, a `&T` with metadata
556 // `elems` has size not larger than `isize::MAX`.
557 let elems = meta.unwrap_or(elems);
558
559 // SAFETY: See Lemma 2.
560 let elems = unsafe { MetadataOf::new_unchecked(elems) };
561
562 // SAFETY: Let `size` be the size of a `&T` with metadata `elems`.
563 // By post-condition on `validate_cast_and_convert_metadata`, one of
564 // the following conditions holds:
565 // - `split_at == size`, in which case, by Lemma 2, `split_at <=
566 // isize::MAX`. Since `size_of::<u8>() == 1`, a `[u8]` with
567 // `split_at` elems has size not larger than `isize::MAX`.
568 // - `split_at == bytes_len - size`. Since `bytes_len:
569 // MetadataOf<u8>`, and since `size` is non-negative, `split_at`
570 // addresses no more bytes than `bytes_len` does. Since
571 // `bytes_len: MetadataOf<u8>`, `bytes_len` describes a `[u8]`
572 // which has no more than `isize::MAX` bytes, and thus so does
573 // `split_at`.
574 let split_at = unsafe { MetadataOf::<[u8]>::new_unchecked(split_at) };
575 Ok((elems, split_at))
576 }
577 }
578}
579
580pub(crate) use len_of::MetadataOf;
581
582/// Since we support multiple versions of Rust, there are often features which
583/// have been stabilized in the most recent stable release which do not yet
584/// exist (stably) on our MSRV. This module provides polyfills for those
585/// features so that we can write more "modern" code, and just remove the
586/// polyfill once our MSRV supports the corresponding feature. Without this,
587/// we'd have to write worse/more verbose code and leave FIXME comments sprinkled
588/// throughout the codebase to update to the new pattern once it's stabilized.
589///
590/// Each trait is imported as `_` at the crate root; each polyfill should "just
591/// work" at usage sites.
592pub(crate) mod polyfills {
593 use core::ptr::{self, NonNull};
594
595 // A polyfill for `NonNull::slice_from_raw_parts` that we can use before our
596 // MSRV is 1.70, when that function was stabilized.
597 //
598 // The `#[allow(unused)]` is necessary because, on sufficiently recent
599 // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
600 // method rather than to this trait, and so this trait is considered unused.
601 //
602 // FIXME(#67): Once our MSRV is 1.70, remove this.
603 #[allow(unused)]
604 pub(crate) trait NonNullExt<T> {
605 fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]>;
606 }
607
608 impl<T> NonNullExt<T> for NonNull<T> {
609 // NOTE on coverage: this will never be tested in nightly since it's a
610 // polyfill for a feature which has been stabilized on our nightly
611 // toolchain.
612 #[cfg_attr(
613 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
614 coverage(off)
615 )]
616 #[inline(always)]
617 fn slice_from_raw_parts(data: Self, len: usize) -> NonNull<[T]> {
618 let ptr = ptr::slice_from_raw_parts_mut(data.as_ptr(), len);
619 // SAFETY: `ptr` is converted from `data`, which is non-null.
620 unsafe { NonNull::new_unchecked(ptr) }
621 }
622 }
623
624 // A polyfill for `Self::unchecked_sub` that we can use until methods like
625 // `usize::unchecked_sub` is stabilized.
626 //
627 // The `#[allow(unused)]` is necessary because, on sufficiently recent
628 // toolchain versions, `ptr.slice_from_raw_parts()` resolves to the inherent
629 // method rather than to this trait, and so this trait is considered unused.
630 //
631 // FIXME(#67): Once our MSRV is high enough, remove this.
632 #[allow(unused)]
633 pub(crate) trait NumExt {
634 /// Subtract without checking for underflow.
635 ///
636 /// # Safety
637 ///
638 /// The caller promises that the subtraction will not underflow.
639 unsafe fn unchecked_sub(self, rhs: Self) -> Self;
640
641 /// Add without checking for overflow.
642 ///
643 /// # Safety
644 ///
645 /// The caller promises that the addition will not overflow.
646 unsafe fn unchecked_add(self, rhs: Self) -> Self;
647
648 /// Multiply without checking for overflow.
649 ///
650 /// # Safety
651 ///
652 /// The caller promises that the multiplication will not overflow.
653 unsafe fn unchecked_mul(self, rhs: Self) -> Self;
654 }
655
656 impl NumExt for usize {
657 // NOTE on coverage: this will never be tested in nightly since it's a
658 // polyfill for a feature which has been stabilized on our nightly
659 // toolchain.
660 #[cfg_attr(
661 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
662 coverage(off)
663 )]
664 #[inline(always)]
665 unsafe fn unchecked_sub(self, rhs: usize) -> usize {
666 match self.checked_sub(rhs) {
667 Some(x) => x,
668 None => {
669 // SAFETY: The caller promises that the subtraction will not
670 // underflow.
671 unsafe { core::hint::unreachable_unchecked() }
672 }
673 }
674 }
675
676 // NOTE on coverage: this will never be tested in nightly since it's a
677 // polyfill for a feature which has been stabilized on our nightly
678 // toolchain.
679 #[cfg_attr(
680 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
681 coverage(off)
682 )]
683 #[inline(always)]
684 unsafe fn unchecked_add(self, rhs: usize) -> usize {
685 match self.checked_add(rhs) {
686 Some(x) => x,
687 None => {
688 // SAFETY: The caller promises that the addition will not
689 // overflow.
690 unsafe { core::hint::unreachable_unchecked() }
691 }
692 }
693 }
694
695 // NOTE on coverage: this will never be tested in nightly since it's a
696 // polyfill for a feature which has been stabilized on our nightly
697 // toolchain.
698 #[cfg_attr(
699 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
700 coverage(off)
701 )]
702 #[inline(always)]
703 unsafe fn unchecked_mul(self, rhs: usize) -> usize {
704 match self.checked_mul(rhs) {
705 Some(x) => x,
706 None => {
707 // SAFETY: The caller promises that the multiplication will
708 // not overflow.
709 unsafe { core::hint::unreachable_unchecked() }
710 }
711 }
712 }
713 }
714}
715
716#[cfg(test)]
717pub(crate) mod testutil {
718 use crate::*;
719
720 /// A `T` which is aligned to at least `align_of::<A>()`.
721 #[derive(Default)]
722 pub(crate) struct Align<T, A> {
723 pub(crate) t: T,
724 _a: [A; 0],
725 }
726
727 impl<T: Default, A> Align<T, A> {
728 pub(crate) fn set_default(&mut self) {
729 self.t = T::default();
730 }
731 }
732
733 impl<T, A> Align<T, A> {
734 pub(crate) const fn new(t: T) -> Align<T, A> {
735 Align { t, _a: [] }
736 }
737 }
738
739 /// A `T` which is guaranteed not to satisfy `align_of::<A>()`.
740 ///
741 /// It must be the case that `align_of::<T>() < align_of::<A>()` in order
742 /// fot this type to work properly.
743 #[repr(C)]
744 pub(crate) struct ForceUnalign<T: Unaligned, A> {
745 // The outer struct is aligned to `A`, and, thanks to `repr(C)`, `t` is
746 // placed at the minimum offset that guarantees its alignment. If
747 // `align_of::<T>() < align_of::<A>()`, then that offset will be
748 // guaranteed *not* to satisfy `align_of::<A>()`.
749 //
750 // Note that we need `T: Unaligned` in order to guarantee that there is
751 // no padding between `_u` and `t`.
752 _u: u8,
753 pub(crate) t: T,
754 _a: [A; 0],
755 }
756
757 impl<T: Unaligned, A> ForceUnalign<T, A> {
758 pub(crate) fn new(t: T) -> ForceUnalign<T, A> {
759 ForceUnalign { _u: 0, t, _a: [] }
760 }
761 }
762 // A `u64` with alignment 8.
763 //
764 // Though `u64` has alignment 8 on some platforms, it's not guaranteed. By
765 // contrast, `AU64` is guaranteed to have alignment 8 on all platforms.
766 #[derive(
767 KnownLayout,
768 Immutable,
769 FromBytes,
770 IntoBytes,
771 Eq,
772 PartialEq,
773 Ord,
774 PartialOrd,
775 Default,
776 Debug,
777 Copy,
778 Clone,
779 )]
780 #[repr(C, align(8))]
781 pub(crate) struct AU64(pub(crate) u64);
782
783 impl AU64 {
784 // Converts this `AU64` to bytes using this platform's endianness.
785 pub(crate) fn to_bytes(self) -> [u8; 8] {
786 crate::transmute!(self)
787 }
788 }
789
790 impl Display for AU64 {
791 #[cfg_attr(
792 all(coverage_nightly, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS),
793 coverage(off)
794 )]
795 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
796 Display::fmt(&self.0, f)
797 }
798 }
799
800 #[derive(Immutable, FromBytes, Eq, PartialEq, Ord, PartialOrd, Default, Debug, Copy, Clone)]
801 #[repr(C)]
802 pub(crate) struct Nested<T, U: ?Sized> {
803 _t: T,
804 _u: U,
805 }
806}
807
808#[cfg(test)]
809mod tests {
810 use super::*;
811
812 #[test]
813 fn test_round_down_to_next_multiple_of_alignment() {
814 fn alt_impl(n: usize, align: NonZeroUsize) -> usize {
815 let mul = n / align.get();
816 mul * align.get()
817 }
818
819 for align in [1, 2, 4, 8, 16] {
820 for n in 0..256 {
821 let align = NonZeroUsize::new(align).unwrap();
822 let want = alt_impl(n, align);
823 let got = round_down_to_next_multiple_of_alignment(n, align);
824 assert_eq!(got, want, "round_down_to_next_multiple_of_alignment({}, {})", n, align);
825 }
826 }
827 }
828
829 #[rustversion::since(1.57.0)]
830 #[test]
831 #[should_panic]
832 fn test_round_down_to_next_multiple_of_alignment_zerocopy_panic_in_const_and_vec_try_reserve() {
833 round_down_to_next_multiple_of_alignment(0, NonZeroUsize::new(3).unwrap());
834 }
835}