Coverage Report

Created: 2025-12-05 07:37

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