/rust/registry/src/index.crates.io-6f17d22bba15001f/zerocopy-0.8.14/src/byte_slice.rs
Line | Count | Source (jump to first uncovered line) |
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 | | //! Traits for types that encapsulate a `[u8]`. |
10 | | //! |
11 | | //! These traits are used to bound the `B` parameter of [`Ref`]. |
12 | | |
13 | | use core::{ |
14 | | cell, |
15 | | ops::{Deref, DerefMut}, |
16 | | }; |
17 | | |
18 | | #[cfg(doc)] |
19 | | use crate::Ref; |
20 | | |
21 | | // For each trait polyfill, as soon as the corresponding feature is stable, the |
22 | | // polyfill import will be unused because method/function resolution will prefer |
23 | | // the inherent method/function over a trait method/function. Thus, we suppress |
24 | | // the `unused_imports` warning. |
25 | | // |
26 | | // See the documentation on `util::polyfills` for more information. |
27 | | #[allow(unused_imports)] |
28 | | use crate::util::polyfills::{self, NonNullExt as _, NumExt as _}; |
29 | | |
30 | | /// A mutable or immutable reference to a byte slice. |
31 | | /// |
32 | | /// `ByteSlice` abstracts over the mutability of a byte slice reference, and is |
33 | | /// implemented for various special reference types such as |
34 | | /// [`Ref<[u8]>`](core::cell::Ref) and [`RefMut<[u8]>`](core::cell::RefMut). |
35 | | /// |
36 | | /// # Safety |
37 | | /// |
38 | | /// Implementations of `ByteSlice` must promise that their implementations of |
39 | | /// [`Deref`] and [`DerefMut`] are "stable". In particular, given `B: ByteSlice` |
40 | | /// and `b: B`, two calls, each to either `b.deref()` or `b.deref_mut()`, must |
41 | | /// return a byte slice with the same address and length. This must hold even if |
42 | | /// the two calls are separated by an arbitrary sequence of calls to methods on |
43 | | /// `ByteSlice`, [`ByteSliceMut`], [`IntoByteSlice`], or [`IntoByteSliceMut`], |
44 | | /// or on their super-traits. This does *not* need to hold if the two calls are |
45 | | /// separated by any method calls, field accesses, or field modifications *other |
46 | | /// than* those from these traits. |
47 | | /// |
48 | | /// Note that this also implies that, given `b: B`, the address and length |
49 | | /// cannot be modified via objects other than `b`, either on the same thread or |
50 | | /// on another thread. |
51 | | pub unsafe trait ByteSlice: Deref<Target = [u8]> + Sized {} |
52 | | |
53 | | /// A mutable reference to a byte slice. |
54 | | /// |
55 | | /// `ByteSliceMut` abstracts over various ways of storing a mutable reference to |
56 | | /// a byte slice, and is implemented for various special reference types such as |
57 | | /// `RefMut<[u8]>`. |
58 | | /// |
59 | | /// `ByteSliceMut` is a shorthand for [`ByteSlice`] and [`DerefMut`]. |
60 | | pub trait ByteSliceMut: ByteSlice + DerefMut {} |
61 | | impl<B: ByteSlice + DerefMut> ByteSliceMut for B {} |
62 | | |
63 | | /// A [`ByteSlice`] which can be copied without violating dereference stability. |
64 | | /// |
65 | | /// # Safety |
66 | | /// |
67 | | /// If `B: CopyableByteSlice`, then the dereference stability properties |
68 | | /// required by [`ByteSlice`] (see that trait's safety documentation) do not |
69 | | /// only hold regarding two calls to `b.deref()` or `b.deref_mut()`, but also |
70 | | /// hold regarding `c.deref()` or `c.deref_mut()`, where `c` is produced by |
71 | | /// copying `b`. |
72 | | pub unsafe trait CopyableByteSlice: ByteSlice + Copy + CloneableByteSlice {} |
73 | | |
74 | | /// A [`ByteSlice`] which can be cloned without violating dereference stability. |
75 | | /// |
76 | | /// # Safety |
77 | | /// |
78 | | /// If `B: CloneableByteSlice`, then the dereference stability properties |
79 | | /// required by [`ByteSlice`] (see that trait's safety documentation) do not |
80 | | /// only hold regarding two calls to `b.deref()` or `b.deref_mut()`, but also |
81 | | /// hold regarding `c.deref()` or `c.deref_mut()`, where `c` is produced by |
82 | | /// `b.clone()`, `b.clone().clone()`, etc. |
83 | | pub unsafe trait CloneableByteSlice: ByteSlice + Clone {} |
84 | | |
85 | | /// A [`ByteSlice`] that can be split in two. |
86 | | /// |
87 | | /// # Safety |
88 | | /// |
89 | | /// Unsafe code may depend for its soundness on the assumption that `split_at` |
90 | | /// and `split_at_unchecked` are implemented correctly. In particular, given `B: |
91 | | /// SplitByteSlice` and `b: B`, if `b.deref()` returns a byte slice with address |
92 | | /// `addr` and length `len`, then if `split <= len`, both of these |
93 | | /// invocations: |
94 | | /// - `b.split_at(split)` |
95 | | /// - `b.split_at_unchecked(split)` |
96 | | /// |
97 | | /// ...will return `(first, second)` such that: |
98 | | /// - `first`'s address is `addr` and its length is `split` |
99 | | /// - `second`'s address is `addr + split` and its length is `len - split` |
100 | | pub unsafe trait SplitByteSlice: ByteSlice { |
101 | | /// Attempts to split `self` at the midpoint. |
102 | | /// |
103 | | /// `s.split_at(mid)` returns `Ok((s[..mid], s[mid..]))` if `mid <= |
104 | | /// s.deref().len()` and otherwise returns `Err(s)`. |
105 | | /// |
106 | | /// # Safety |
107 | | /// |
108 | | /// Unsafe code may rely on this function correctly implementing the above |
109 | | /// functionality. |
110 | | #[inline] |
111 | 589 | fn split_at(self, mid: usize) -> Result<(Self, Self), Self> { |
112 | 589 | if mid <= self.deref().len() { |
113 | | // SAFETY: Above, we ensure that `mid <= self.deref().len()`. By |
114 | | // invariant on `ByteSlice`, a supertrait of `SplitByteSlice`, |
115 | | // `.deref()` is guranteed to be "stable"; i.e., it will always |
116 | | // dereference to a byte slice of the same address and length. Thus, |
117 | | // we can be sure that the above precondition remains satisfied |
118 | | // through the call to `split_at_unchecked`. |
119 | 589 | unsafe { Ok(self.split_at_unchecked(mid)) } |
120 | | } else { |
121 | 0 | Err(self) |
122 | | } |
123 | 589 | } <&[u8] as zerocopy::byte_slice::SplitByteSlice>::split_at Line | Count | Source | 111 | 589 | fn split_at(self, mid: usize) -> Result<(Self, Self), Self> { | 112 | 589 | if mid <= self.deref().len() { | 113 | | // SAFETY: Above, we ensure that `mid <= self.deref().len()`. By | 114 | | // invariant on `ByteSlice`, a supertrait of `SplitByteSlice`, | 115 | | // `.deref()` is guranteed to be "stable"; i.e., it will always | 116 | | // dereference to a byte slice of the same address and length. Thus, | 117 | | // we can be sure that the above precondition remains satisfied | 118 | | // through the call to `split_at_unchecked`. | 119 | 589 | unsafe { Ok(self.split_at_unchecked(mid)) } | 120 | | } else { | 121 | 0 | Err(self) | 122 | | } | 123 | 589 | } |
Unexecuted instantiation: <_ as zerocopy::byte_slice::SplitByteSlice>::split_at Unexecuted instantiation: <&[u8] as zerocopy::byte_slice::SplitByteSlice>::split_at |
124 | | |
125 | | /// Splits the slice at the midpoint, possibly omitting bounds checks. |
126 | | /// |
127 | | /// `s.split_at_unchecked(mid)` returns `s[..mid]` and `s[mid..]`. |
128 | | /// |
129 | | /// # Safety |
130 | | /// |
131 | | /// `mid` must not be greater than `self.deref().len()`. |
132 | | /// |
133 | | /// # Panics |
134 | | /// |
135 | | /// Implementations of this method may choose to perform a bounds check and |
136 | | /// panic if `mid > self.deref().len()`. They may also panic for any other |
137 | | /// reason. Since it is optional, callers must not rely on this behavior for |
138 | | /// soundness. |
139 | | #[must_use] |
140 | | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self); |
141 | | } |
142 | | |
143 | | /// A shorthand for [`SplitByteSlice`] and [`ByteSliceMut`]. |
144 | | pub trait SplitByteSliceMut: SplitByteSlice + ByteSliceMut {} |
145 | | impl<B: SplitByteSlice + ByteSliceMut> SplitByteSliceMut for B {} |
146 | | |
147 | | #[allow(clippy::missing_safety_doc)] // There's a `Safety` section on `into_byte_slice`. |
148 | | /// A [`ByteSlice`] that conveys no ownership, and so can be converted into a |
149 | | /// byte slice. |
150 | | /// |
151 | | /// Some `ByteSlice` types (notably, the standard library's [`Ref`] type) convey |
152 | | /// ownership, and so they cannot soundly be moved by-value into a byte slice |
153 | | /// type (`&[u8]`). Some methods in this crate's API (such as [`Ref::into_ref`]) |
154 | | /// are only compatible with `ByteSlice` types without these ownership |
155 | | /// semantics. |
156 | | /// |
157 | | /// [`Ref`]: core::cell::Ref |
158 | | pub unsafe trait IntoByteSlice<'a>: ByteSlice { |
159 | | /// Coverts `self` into a `&[u8]`. |
160 | | /// |
161 | | /// # Safety |
162 | | /// |
163 | | /// The returned reference has the same address and length as `self.deref()` |
164 | | /// and `self.deref_mut()`. |
165 | | /// |
166 | | /// Note that, combined with the safety invariant on [`ByteSlice`], this |
167 | | /// safety invariant implies that the returned reference is "stable" in the |
168 | | /// sense described in the `ByteSlice` docs. |
169 | | fn into_byte_slice(self) -> &'a [u8]; |
170 | | } |
171 | | |
172 | | #[allow(clippy::missing_safety_doc)] // There's a `Safety` section on `into_byte_slice_mut`. |
173 | | /// A [`ByteSliceMut`] that conveys no ownership, and so can be converted into a |
174 | | /// mutable byte slice. |
175 | | /// |
176 | | /// Some `ByteSliceMut` types (notably, the standard library's [`RefMut`] type) |
177 | | /// convey ownership, and so they cannot soundly be moved by-value into a byte |
178 | | /// slice type (`&mut [u8]`). Some methods in this crate's API (such as |
179 | | /// [`Ref::into_mut`]) are only compatible with `ByteSliceMut` types without |
180 | | /// these ownership semantics. |
181 | | /// |
182 | | /// [`RefMut`]: core::cell::RefMut |
183 | | pub unsafe trait IntoByteSliceMut<'a>: IntoByteSlice<'a> + ByteSliceMut { |
184 | | /// Coverts `self` into a `&mut [u8]`. |
185 | | /// |
186 | | /// # Safety |
187 | | /// |
188 | | /// The returned reference has the same address and length as `self.deref()` |
189 | | /// and `self.deref_mut()`. |
190 | | /// |
191 | | /// Note that, combined with the safety invariant on [`ByteSlice`], this |
192 | | /// safety invariant implies that the returned reference is "stable" in the |
193 | | /// sense described in the `ByteSlice` docs. |
194 | | fn into_byte_slice_mut(self) -> &'a mut [u8]; |
195 | | } |
196 | | |
197 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
198 | | #[allow(clippy::undocumented_unsafe_blocks)] |
199 | | unsafe impl ByteSlice for &[u8] {} |
200 | | |
201 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
202 | | #[allow(clippy::undocumented_unsafe_blocks)] |
203 | | unsafe impl CopyableByteSlice for &[u8] {} |
204 | | |
205 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
206 | | #[allow(clippy::undocumented_unsafe_blocks)] |
207 | | unsafe impl CloneableByteSlice for &[u8] {} |
208 | | |
209 | | // SAFETY: This delegates to `polyfills:split_at_unchecked`, which is documented |
210 | | // to correctly split `self` into two slices at the given `mid` point. |
211 | | unsafe impl SplitByteSlice for &[u8] { |
212 | | #[inline] |
213 | 589 | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { |
214 | 589 | // SAFETY: By contract on caller, `mid` is not greater than |
215 | 589 | // `bytes.len()`. |
216 | 589 | unsafe { (<[u8]>::get_unchecked(self, ..mid), <[u8]>::get_unchecked(self, mid..)) } |
217 | 589 | } <&[u8] as zerocopy::byte_slice::SplitByteSlice>::split_at_unchecked Line | Count | Source | 213 | 589 | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { | 214 | 589 | // SAFETY: By contract on caller, `mid` is not greater than | 215 | 589 | // `bytes.len()`. | 216 | 589 | unsafe { (<[u8]>::get_unchecked(self, ..mid), <[u8]>::get_unchecked(self, mid..)) } | 217 | 589 | } |
Unexecuted instantiation: <&[u8] as zerocopy::byte_slice::SplitByteSlice>::split_at_unchecked Unexecuted instantiation: <&[u8] as zerocopy::byte_slice::SplitByteSlice>::split_at_unchecked |
218 | | } |
219 | | |
220 | | // SAFETY: See inline. |
221 | | unsafe impl<'a> IntoByteSlice<'a> for &'a [u8] { |
222 | | #[inline(always)] |
223 | 0 | fn into_byte_slice(self) -> &'a [u8] { |
224 | 0 | // SAFETY: It would be patently insane to implement `<Deref for |
225 | 0 | // &[u8]>::deref` as anything other than `fn deref(&self) -> &[u8] { |
226 | 0 | // *self }`. Assuming this holds, then `self` is stable as required by |
227 | 0 | // `into_byte_slice`. |
228 | 0 | self |
229 | 0 | } |
230 | | } |
231 | | |
232 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
233 | | #[allow(clippy::undocumented_unsafe_blocks)] |
234 | | unsafe impl ByteSlice for &mut [u8] {} |
235 | | |
236 | | // SAFETY: This delegates to `polyfills:split_at_mut_unchecked`, which is |
237 | | // documented to correctly split `self` into two slices at the given `mid` |
238 | | // point. |
239 | | unsafe impl SplitByteSlice for &mut [u8] { |
240 | | #[inline] |
241 | 0 | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { |
242 | | use core::slice::from_raw_parts_mut; |
243 | | |
244 | | // `l_ptr` is non-null, because `self` is non-null, by invariant on |
245 | | // `&mut [u8]`. |
246 | 0 | let l_ptr = self.as_mut_ptr(); |
247 | 0 |
|
248 | 0 | // SAFETY: By contract on caller, `mid` is not greater than |
249 | 0 | // `self.len()`. |
250 | 0 | let r_ptr = unsafe { l_ptr.add(mid) }; |
251 | 0 |
|
252 | 0 | let l_len = mid; |
253 | 0 |
|
254 | 0 | // SAFETY: By contract on caller, `mid` is not greater than |
255 | 0 | // `self.len()`. |
256 | 0 | // |
257 | 0 | // TODO(#67): Remove this allow. See NumExt for more details. |
258 | 0 | #[allow(unstable_name_collisions, clippy::incompatible_msrv)] |
259 | 0 | let r_len = unsafe { self.len().unchecked_sub(mid) }; |
260 | 0 |
|
261 | 0 | // SAFETY: These invocations of `from_raw_parts_mut` satisfy its |
262 | 0 | // documented safety preconditions [1]: |
263 | 0 | // - The data `l_ptr` and `r_ptr` are valid for both reads and writes of |
264 | 0 | // `l_len` and `r_len` bytes, respectively, and they are trivially |
265 | 0 | // aligned. In particular: |
266 | 0 | // - The entire memory range of each slice is contained within a |
267 | 0 | // single allocated object, since `l_ptr` and `r_ptr` are both |
268 | 0 | // derived from within the address range of `self`. |
269 | 0 | // - Both `l_ptr` and `r_ptr` are non-null and trivially aligned. |
270 | 0 | // `self` is non-null by invariant on `&mut [u8]`, and the |
271 | 0 | // operations that derive `l_ptr` and `r_ptr` from `self` do not |
272 | 0 | // nullify either pointer. |
273 | 0 | // - The data `l_ptr` and `r_ptr` point to `l_len` and `r_len`, |
274 | 0 | // respectively, consecutive properly initialized values of type `u8`. |
275 | 0 | // This is true for `self` by invariant on `&mut [u8]`, and remains |
276 | 0 | // true for these two sub-slices of `self`. |
277 | 0 | // - The memory referenced by the returned slice cannot be accessed |
278 | 0 | // through any other pointer (not derived from the return value) for |
279 | 0 | // the duration of lifetime `'a``, because: |
280 | 0 | // - `split_at_unchecked` consumes `self` (which is not `Copy`), |
281 | 0 | // - `split_at_unchecked` does not exfiltrate any references to this |
282 | 0 | // memory, besides those references returned below, |
283 | 0 | // - the returned slices are non-overlapping. |
284 | 0 | // - The individual sizes of the sub-slices of `self` are no larger than |
285 | 0 | // `isize::MAX`, because their combined sizes are no larger than |
286 | 0 | // `isize::MAX`, by invariant on `self`. |
287 | 0 | // |
288 | 0 | // [1] https://doc.rust-lang.org/std/slice/fn.from_raw_parts_mut.html#safety |
289 | 0 | unsafe { (from_raw_parts_mut(l_ptr, l_len), from_raw_parts_mut(r_ptr, r_len)) } |
290 | 0 | } |
291 | | } |
292 | | |
293 | | // SAFETY: See inline. |
294 | | unsafe impl<'a> IntoByteSlice<'a> for &'a mut [u8] { |
295 | | #[inline(always)] |
296 | 0 | fn into_byte_slice(self) -> &'a [u8] { |
297 | 0 | // SAFETY: It would be patently insane to implement `<Deref for &mut |
298 | 0 | // [u8]>::deref` as anything other than `fn deref(&self) -> &[u8] { |
299 | 0 | // *self }`. Assuming this holds, then `self` is stable as required by |
300 | 0 | // `into_byte_slice`. |
301 | 0 | self |
302 | 0 | } |
303 | | } |
304 | | |
305 | | // SAFETY: See inline. |
306 | | unsafe impl<'a> IntoByteSliceMut<'a> for &'a mut [u8] { |
307 | | #[inline(always)] |
308 | 0 | fn into_byte_slice_mut(self) -> &'a mut [u8] { |
309 | 0 | // SAFETY: It would be patently insane to implement `<DerefMut for &mut |
310 | 0 | // [u8]>::deref` as anything other than `fn deref_mut(&mut self) -> &mut |
311 | 0 | // [u8] { *self }`. Assuming this holds, then `self` is stable as |
312 | 0 | // required by `into_byte_slice_mut`. |
313 | 0 | self |
314 | 0 | } |
315 | | } |
316 | | |
317 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
318 | | #[allow(clippy::undocumented_unsafe_blocks)] |
319 | | unsafe impl ByteSlice for cell::Ref<'_, [u8]> {} |
320 | | |
321 | | // SAFETY: This delegates to stdlib implementation of `Ref::map_split`, which is |
322 | | // assumed to be correct, and `SplitByteSlice::split_at_unchecked`, which is |
323 | | // documented to correctly split `self` into two slices at the given `mid` |
324 | | // point. |
325 | | unsafe impl SplitByteSlice for cell::Ref<'_, [u8]> { |
326 | | #[inline] |
327 | 0 | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { |
328 | 0 | cell::Ref::map_split(self, |slice| |
329 | | // SAFETY: By precondition on caller, `mid` is not greater than |
330 | | // `slice.len()`. |
331 | 0 | unsafe { |
332 | 0 | SplitByteSlice::split_at_unchecked(slice, mid) |
333 | 0 | }) |
334 | 0 | } |
335 | | } |
336 | | |
337 | | // TODO(#429): Add a "SAFETY" comment and remove this `allow`. |
338 | | #[allow(clippy::undocumented_unsafe_blocks)] |
339 | | unsafe impl ByteSlice for cell::RefMut<'_, [u8]> {} |
340 | | |
341 | | // SAFETY: This delegates to stdlib implementation of `RefMut::map_split`, which |
342 | | // is assumed to be correct, and `SplitByteSlice::split_at_unchecked`, which is |
343 | | // documented to correctly split `self` into two slices at the given `mid` |
344 | | // point. |
345 | | unsafe impl SplitByteSlice for cell::RefMut<'_, [u8]> { |
346 | | #[inline] |
347 | 0 | unsafe fn split_at_unchecked(self, mid: usize) -> (Self, Self) { |
348 | 0 | cell::RefMut::map_split(self, |slice| |
349 | | // SAFETY: By precondition on caller, `mid` is not greater than |
350 | | // `slice.len()` |
351 | 0 | unsafe { |
352 | 0 | SplitByteSlice::split_at_unchecked(slice, mid) |
353 | 0 | }) |
354 | 0 | } |
355 | | } |