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