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