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