Coverage Report

Created: 2025-07-23 06:18

/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
}