xref: /linux/rust/zerocopy/src/pointer/inner.rs (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
1 // SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
2 //
3 // Copyright 2024 The Fuchsia Authors
4 //
5 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
6 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
7 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
8 // This file may not be copied, modified, or distributed except according to
9 // those terms.
10 
11 use core::{marker::PhantomData, ops::Range, ptr::NonNull};
12 
13 pub use _def::PtrInner;
14 
15 #[allow(unused_imports)]
16 use crate::util::polyfills::NumExt as _;
17 use crate::{
18     layout::{CastType, MetadataCastError},
19     pointer::cast,
20     util::AsAddress,
21     AlignmentError, CastError, KnownLayout, MetadataOf, SizeError, SplitAt,
22 };
23 
24 mod _def {
25     use super::*;
26     /// The inner pointer stored inside a [`Ptr`][crate::Ptr].
27     ///
28     /// `PtrInner<'a, T>` is [covariant] in `'a` and invariant in `T`.
29     ///
30     /// [covariant]: https://doc.rust-lang.org/reference/subtyping.html
31     #[allow(missing_debug_implementations)]
32     pub struct PtrInner<'a, T>
33     where
34         T: ?Sized,
35     {
36         /// # Invariants
37         ///
38         /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
39         ///    provenance for its referent, which is entirely contained in some
40         ///    Rust allocation, `A`.
41         /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live
42         ///    for at least `'a`.
43         ///
44         /// # Postconditions
45         ///
46         /// By virtue of these invariants, code may assume the following, which
47         /// are logical implications of the invariants:
48         /// - `ptr`'s referent is not larger than `isize::MAX` bytes \[1\]
49         /// - `ptr`'s referent does not wrap around the address space \[1\]
50         ///
51         /// \[1\] Per <https://doc.rust-lang.org/1.85.0/std/ptr/index.html#allocated-object>:
52         ///
53         ///   For any allocated object with `base` address, `size`, and a set of
54         ///   `addresses`, the following are guaranteed:
55         ///   ...
56         ///   - `size <= isize::MAX`
57         ///
58         ///   As a consequence of these guarantees, given any address `a` within
59         ///   the set of addresses of an allocated object:
60         ///   ...
61         ///   - It is guaranteed that, given `o = a - base` (i.e., the offset of
62         ///     `a` within the allocated object), `base + o` will not wrap
63         ///     around the address space (in other words, will not overflow
64         ///     `usize`)
65         ptr: NonNull<T>,
66         // SAFETY: `&'a UnsafeCell<T>` is covariant in `'a` and invariant in `T`
67         // [1]. We use this construction rather than the equivalent `&mut T`,
68         // because our MSRV of 1.65 prohibits `&mut` types in const contexts.
69         //
70         // [1] https://doc.rust-lang.org/1.81.0/reference/subtyping.html#variance
71         _marker: PhantomData<&'a core::cell::UnsafeCell<T>>,
72     }
73 
74     impl<'a, T: 'a + ?Sized> Copy for PtrInner<'a, T> {}
75     impl<'a, T: 'a + ?Sized> Clone for PtrInner<'a, T> {
76         #[inline(always)]
77         fn clone(&self) -> PtrInner<'a, T> {
78             // SAFETY: None of the invariants on `ptr` are affected by having
79             // multiple copies of a `PtrInner`.
80             *self
81         }
82     }
83 
84     impl<'a, T: 'a + ?Sized> PtrInner<'a, T> {
85         /// Constructs a `Ptr` from a [`NonNull`].
86         ///
87         /// # Safety
88         ///
89         /// The caller promises that:
90         ///
91         /// 0. If `ptr`'s referent is not zero sized, then `ptr` has valid
92         ///    provenance for its referent, which is entirely contained in some
93         ///    Rust allocation, `A`.
94         /// 1. If `ptr`'s referent is not zero sized, `A` is guaranteed to live
95         ///    for at least `'a`.
96         #[inline(always)]
97         #[must_use]
98         pub const unsafe fn new(ptr: NonNull<T>) -> PtrInner<'a, T> {
99             // SAFETY: The caller has promised to satisfy all safety invariants
100             // of `PtrInner`.
101             Self { ptr, _marker: PhantomData }
102         }
103 
104         /// Converts this `PtrInner<T>` to a [`NonNull<T>`].
105         ///
106         /// Note that this method does not consume `self`. The caller should
107         /// watch out for `unsafe` code which uses the returned `NonNull` in a
108         /// way that violates the safety invariants of `self`.
109         #[inline(always)]
110         #[must_use]
111         pub const fn as_non_null(&self) -> NonNull<T> {
112             self.ptr
113         }
114 
115         /// Converts this `PtrInner<T>` to a [`*mut T`].
116         ///
117         /// Note that this method does not consume `self`. The caller should
118         /// watch out for `unsafe` code which uses the returned `*mut T` in a
119         /// way that violates the safety invariants of `self`.
120         #[inline(always)]
121         #[must_use]
122         pub const fn as_ptr(&self) -> *mut T {
123             self.ptr.as_ptr()
124         }
125     }
126 }
127 
128 impl<'a, T: ?Sized> PtrInner<'a, T> {
129     /// Constructs a `PtrInner` from a reference.
130     #[inline]
131     pub fn from_ref(ptr: &'a T) -> Self {
132         let ptr = NonNull::from(ptr);
133         // SAFETY:
134         // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
135         //    `&'a T` [1], has valid provenance for its referent, which is
136         //    entirely contained in some Rust allocation, `A`.
137         // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on
138         //    `&'a T`, is guaranteed to live for at least `'a`.
139         //
140         // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety:
141         //
142         //   For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`,
143         //   when such values cross an API boundary, the following invariants
144         //   must generally be upheld:
145         //   ...
146         //   - if `size_of_val(t) > 0`, then `t` is dereferenceable for
147         //     `size_of_val(t)` many bytes
148         //
149         //   If `t` points at address `a`, being “dereferenceable” for N bytes
150         //   means that the memory range `[a, a + N)` is all contained within a
151         //   single allocated object.
152         unsafe { Self::new(ptr) }
153     }
154 
155     /// Constructs a `PtrInner` from a mutable reference.
156     #[inline]
157     pub fn from_mut(ptr: &'a mut T) -> Self {
158         let ptr = NonNull::from(ptr);
159         // SAFETY:
160         // 0. If `ptr`'s referent is not zero sized, then `ptr`, by invariant on
161         //    `&'a mut T` [1], has valid provenance for its referent, which is
162         //    entirely contained in some Rust allocation, `A`.
163         // 1. If `ptr`'s referent is not zero sized, then `A`, by invariant on
164         //    `&'a mut T`, is guaranteed to live for at least `'a`.
165         //
166         // [1] Per https://doc.rust-lang.org/1.85.0/std/primitive.reference.html#safety:
167         //
168         //   For all types, `T: ?Sized`, and for all `t: &T` or `t: &mut T`,
169         //   when such values cross an API boundary, the following invariants
170         //   must generally be upheld:
171         //   ...
172         //   - if `size_of_val(t) > 0`, then `t` is dereferenceable for
173         //     `size_of_val(t)` many bytes
174         //
175         //   If `t` points at address `a`, being “dereferenceable” for N bytes
176         //   means that the memory range `[a, a + N)` is all contained within a
177         //   single allocated object.
178         unsafe { Self::new(ptr) }
179     }
180 
181     /// # Safety
182     ///
183     /// The caller may assume that the resulting `PtrInner` addresses the subset
184     /// of the bytes of `self`'s referent addressed by `C::project(self)`.
185     #[must_use]
186     #[inline(always)]
187     pub fn project<U: ?Sized, C: cast::Project<T, U>>(self) -> PtrInner<'a, U> {
188         let projected_raw = C::project(self);
189 
190         // SAFETY: `self`'s referent lives at a `NonNull` address, and is either
191         // zero-sized or lives in an allocation. In either case, it does not
192         // wrap around the address space [1], and so none of the addresses
193         // contained in it or one-past-the-end of it are null.
194         //
195         // By invariant on `C: Project`, `C::project` is a provenance-preserving
196         // projection which preserves or shrinks the set of referent bytes, so
197         // `projected_raw` references a subset of `self`'s referent, and so it
198         // cannot be null.
199         //
200         // [1] https://doc.rust-lang.org/1.92.0/std/ptr/index.html#allocation
201         let projected_non_null = unsafe { NonNull::new_unchecked(projected_raw) };
202 
203         // SAFETY: As described in the preceding safety comment, `projected_raw`,
204         // and thus `projected_non_null`, addresses a subset of `self`'s
205         // referent. Thus, `projected_non_null` either:
206         // - Addresses zero bytes or,
207         // - Addresses a subset of the referent of `self`. In this case, `self`
208         //   has provenance for its referent, which lives in an allocation.
209         //   Since `projected_non_null` was constructed using a sequence of
210         //   provenance-preserving operations, it also has provenance for its
211         //   referent and that referent lives in an allocation. By invariant on
212         //   `self`, that allocation lives for `'a`.
213         unsafe { PtrInner::new(projected_non_null) }
214     }
215 }
216 
217 #[allow(clippy::needless_lifetimes)]
218 impl<'a, T> PtrInner<'a, T>
219 where
220     T: ?Sized + KnownLayout,
221 {
222     /// Extracts the metadata of this `ptr`.
223     #[inline]
224     #[must_use]
225     pub fn meta(self) -> MetadataOf<T> {
226         let meta = T::pointer_to_metadata(self.as_ptr());
227         // SAFETY: By invariant on `PtrInner`, `self.as_non_null()` addresses no
228         // more than `isize::MAX` bytes.
229         unsafe { MetadataOf::new_unchecked(meta) }
230     }
231 
232     /// Produces a `PtrInner` with the same address and provenance as `self` but
233     /// the given `meta`.
234     ///
235     /// # Safety
236     ///
237     /// The caller promises that if `self`'s referent is not zero sized, then
238     /// a pointer constructed from its address with the given `meta` metadata
239     /// will address a subset of the allocation pointed to by `self`.
240     #[inline]
241     #[must_use]
242     pub unsafe fn with_meta(self, meta: T::PointerMetadata) -> Self
243     where
244         T: KnownLayout,
245     {
246         let raw = T::raw_from_ptr_len(self.as_non_null().cast(), meta);
247 
248         // SAFETY:
249         //
250         // Lemma 0: `raw` either addresses zero bytes, or addresses a subset of
251         //          the allocation pointed to by `self` and has the same
252         //          provenance as `self`. Proof: `raw` is constructed using
253         //          provenance-preserving operations, and the caller has
254         //          promised that, if `self`'s referent is not zero-sized, the
255         //          resulting pointer addresses a subset of the allocation
256         //          pointed to by `self`.
257         //
258         // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
259         //    zero sized, then `ptr` is derived from some valid Rust allocation,
260         //    `A`.
261         // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
262         //    zero sized, then `ptr` has valid provenance for `A`.
263         // 2. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
264         //    zero sized, then `ptr` addresses a byte range which is entirely
265         //    contained in `A`.
266         // 3. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
267         //    range whose length fits in an `isize`.
268         // 4. Per Lemma 0 and by invariant on `self`, `ptr` addresses a byte
269         //    range which does not wrap around the address space.
270         // 5. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
271         //    zero sized, then `A` is guaranteed to live for at least `'a`.
272         unsafe { PtrInner::new(raw) }
273     }
274 }
275 
276 #[allow(clippy::needless_lifetimes)]
277 impl<'a, T> PtrInner<'a, T>
278 where
279     T: ?Sized + KnownLayout<PointerMetadata = usize>,
280 {
281     /// Splits `T` in two.
282     ///
283     /// # Safety
284     ///
285     /// The caller promises that:
286     ///  - `l_len.get() <= self.meta()`.
287     ///
288     /// ## (Non-)Overlap
289     ///
290     /// Given `let (left, right) = ptr.split_at(l_len)`, it is guaranteed that
291     /// `left` and `right` are contiguous and non-overlapping if
292     /// the left part has no trailing padding. This is true for all `[T]`.
293     ///
294     /// Any trailing padding in the left part begins at the right part's
295     /// starting address and may overlap its referent.
296     #[inline]
297     #[must_use]
298     pub unsafe fn split_at_unchecked(
299         self,
300         l_len: crate::util::MetadataOf<T>,
301     ) -> (Self, PtrInner<'a, [T::Elem]>)
302     where
303         T: SplitAt,
304     {
305         let l_len = l_len.get();
306 
307         // SAFETY: The caller promises that `l_len.get() <= self.meta()`.
308         // Trivially, `0 <= l_len`.
309         let left = unsafe { self.with_meta(l_len) };
310 
311         let right = self.trailing_slice();
312         // SAFETY: The caller promises that `l_len <= self.meta() = slf.meta()`.
313         // Trivially, `slf.meta() <= slf.meta()`.
314         let right = unsafe { right.slice_unchecked(l_len..self.meta().get()) };
315 
316         // SAFETY: If the left part has no trailing padding, then `left` and
317         // `right` are non-overlapping. Proof: `left` has `l_len` trailing
318         // elements, and `right` starts at element `l_len` of the original
319         // trailing slice. Without padding after `left`'s final element, no
320         // byte is referred to by both pointers.
321         //
322         // Any trailing padding in `left` begins at `right`'s starting
323         // address. If `right` is nonzero sized, the referents overlap.
324         (left, right)
325     }
326 
327     /// Produces the trailing slice of `self` using `T::Elem` as its element
328     /// representation.
329     #[inline]
330     #[must_use]
331     pub fn trailing_slice(self) -> PtrInner<'a, [T::Elem]>
332     where
333         T: SplitAt,
334     {
335         let offset = crate::trailing_slice_layout::<T>().offset;
336 
337         let bytes = self.as_non_null().cast::<u8>().as_ptr();
338 
339         // SAFETY:
340         // - By invariant on `T: KnownLayout`, `T::LAYOUT` describes `T`'s
341         //   layout. `offset` is the offset of the trailing slice within `T`,
342         //   which is by definition in-bounds or one byte past the end of any
343         //   `T`, regardless of metadata. By invariant on `PtrInner`, `self`
344         //   (and thus `bytes`) points to a byte range of size `<= isize::MAX`,
345         //   and so `offset <= isize::MAX`. Since `size_of::<u8>() == 1`,
346         //   `offset * size_of::<u8>() <= isize::MAX`.
347         // - If `offset > 0`, then by invariant on `PtrInner`, `self` (and thus
348         //   `bytes`) points to a byte range entirely contained within the same
349         //   allocated object as `self`. As explained above, this offset results
350         //   in a pointer to or one byte past the end of this allocated object.
351         let bytes = unsafe { bytes.add(offset) };
352 
353         // SAFETY: By the preceding safety argument, `bytes` is within or one
354         // byte past the end of the same allocated object as `self`, which
355         // ensures that it is non-null.
356         let bytes = unsafe { NonNull::new_unchecked(bytes) };
357 
358         let ptr = KnownLayout::raw_from_ptr_len(bytes, self.meta().get());
359 
360         // SAFETY:
361         // 0. If `ptr`'s referent is not zero sized, then `ptr` is derived from
362         //    some valid Rust allocation, `A`, because `ptr` is derived from
363         //    the same allocated object as `self`.
364         // 1. If `ptr`'s referent is not zero sized, then `ptr` has valid
365         //    provenance for `A` because `raw` is derived from the same
366         //    allocated object as `self` via provenance-preserving operations.
367         // 2. `T: SplitAt` guarantees that `T::Elem` has the size of the actual
368         //    trailing element. The new slice has the same length and start as
369         //    the original trailing slice, so it covers the same byte range.
370         //    If nonzero sized, that range is entirely contained in `A`.
371         // 3. `ptr` addresses a byte range whose length fits in an `isize`, by
372         //    consequence of #2.
373         // 4. `ptr` addresses a byte range which does not wrap around the
374         //    address space, by consequence of #2.
375         // 5. If `ptr`'s referent is not zero sized, then `A` is guaranteed to
376         //    live for at least `'a`, because `ptr` is derived from `self`.
377         unsafe { PtrInner::new(ptr) }
378     }
379 }
380 
381 #[allow(clippy::needless_lifetimes)]
382 impl<'a, T> PtrInner<'a, [T]> {
383     /// Creates a pointer which addresses the given `range` of self.
384     ///
385     /// # Safety
386     ///
387     /// `range` is a valid range (`start <= end`) and `end <= self.meta()`.
388     #[inline]
389     #[must_use]
390     pub unsafe fn slice_unchecked(self, range: Range<usize>) -> Self {
391         let base = self.as_non_null().cast::<T>().as_ptr();
392 
393         // SAFETY: The caller promises that `start <= end <= self.meta()`. By
394         // invariant, if `self`'s referent is not zero-sized, then `self` refers
395         // to a byte range which is contained within a single allocation, which
396         // is no more than `isize::MAX` bytes long, and which does not wrap
397         // around the address space. Thus, this pointer arithmetic remains
398         // in-bounds of the same allocation, and does not wrap around the
399         // address space. The offset (in bytes) does not overflow `isize`.
400         //
401         // If `self`'s referent is zero-sized, then these conditions are
402         // trivially satisfied.
403         let base = unsafe { base.add(range.start) };
404 
405         // SAFETY: The caller promises that `start <= end`, and so this will not
406         // underflow.
407         #[allow(unstable_name_collisions)]
408         let len = unsafe { range.end.unchecked_sub(range.start) };
409 
410         let ptr = core::ptr::slice_from_raw_parts_mut(base, len);
411 
412         // SAFETY: By invariant, `self`'s referent is either a ZST or lives
413         // entirely in an allocation. `ptr` points inside of or one byte past
414         // the end of that referent. Thus, in either case, `ptr` is non-null.
415         let ptr = unsafe { NonNull::new_unchecked(ptr) };
416 
417         // SAFETY:
418         //
419         // Lemma 0: `ptr` addresses a subset of the bytes addressed by `self`,
420         //          and has the same provenance. Proof: The caller guarantees
421         //          that `start <= end <= self.meta()`. Thus, `base` is
422         //          in-bounds of `self`, and `base + (end - start)` is also
423         //          in-bounds of self. Finally, `ptr` is constructed using
424         //          provenance-preserving operations.
425         //
426         // 0. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
427         //    zero sized, then `ptr` has valid provenance for its referent,
428         //    which is entirely contained in some Rust allocation, `A`.
429         // 1. Per Lemma 0 and by invariant on `self`, if `ptr`'s referent is not
430         //    zero sized, then `A` is guaranteed to live for at least `'a`.
431         unsafe { PtrInner::new(ptr) }
432     }
433 
434     /// Iteratively projects the elements `PtrInner<T>` from `PtrInner<[T]>`.
435     #[inline]
436     pub fn iter(&self) -> impl Iterator<Item = PtrInner<'a, T>> {
437         // FIXME(#429): Once `NonNull::cast` documents that it preserves
438         // provenance, cite those docs.
439         let base = self.as_non_null().cast::<T>().as_ptr();
440         (0..self.meta().get()).map(move |i| {
441             // FIXME(https://github.com/rust-lang/rust/issues/74265): Use
442             // `NonNull::get_unchecked_mut`.
443 
444             // SAFETY: If the following conditions are not satisfied
445             // `pointer::cast` may induce Undefined Behavior [1]:
446             //
447             // > - The computed offset, `count * size_of::<T>()` bytes, must not
448             // >   overflow `isize``.
449             // > - If the computed offset is non-zero, then `self` must be
450             // >   derived from a pointer to some allocated object, and the
451             // >   entire memory range between `self` and the result must be in
452             // >   bounds of that allocated object. In particular, this range
453             // >   must not “wrap around” the edge of the address space.
454             //
455             // [1] https://doc.rust-lang.org/std/primitive.pointer.html#method.add
456             //
457             // We satisfy both of these conditions here:
458             // - By invariant on `Ptr`, `self` addresses a byte range whose
459             //   length fits in an `isize`. Since `elem` is contained in `self`,
460             //   the computed offset of `elem` must fit within `isize.`
461             // - If the computed offset is non-zero, then this means that the
462             //   referent is not zero-sized. In this case, `base` points to an
463             //   allocated object (by invariant on `self`). Thus:
464             //   - By contract, `self.meta()` accurately reflects the number of
465             //     elements in the slice. `i` is in bounds of `c.meta()` by
466             //     construction, and so the result of this addition cannot
467             //     overflow past the end of the allocation referred to by `c`.
468             //   - By invariant on `Ptr`, `self` addresses a byte range which
469             //     does not wrap around the address space. Since `elem` is
470             //     contained in `self`, the computed offset of `elem` must wrap
471             //     around the address space.
472             //
473             // FIXME(#429): Once `pointer::add` documents that it preserves
474             // provenance, cite those docs.
475             let elem = unsafe { base.add(i) };
476 
477             // SAFETY: `elem` must not be null. `base` is constructed from a
478             // `NonNull` pointer, and the addition that produces `elem` must not
479             // overflow or wrap around, so `elem >= base > 0`.
480             //
481             // FIXME(#429): Once `NonNull::new_unchecked` documents that it
482             // preserves provenance, cite those docs.
483             let elem = unsafe { NonNull::new_unchecked(elem) };
484 
485             // SAFETY: The safety invariants of `Ptr::new` (see definition) are
486             // satisfied:
487             // 0. If `elem`'s referent is not zero sized, then `elem` has valid
488             //    provenance for its referent, because it derived from `self`
489             //    using a series of provenance-preserving operations, and
490             //    because `self` has valid provenance for its referent. By the
491             //    same argument, `elem`'s referent is entirely contained within
492             //    the same allocated object as `self`'s referent.
493             // 1. If `elem`'s referent is not zero sized, then the allocation of
494             //    `elem` is guaranteed to live for at least `'a`, because `elem`
495             //    is entirely contained in `self`, which lives for at least `'a`
496             //    by invariant on `Ptr`.
497             unsafe { PtrInner::new(elem) }
498         })
499     }
500 }
501 
502 impl<'a, T, const N: usize> PtrInner<'a, [T; N]> {
503     /// Casts this pointer-to-array into a slice.
504     ///
505     /// # Safety
506     ///
507     /// Callers may assume that the returned `PtrInner` references the same
508     /// address and length as `self`.
509     #[allow(clippy::wrong_self_convention)]
510     #[inline]
511     #[must_use]
512     pub fn as_slice(self) -> PtrInner<'a, [T]> {
513         let start = self.as_non_null().cast::<T>().as_ptr();
514         let slice = core::ptr::slice_from_raw_parts_mut(start, N);
515         // SAFETY: `slice` is not null, because it is derived from `start`
516         // which is non-null.
517         let slice = unsafe { NonNull::new_unchecked(slice) };
518         // SAFETY: Lemma: In the following safety arguments, note that `slice`
519         // is derived from `self` in two steps: first, by casting `self: [T; N]`
520         // to `start: T`, then by constructing a pointer to a slice starting at
521         // `start` of length `N`. As a result, `slice` references exactly the
522         // same allocation as `self`, if any.
523         //
524         // 0. By the above lemma, if `slice`'s referent is not zero sized, then
525         //    `slice` has the same referent as `self`. By invariant on `self`,
526         //    this referent is entirely contained within some allocation, `A`.
527         //    Because `slice` was constructed using provenance-preserving
528         //    operations, it has provenance for its entire referent.
529         // 1. By the above lemma, if `slice`'s referent is not zero sized, then
530         //    `A` is guaranteed to live for at least `'a`, because it is derived
531         //    from the same allocation as `self`, which, by invariant on
532         //    `PtrInner`, lives for at least `'a`.
533         unsafe { PtrInner::new(slice) }
534     }
535 }
536 
537 impl<'a> PtrInner<'a, [u8]> {
538     /// Attempts to cast `self` to a `U` using the given cast type.
539     ///
540     /// If `U` is a slice DST and pointer metadata (`meta`) is provided, then
541     /// the cast will only succeed if it would produce an object with the given
542     /// metadata.
543     ///
544     /// Returns `None` if the resulting `U` would be invalidly-aligned, if no
545     /// `U` can fit in `self`, or if the provided pointer metadata describes an
546     /// invalid instance of `U`. On success, returns a pointer to the
547     /// largest-possible `U` which fits in `self`.
548     ///
549     /// # Safety
550     ///
551     /// The caller may assume that this implementation is correct, and may rely
552     /// on that assumption for the soundness of their code. In particular, the
553     /// caller may assume that, if `try_cast_into` returns `Some((ptr,
554     /// remainder))`, then `ptr` and `remainder` refer to non-overlapping byte
555     /// ranges within `self`, and that `ptr` and `remainder` entirely cover
556     /// `self`. Finally:
557     /// - If this is a prefix cast, `ptr` has the same address as `self`.
558     /// - If this is a suffix cast, `remainder` has the same address as `self`.
559     #[inline]
560     pub fn try_cast_into<U>(
561         self,
562         cast_type: CastType,
563         meta: Option<U::PointerMetadata>,
564     ) -> Result<(PtrInner<'a, U>, PtrInner<'a, [u8]>), CastError<Self, U>>
565     where
566         U: 'a + ?Sized + KnownLayout,
567     {
568         // PANICS: By invariant, the byte range addressed by
569         // `self.as_non_null()` does not wrap around the address space. This
570         // implies that the sum of the address (represented as a `usize`) and
571         // length do not overflow `usize`, as required by
572         // `validate_cast_and_convert_metadata`. Thus, this call to
573         // `validate_cast_and_convert_metadata` will only panic if `U` is a DST
574         // whose trailing slice element is zero-sized.
575         let maybe_metadata = MetadataOf::<U>::validate_cast_and_convert_metadata(
576             AsAddress::addr(self.as_ptr()),
577             self.meta(),
578             cast_type,
579             meta,
580         );
581 
582         let (elems, split_at) = match maybe_metadata {
583             Ok((elems, split_at)) => (elems, split_at),
584             Err(MetadataCastError::Alignment) => {
585                 // SAFETY: Since `validate_cast_and_convert_metadata` returned
586                 // an alignment error, `U` must have an alignment requirement
587                 // greater than one.
588                 let err = unsafe { AlignmentError::<_, U>::new_unchecked(self) };
589                 return Err(CastError::Alignment(err));
590             }
591             Err(MetadataCastError::Size) => return Err(CastError::Size(SizeError::new(self))),
592         };
593 
594         // SAFETY: `validate_cast_and_convert_metadata` promises to return
595         // `split_at <= self.meta()`.
596         //
597         // Lemma 0: `l_slice` and `r_slice` are non-overlapping. Proof: By
598         // contract on `PtrInner::split_at_unchecked`, the produced `PtrInner`s
599         // are always non-overlapping if `self` is a `[T]`; here it is a `[u8]`.
600         let (l_slice, r_slice) = unsafe { self.split_at_unchecked(split_at) };
601 
602         let (target, remainder) = match cast_type {
603             CastType::Prefix => (l_slice, r_slice),
604             CastType::Suffix => (r_slice, l_slice),
605         };
606 
607         let base = target.as_non_null().cast::<u8>();
608 
609         let ptr = U::raw_from_ptr_len(base, elems.get());
610 
611         // SAFETY:
612         // 0. By invariant, if `target`'s referent is not zero sized, then
613         //    `target` has provenance valid for some Rust allocation, `A`.
614         //    Because `ptr` is derived from `target` via provenance-preserving
615         //    operations, `ptr` will also have provenance valid for its entire
616         //    referent.
617         // 1. `validate_cast_and_convert_metadata` promises that the object
618         //    described by `elems` and `split_at` lives at a byte range which is
619         //    a subset of the input byte range. Thus, by invariant, if
620         //    `target`'s referent is not zero sized, then `target` refers to an
621         //    allocation which is guaranteed to live for at least `'a`, and thus
622         //    so does `ptr`.
623         Ok((unsafe { PtrInner::new(ptr) }, remainder))
624     }
625 }
626 
627 #[cfg(test)]
628 mod tests {
629     use super::*;
630     use crate::*;
631 
632     #[test]
633     fn test_meta() {
634         let arr = [1; 16];
635         let dst = <[u8]>::ref_from_bytes(&arr[..]).unwrap();
636         let ptr = PtrInner::from_ref(dst);
637         assert_eq!(ptr.meta().get(), 16);
638 
639         // SAFETY: 8 is less than 16
640         let ptr = unsafe { ptr.with_meta(8) };
641 
642         assert_eq!(ptr.meta().get(), 8);
643     }
644 
645     #[test]
646     fn test_split_at() {
647         fn test_split_at<const OFFSET: usize, const BUFFER_SIZE: usize>() {
648             #[derive(FromBytes, KnownLayout, SplitAt, Immutable)]
649             #[repr(C)]
650             struct SliceDst<const OFFSET: usize> {
651                 prefix: [u8; OFFSET],
652                 trailing: [u8],
653             }
654 
655             let n: usize = BUFFER_SIZE - OFFSET;
656             let arr = [1; BUFFER_SIZE];
657             let dst = SliceDst::<OFFSET>::ref_from_bytes(&arr[..]).unwrap();
658             let ptr = PtrInner::from_ref(dst);
659             for i in 0..=n {
660                 assert_eq!(ptr.meta().get(), n);
661                 // SAFETY: `i` is in bounds by construction.
662                 let i = unsafe { MetadataOf::new_unchecked(i) };
663                 // SAFETY: `i` is in bounds by construction.
664                 let (l, r) = unsafe { ptr.split_at_unchecked(i) };
665                 // SAFETY: Points to a valid value by construction.
666                 #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)]
667                 // Clippy false positive
668                 let l_sum: usize = l
669                     .trailing_slice()
670                     .iter()
671                     .map(
672                         #[inline(always)]
673                         |ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize,
674                     )
675                     .sum();
676                 // SAFETY: Points to a valid value by construction.
677                 #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)]
678                 // Clippy false positive
679                 let r_sum: usize = r
680                     .iter()
681                     .map(
682                         #[inline(always)]
683                         |ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize,
684                     )
685                     .sum();
686                 assert_eq!(l_sum, i.get());
687                 assert_eq!(r_sum, n - i.get());
688                 assert_eq!(l_sum + r_sum, n);
689             }
690         }
691 
692         test_split_at::<0, 16>();
693         test_split_at::<1, 17>();
694         test_split_at::<2, 18>();
695     }
696 
697     #[test]
698     fn test_trailing_slice() {
699         fn test_trailing_slice<const OFFSET: usize, const BUFFER_SIZE: usize>() {
700             #[derive(FromBytes, KnownLayout, SplitAt, Immutable)]
701             #[repr(C)]
702             struct SliceDst<const OFFSET: usize> {
703                 prefix: [u8; OFFSET],
704                 trailing: [u8],
705             }
706 
707             let n: usize = BUFFER_SIZE - OFFSET;
708             let arr = [1; BUFFER_SIZE];
709             let dst = SliceDst::<OFFSET>::ref_from_bytes(&arr[..]).unwrap();
710             let ptr = PtrInner::from_ref(dst);
711 
712             assert_eq!(ptr.meta().get(), n);
713             let trailing = ptr.trailing_slice();
714             assert_eq!(trailing.meta().get(), n);
715 
716             assert_eq!(
717                 // SAFETY: We assume this to be sound for the sake of this test,
718                 // which will fail, here, in miri, if the safety precondition of
719                 // `offset_of` is not satisfied.
720                 unsafe {
721                     #[allow(clippy::as_conversions)]
722                     let offset = (trailing.as_ptr() as *mut u8).offset_from(ptr.as_ptr() as *mut _);
723                     offset
724                 },
725                 isize::try_from(OFFSET).unwrap(),
726             );
727 
728             // SAFETY: Points to a valid value by construction.
729             #[allow(clippy::undocumented_unsafe_blocks, clippy::as_conversions)]
730             // Clippy false positive
731             let trailing: usize = trailing
732                 .iter()
733                 .map(|ptr| unsafe { core::ptr::read_unaligned(ptr.as_ptr()) } as usize)
734                 .sum();
735 
736             assert_eq!(trailing, n);
737         }
738 
739         test_trailing_slice::<0, 16>();
740         test_trailing_slice::<1, 17>();
741         test_trailing_slice::<2, 18>();
742     }
743     #[test]
744     fn test_ptr_inner_clone() {
745         let mut x = 0u8;
746         let p = PtrInner::from_mut(&mut x);
747         #[allow(clippy::clone_on_copy)]
748         let p2 = p.clone();
749         assert_eq!(p.as_non_null(), p2.as_non_null());
750     }
751 }
752