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