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