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