Coverage Report

Created: 2026-06-30 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerocopy-0.8.52/src/ref.rs
Line
Count
Source
1
// SPDX-License-Identifier: BSD-2-Clause OR Apache-2.0 OR MIT
2
//
3
// Copyright 2024 The Fuchsia Authors
4
//
5
// Licensed under the 2-Clause BSD License <LICENSE-BSD or
6
// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
7
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
8
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
9
// This file may not be copied, modified, or distributed except according to
10
// those terms.
11
use super::*;
12
use crate::pointer::{
13
    BecauseInvariantsEq, BecauseMutationCompatible, MutationCompatible, TransmuteFromPtr,
14
};
15
16
mod def {
17
    use core::marker::PhantomData;
18
19
    use crate::{
20
        ByteSlice, ByteSliceMut, CloneableByteSlice, CopyableByteSlice, IntoByteSlice,
21
        IntoByteSliceMut,
22
    };
23
24
    /// A typed reference derived from a byte slice.
25
    ///
26
    /// A `Ref<B, T>` is a reference to a `T` which is stored in a byte slice, `B`.
27
    /// Unlike a native reference (`&T` or `&mut T`), `Ref<B, T>` has the same
28
    /// mutability as the byte slice it was constructed from (`B`).
29
    ///
30
    /// # Examples
31
    ///
32
    /// `Ref` can be used to treat a sequence of bytes as a structured type, and
33
    /// to read and write the fields of that type as if the byte slice reference
34
    /// were simply a reference to that type.
35
    ///
36
    /// ```rust
37
    /// use zerocopy::*;
38
    /// # use zerocopy_derive::*;
39
    ///
40
    /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
41
    /// #[repr(C)]
42
    /// struct UdpHeader {
43
    ///     src_port: [u8; 2],
44
    ///     dst_port: [u8; 2],
45
    ///     length: [u8; 2],
46
    ///     checksum: [u8; 2],
47
    /// }
48
    ///
49
    /// #[derive(FromBytes, IntoBytes, KnownLayout, Immutable, Unaligned)]
50
    /// #[repr(C, packed)]
51
    /// struct UdpPacket {
52
    ///     header: UdpHeader,
53
    ///     body: [u8],
54
    /// }
55
    ///
56
    /// impl UdpPacket {
57
    ///     pub fn parse<B: ByteSlice>(bytes: B) -> Option<Ref<B, UdpPacket>> {
58
    ///         Ref::from_bytes(bytes).ok()
59
    ///     }
60
    /// }
61
    /// ```
62
    pub struct Ref<B, T: ?Sized>(
63
        // INVARIANTS: The referent (via `.deref`, `.deref_mut`, `.into`) byte
64
        // slice is aligned to `T`'s alignment and its size corresponds to a
65
        // valid size for `T`.
66
        B,
67
        PhantomData<T>,
68
    );
69
70
    impl<B, T: ?Sized> Ref<B, T> {
71
        /// Constructs a new `Ref`.
72
        ///
73
        /// # Safety
74
        ///
75
        /// `bytes` dereferences (via [`deref`], [`deref_mut`], and [`into`]) to
76
        /// a byte slice which is aligned to `T`'s alignment and whose size is a
77
        /// valid size for `T`.
78
        ///
79
        /// [`deref`]: core::ops::Deref::deref
80
        /// [`deref_mut`]: core::ops::DerefMut::deref_mut
81
        /// [`into`]: core::convert::Into::into
82
0
        pub(crate) unsafe fn new_unchecked(bytes: B) -> Ref<B, T> {
83
            // INVARIANTS: The caller has promised that `bytes`'s referent is
84
            // validly-aligned and has a valid size.
85
0
            Ref(bytes, PhantomData)
86
0
        }
Unexecuted instantiation: <zerocopy::ref::def::Ref<_, _>>::new_unchecked
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Request>>>>::new_unchecked
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Response>>>>::new_unchecked
87
    }
88
89
    impl<B: ByteSlice, T: ?Sized> Ref<B, T> {
90
        /// Access the byte slice as a [`ByteSlice`].
91
        ///
92
        /// # Safety
93
        ///
94
        /// The caller promises not to call methods on the returned
95
        /// [`ByteSlice`] other than `ByteSlice` methods (for example, via
96
        /// `Any::downcast_ref`).
97
        ///
98
        /// `as_byte_slice` promises to return a `ByteSlice` whose referent is
99
        /// validly-aligned for `T` and has a valid size for `T`.
100
0
        pub(crate) unsafe fn as_byte_slice(&self) -> &impl ByteSlice {
101
            // INVARIANTS: The caller promises not to call methods other than
102
            // those on `ByteSlice`. Since `B: ByteSlice`, dereference stability
103
            // guarantees that calling `ByteSlice` methods will not change the
104
            // address or length of `self.0`'s referent.
105
            //
106
            // SAFETY: By invariant on `self.0`, the alignment and size
107
            // post-conditions are upheld.
108
0
            &self.0
109
0
        }
Unexecuted instantiation: <zerocopy::ref::def::Ref<_, _>>::as_byte_slice
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Request>>>>::as_byte_slice
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Response>>>>::as_byte_slice
110
    }
111
112
    impl<B: ByteSliceMut, T: ?Sized> Ref<B, T> {
113
        /// Access the byte slice as a [`ByteSliceMut`].
114
        ///
115
        /// # Safety
116
        ///
117
        /// The caller promises not to call methods on the returned
118
        /// [`ByteSliceMut`] other than `ByteSliceMut` methods (for example, via
119
        /// `Any::downcast_mut`).
120
        ///
121
        /// `as_byte_slice` promises to return a `ByteSlice` whose referent is
122
        /// validly-aligned for `T` and has a valid size for `T`.
123
0
        pub(crate) unsafe fn as_byte_slice_mut(&mut self) -> &mut impl ByteSliceMut {
124
            // INVARIANTS: The caller promises not to call methods other than
125
            // those on `ByteSliceMut`. Since `B: ByteSlice`, dereference
126
            // stability guarantees that calling `ByteSlice` methods will not
127
            // change the address or length of `self.0`'s referent.
128
            //
129
            // SAFETY: By invariant on `self.0`, the alignment and size
130
            // post-conditions are upheld.
131
0
            &mut self.0
132
0
        }
133
    }
134
135
    impl<'a, B: IntoByteSlice<'a>, T: ?Sized> Ref<B, T> {
136
        /// Access the byte slice as an [`IntoByteSlice`].
137
        ///
138
        /// # Safety
139
        ///
140
        /// The caller promises not to call methods on the returned
141
        /// [`IntoByteSlice`] other than `IntoByteSlice` methods (for example,
142
        /// via `Any::downcast_ref`).
143
        ///
144
        /// `as_byte_slice` promises to return a `ByteSlice` whose referent is
145
        /// validly-aligned for `T` and has a valid size for `T`.
146
0
        pub(crate) unsafe fn into_byte_slice(self) -> impl IntoByteSlice<'a> {
147
            // INVARIANTS: The caller promises not to call methods other than
148
            // those on `IntoByteSlice`. Since `B: ByteSlice`, dereference
149
            // stability guarantees that calling `ByteSlice` methods will not
150
            // change the address or length of `self.0`'s referent.
151
            //
152
            // SAFETY: By invariant on `self.0`, the alignment and size
153
            // post-conditions are upheld.
154
0
            self.0
155
0
        }
156
    }
157
158
    impl<'a, B: IntoByteSliceMut<'a>, T: ?Sized> Ref<B, T> {
159
        /// Access the byte slice as an [`IntoByteSliceMut`].
160
        ///
161
        /// # Safety
162
        ///
163
        /// The caller promises not to call methods on the returned
164
        /// [`IntoByteSliceMut`] other than `IntoByteSliceMut` methods (for
165
        /// example, via `Any::downcast_mut`).
166
        ///
167
        /// `as_byte_slice` promises to return a `ByteSlice` whose referent is
168
        /// validly-aligned for `T` and has a valid size for `T`.
169
0
        pub(crate) unsafe fn into_byte_slice_mut(self) -> impl IntoByteSliceMut<'a> {
170
            // INVARIANTS: The caller promises not to call methods other than
171
            // those on `IntoByteSliceMut`. Since `B: ByteSlice`, dereference
172
            // stability guarantees that calling `ByteSlice` methods will not
173
            // change the address or length of `self.0`'s referent.
174
            //
175
            // SAFETY: By invariant on `self.0`, the alignment and size
176
            // post-conditions are upheld.
177
0
            self.0
178
0
        }
179
    }
180
181
    impl<B: CloneableByteSlice + Clone, T: ?Sized> Clone for Ref<B, T> {
182
        #[inline]
183
0
        fn clone(&self) -> Ref<B, T> {
184
            // INVARIANTS: Since `B: CloneableByteSlice`, `self.0.clone()` has
185
            // the same address and length as `self.0`. Since `self.0` upholds
186
            // the field invariants, so does `self.0.clone()`.
187
0
            Ref(self.0.clone(), PhantomData)
188
0
        }
189
    }
190
191
    // INVARIANTS: Since `B: CopyableByteSlice`, the copied `Ref`'s `.0` has the
192
    // same address and length as the original `Ref`'s `.0`. Since the original
193
    // upholds the field invariants, so does the copy.
194
    impl<B: CopyableByteSlice + Copy, T: ?Sized> Copy for Ref<B, T> {}
195
}
196
197
#[allow(unreachable_pub)] // This is a false positive on our MSRV toolchain.
198
pub use def::Ref;
199
200
use crate::pointer::{
201
    invariant::{Aligned, BecauseExclusive, Initialized, Unaligned, Valid},
202
    BecauseRead, PtrInner,
203
};
204
205
impl<B, T> Ref<B, T>
206
where
207
    B: ByteSlice,
208
{
209
    #[must_use = "has no side effects"]
210
0
    pub(crate) fn sized_from(bytes: B) -> Result<Ref<B, T>, CastError<B, T>> {
211
0
        if bytes.len() != mem::size_of::<T>() {
212
0
            return Err(SizeError::new(bytes).into());
213
0
        }
214
0
        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
215
0
            return Err(err.with_src(bytes).into());
216
0
        }
217
218
        // SAFETY: We just validated size and alignment.
219
0
        Ok(unsafe { Ref::new_unchecked(bytes) })
220
0
    }
Unexecuted instantiation: <zerocopy::ref::def::Ref<_, _>>::sized_from
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Request>>>>::sized_from
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Response>>>>::sized_from
221
}
222
223
impl<B, T> Ref<B, T>
224
where
225
    B: SplitByteSlice,
226
{
227
    #[must_use = "has no side effects"]
228
0
    pub(crate) fn sized_from_prefix(bytes: B) -> Result<(Ref<B, T>, B), CastError<B, T>> {
229
0
        if bytes.len() < mem::size_of::<T>() {
230
0
            return Err(SizeError::new(bytes).into());
231
0
        }
232
0
        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
233
0
            return Err(err.with_src(bytes).into());
234
0
        }
235
0
        let (bytes, suffix) = bytes.split_at(mem::size_of::<T>()).map_err(
236
            #[inline(always)]
237
0
            |b| SizeError::new(b).into(),
238
0
        )?;
239
        // SAFETY: We just validated alignment and that `bytes` is at least as
240
        // large as `T`. `bytes.split_at(mem::size_of::<T>())?` ensures that the
241
        // new `bytes` is exactly the size of `T`. By safety postcondition on
242
        // `SplitByteSlice::split_at` we can rely on `split_at` to produce the
243
        // correct `bytes` and `suffix`.
244
0
        let r = unsafe { Ref::new_unchecked(bytes) };
245
0
        Ok((r, suffix))
246
0
    }
247
248
    #[must_use = "has no side effects"]
249
0
    pub(crate) fn sized_from_suffix(bytes: B) -> Result<(B, Ref<B, T>), CastError<B, T>> {
250
0
        let bytes_len = bytes.len();
251
0
        let split_at = if let Some(split_at) = bytes_len.checked_sub(mem::size_of::<T>()) {
252
0
            split_at
253
        } else {
254
0
            return Err(SizeError::new(bytes).into());
255
        };
256
0
        let (prefix, bytes) = bytes.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
257
0
        if let Err(err) = util::validate_aligned_to::<_, T>(bytes.deref()) {
258
0
            return Err(err.with_src(bytes).into());
259
0
        }
260
        // SAFETY: Since `split_at` is defined as `bytes_len - size_of::<T>()`,
261
        // the `bytes` which results from `let (prefix, bytes) =
262
        // bytes.split_at(split_at)?` has length `size_of::<T>()`. After
263
        // constructing `bytes`, we validate that it has the proper alignment.
264
        // By safety postcondition on `SplitByteSlice::split_at` we can rely on
265
        // `split_at` to produce the correct `prefix` and `bytes`.
266
0
        let r = unsafe { Ref::new_unchecked(bytes) };
267
0
        Ok((prefix, r))
268
0
    }
269
}
270
271
impl<B, T> Ref<B, T>
272
where
273
    B: ByteSlice,
274
    T: KnownLayout + Immutable + ?Sized,
275
{
276
    /// Constructs a `Ref` from a byte slice.
277
    ///
278
    /// If the length of `source` is not a [valid size of `T`][valid-size], or
279
    /// if `source` is not appropriately aligned for `T`, this returns `Err`. If
280
    /// [`T: Unaligned`][t-unaligned], you can [infallibly discard the alignment
281
    /// error][size-error-from].
282
    ///
283
    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
284
    ///
285
    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
286
    /// [t-unaligned]: crate::Unaligned
287
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
288
    /// [slice-dst]: KnownLayout#dynamically-sized-types
289
    ///
290
    /// # Compile-Time Assertions
291
    ///
292
    /// This method cannot yet be used on unsized types whose dynamically-sized
293
    /// component is zero-sized. Attempting to use this method on such types
294
    /// results in a compile-time assertion error; e.g.:
295
    ///
296
    /// ```compile_fail,E0080
297
    /// use zerocopy::*;
298
    /// # use zerocopy_derive::*;
299
    ///
300
    /// #[derive(Immutable, KnownLayout)]
301
    /// #[repr(C)]
302
    /// struct ZSTy {
303
    ///     leading_sized: u16,
304
    ///     trailing_dst: [()],
305
    /// }
306
    ///
307
    /// let _ = Ref::<_, ZSTy>::from_bytes(&b"UU"[..]); // ⚠ Compile Error!
308
    /// ```
309
    #[must_use = "has no side effects"]
310
    #[inline]
311
0
    pub fn from_bytes(source: B) -> Result<Ref<B, T>, CastError<B, T>> {
312
0
        static_assert_dst_is_not_zst!(T);
313
0
        if let Err(e) =
314
0
            Ptr::from_ref(source.deref()).try_cast_into_no_leftover::<T, BecauseImmutable>(None)
315
        {
316
0
            return Err(e.with_src(()).with_src(source));
317
0
        }
318
        // SAFETY: `try_cast_into_no_leftover` validates size and alignment.
319
0
        Ok(unsafe { Ref::new_unchecked(source) })
320
0
    }
321
}
322
323
impl<B, T> Ref<B, T>
324
where
325
    B: SplitByteSlice,
326
    T: KnownLayout + Immutable + ?Sized,
327
{
328
    /// Constructs a `Ref` from the prefix of a byte slice.
329
    ///
330
    /// This method computes the [largest possible size of `T`][valid-size] that
331
    /// can fit in the leading bytes of `source`, then attempts to return both a
332
    /// `Ref` to those bytes, and a reference to the remaining bytes. If there
333
    /// are insufficient bytes, or if `source` is not appropriately aligned,
334
    /// this returns `Err`. If [`T: Unaligned`][t-unaligned], you can
335
    /// [infallibly discard the alignment error][size-error-from].
336
    ///
337
    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
338
    ///
339
    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
340
    /// [t-unaligned]: crate::Unaligned
341
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
342
    /// [slice-dst]: KnownLayout#dynamically-sized-types
343
    ///
344
    /// # Compile-Time Assertions
345
    ///
346
    /// This method cannot yet be used on unsized types whose dynamically-sized
347
    /// component is zero-sized. Attempting to use this method on such types
348
    /// results in a compile-time assertion error; e.g.:
349
    ///
350
    /// ```compile_fail,E0080
351
    /// use zerocopy::*;
352
    /// # use zerocopy_derive::*;
353
    ///
354
    /// #[derive(Immutable, KnownLayout)]
355
    /// #[repr(C)]
356
    /// struct ZSTy {
357
    ///     leading_sized: u16,
358
    ///     trailing_dst: [()],
359
    /// }
360
    ///
361
    /// let _ = Ref::<_, ZSTy>::from_prefix(&b"UU"[..]); // ⚠ Compile Error!
362
    /// ```
363
    #[must_use = "has no side effects"]
364
    #[inline]
365
0
    pub fn from_prefix(source: B) -> Result<(Ref<B, T>, B), CastError<B, T>> {
366
0
        static_assert_dst_is_not_zst!(T);
367
0
        let remainder = match Ptr::from_ref(source.deref())
368
0
            .try_cast_into::<T, BecauseImmutable>(CastType::Prefix, None)
369
        {
370
0
            Ok((_, remainder)) => remainder,
371
0
            Err(e) => {
372
0
                return Err(e.with_src(()).with_src(source));
373
            }
374
        };
375
376
        // SAFETY: `remainder` is constructed as a subset of `source`, and so it
377
        // cannot have a larger size than `source`. Both of their `len` methods
378
        // measure bytes (`source` deref's to `[u8]`, and `remainder` is a
379
        // `Ptr<[u8]>`), so `source.len() >= remainder.len()`. Thus, this cannot
380
        // underflow.
381
        #[allow(unstable_name_collisions)]
382
0
        let split_at = unsafe { source.len().unchecked_sub(remainder.len()) };
383
0
        let (bytes, suffix) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
384
        // SAFETY: `try_cast_into` validates size and alignment, and returns a
385
        // `split_at` that indicates how many bytes of `source` correspond to a
386
        // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we
387
        // can rely on `split_at` to produce the correct `source` and `suffix`.
388
0
        let r = unsafe { Ref::new_unchecked(bytes) };
389
0
        Ok((r, suffix))
390
0
    }
391
392
    /// Constructs a `Ref` from the suffix of a byte slice.
393
    ///
394
    /// This method computes the [largest possible size of `T`][valid-size] that
395
    /// can fit in the trailing bytes of `source`, then attempts to return both
396
    /// a `Ref` to those bytes, and a reference to the preceding bytes. If there
397
    /// are insufficient bytes, or if that suffix of `source` is not
398
    /// appropriately aligned, this returns `Err`. If [`T:
399
    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
400
    /// error][size-error-from].
401
    ///
402
    /// `T` may be a sized type, a slice, or a [slice DST][slice-dst].
403
    ///
404
    /// [valid-size]: crate::KnownLayout#what-is-a-valid-size
405
    /// [t-unaligned]: crate::Unaligned
406
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
407
    /// [slice-dst]: KnownLayout#dynamically-sized-types
408
    ///
409
    /// # Compile-Time Assertions
410
    ///
411
    /// This method cannot yet be used on unsized types whose dynamically-sized
412
    /// component is zero-sized. Attempting to use this method on such types
413
    /// results in a compile-time assertion error; e.g.:
414
    ///
415
    /// ```compile_fail,E0080
416
    /// use zerocopy::*;
417
    /// # use zerocopy_derive::*;
418
    ///
419
    /// #[derive(Immutable, KnownLayout)]
420
    /// #[repr(C)]
421
    /// struct ZSTy {
422
    ///     leading_sized: u16,
423
    ///     trailing_dst: [()],
424
    /// }
425
    ///
426
    /// let _ = Ref::<_, ZSTy>::from_suffix(&b"UU"[..]); // ⚠ Compile Error!
427
    /// ```
428
    #[must_use = "has no side effects"]
429
    #[inline]
430
0
    pub fn from_suffix(source: B) -> Result<(B, Ref<B, T>), CastError<B, T>> {
431
0
        static_assert_dst_is_not_zst!(T);
432
0
        let remainder = match Ptr::from_ref(source.deref())
433
0
            .try_cast_into::<T, BecauseImmutable>(CastType::Suffix, None)
434
        {
435
0
            Ok((_, remainder)) => remainder,
436
0
            Err(e) => {
437
0
                let e = e.with_src(());
438
0
                return Err(e.with_src(source));
439
            }
440
        };
441
442
0
        let split_at = remainder.len();
443
0
        let (prefix, bytes) = source.split_at(split_at).map_err(|b| SizeError::new(b).into())?;
444
        // SAFETY: `try_cast_into` validates size and alignment, and returns a
445
        // `split_at` that indicates how many bytes of `source` correspond to a
446
        // valid `T`. By safety postcondition on `SplitByteSlice::split_at` we
447
        // can rely on `split_at` to produce the correct `prefix` and `bytes`.
448
0
        let r = unsafe { Ref::new_unchecked(bytes) };
449
0
        Ok((prefix, r))
450
0
    }
451
}
452
453
impl<B, T> Ref<B, T>
454
where
455
    B: ByteSlice,
456
    T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,
457
{
458
    /// Constructs a `Ref` from the given bytes with DST length equal to `count`
459
    /// without copying.
460
    ///
461
    /// This method attempts to return a `Ref` to the prefix of `source`
462
    /// interpreted as a `T` with `count` trailing elements, and a reference to
463
    /// the remaining bytes. If the length of `source` is not equal to the size
464
    /// of `Self` with `count` elements, or if `source` is not appropriately
465
    /// aligned, this returns `Err`. If [`T: Unaligned`][t-unaligned], you can
466
    /// [infallibly discard the alignment error][size-error-from].
467
    ///
468
    /// [t-unaligned]: crate::Unaligned
469
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
470
    ///
471
    /// # Compile-Time Assertions
472
    ///
473
    /// This method cannot yet be used on unsized types whose dynamically-sized
474
    /// component is zero-sized. Attempting to use this method on such types
475
    /// results in a compile-time assertion error; e.g.:
476
    ///
477
    /// ```compile_fail,E0080
478
    /// use zerocopy::*;
479
    /// # use zerocopy_derive::*;
480
    ///
481
    /// #[derive(Immutable, KnownLayout)]
482
    /// #[repr(C)]
483
    /// struct ZSTy {
484
    ///     leading_sized: u16,
485
    ///     trailing_dst: [()],
486
    /// }
487
    ///
488
    /// let _ = Ref::<_, ZSTy>::from_bytes_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
489
    /// ```
490
    #[inline]
491
0
    pub fn from_bytes_with_elems(source: B, count: usize) -> Result<Ref<B, T>, CastError<B, T>> {
492
0
        static_assert_dst_is_not_zst!(T);
493
0
        let expected_len = match T::size_for_metadata(count) {
494
0
            Some(len) => len,
495
0
            None => return Err(SizeError::new(source).into()),
496
        };
497
0
        if source.len() != expected_len {
498
0
            return Err(SizeError::new(source).into());
499
0
        }
500
0
        Self::from_bytes(source)
501
0
    }
502
}
503
504
impl<B, T> Ref<B, T>
505
where
506
    B: SplitByteSlice,
507
    T: KnownLayout<PointerMetadata = usize> + Immutable + ?Sized,
508
{
509
    /// Constructs a `Ref` from the prefix of the given bytes with DST
510
    /// length equal to `count` without copying.
511
    ///
512
    /// This method attempts to return a `Ref` to the prefix of `source`
513
    /// interpreted as a `T` with `count` trailing elements, and a reference to
514
    /// the remaining bytes. If there are insufficient bytes, or if `source` is
515
    /// not appropriately aligned, this returns `Err`. If [`T:
516
    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
517
    /// error][size-error-from].
518
    ///
519
    /// [t-unaligned]: crate::Unaligned
520
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
521
    ///
522
    /// # Compile-Time Assertions
523
    ///
524
    /// This method cannot yet be used on unsized types whose dynamically-sized
525
    /// component is zero-sized. Attempting to use this method on such types
526
    /// results in a compile-time assertion error; e.g.:
527
    ///
528
    /// ```compile_fail,E0080
529
    /// use zerocopy::*;
530
    /// # use zerocopy_derive::*;
531
    ///
532
    /// #[derive(Immutable, KnownLayout)]
533
    /// #[repr(C)]
534
    /// struct ZSTy {
535
    ///     leading_sized: u16,
536
    ///     trailing_dst: [()],
537
    /// }
538
    ///
539
    /// let _ = Ref::<_, ZSTy>::from_prefix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
540
    /// ```
541
    #[inline]
542
0
    pub fn from_prefix_with_elems(
543
0
        source: B,
544
0
        count: usize,
545
0
    ) -> Result<(Ref<B, T>, B), CastError<B, T>> {
546
0
        static_assert_dst_is_not_zst!(T);
547
0
        let expected_len = match T::size_for_metadata(count) {
548
0
            Some(len) => len,
549
0
            None => return Err(SizeError::new(source).into()),
550
        };
551
0
        let (prefix, bytes) = source.split_at(expected_len).map_err(SizeError::new)?;
552
0
        Self::from_bytes(prefix).map(move |l| (l, bytes))
553
0
    }
554
555
    /// Constructs a `Ref` from the suffix of the given bytes with DST length
556
    /// equal to `count` without copying.
557
    ///
558
    /// This method attempts to return a `Ref` to the suffix of `source`
559
    /// interpreted as a `T` with `count` trailing elements, and a reference to
560
    /// the preceding bytes. If there are insufficient bytes, or if that suffix
561
    /// of `source` is not appropriately aligned, this returns `Err`. If [`T:
562
    /// Unaligned`][t-unaligned], you can [infallibly discard the alignment
563
    /// error][size-error-from].
564
    ///
565
    /// [t-unaligned]: crate::Unaligned
566
    /// [size-error-from]: error/struct.SizeError.html#method.from-1
567
    ///
568
    /// # Compile-Time Assertions
569
    ///
570
    /// This method cannot yet be used on unsized types whose dynamically-sized
571
    /// component is zero-sized. Attempting to use this method on such types
572
    /// results in a compile-time assertion error; e.g.:
573
    ///
574
    /// ```compile_fail,E0080
575
    /// use zerocopy::*;
576
    /// # use zerocopy_derive::*;
577
    ///
578
    /// #[derive(Immutable, KnownLayout)]
579
    /// #[repr(C)]
580
    /// struct ZSTy {
581
    ///     leading_sized: u16,
582
    ///     trailing_dst: [()],
583
    /// }
584
    ///
585
    /// let _ = Ref::<_, ZSTy>::from_suffix_with_elems(&b"UU"[..], 42); // ⚠ Compile Error!
586
    /// ```
587
    #[inline]
588
0
    pub fn from_suffix_with_elems(
589
0
        source: B,
590
0
        count: usize,
591
0
    ) -> Result<(B, Ref<B, T>), CastError<B, T>> {
592
0
        static_assert_dst_is_not_zst!(T);
593
0
        let expected_len = match T::size_for_metadata(count) {
594
0
            Some(len) => len,
595
0
            None => return Err(SizeError::new(source).into()),
596
        };
597
0
        let split_at = if let Some(split_at) = source.len().checked_sub(expected_len) {
598
0
            split_at
599
        } else {
600
0
            return Err(SizeError::new(source).into());
601
        };
602
        // SAFETY: The preceding `source.len().checked_sub(expected_len)`
603
        // guarantees that `split_at` is in-bounds.
604
0
        let (bytes, suffix) = unsafe { source.split_at_unchecked(split_at) };
605
0
        Self::from_bytes(suffix).map(move |l| (bytes, l))
606
0
    }
607
}
608
609
impl<'a, B, T> Ref<B, T>
610
where
611
    B: 'a + IntoByteSlice<'a>,
612
    T: FromBytes + KnownLayout + Immutable + ?Sized,
613
{
614
    /// Converts this `Ref` into a reference.
615
    ///
616
    /// `into_ref` consumes the `Ref`, and returns a reference to `T`.
617
    ///
618
    /// Note: this is an associated function, which means that you have to call
619
    /// it as `Ref::into_ref(r)` instead of `r.into_ref()`. This is so that
620
    /// there is no conflict with a method on the inner type.
621
    #[must_use = "has no side effects"]
622
    #[inline(always)]
623
0
    pub fn into_ref(r: Self) -> &'a T {
624
        // Presumably unreachable, since we've guarded each constructor of `Ref`.
625
0
        static_assert_dst_is_not_zst!(T);
626
627
        // SAFETY: We don't call any methods on `b` other than those provided by
628
        // `IntoByteSlice`.
629
0
        let b = unsafe { r.into_byte_slice() };
630
0
        let b = b.into_byte_slice();
631
632
0
        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
633
0
            let ptr = Ptr::from_ref(b);
634
            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
635
            // `b`'s size is equal to `size_of::<T>()`.
636
0
            let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
637
638
            // SAFETY: None of the preceding transformations modifies the
639
            // address of the pointer, and by invariant on `r`, we know that it
640
            // is validly-aligned.
641
0
            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
642
0
            return ptr.as_ref();
643
0
        }
644
645
        // PANICS: By post-condition on `into_byte_slice`, `b`'s size and
646
        // alignment are valid for `T`. By post-condition, `b.into_byte_slice()`
647
        // produces a byte slice with identical address and length to that
648
        // produced by `b.deref()`.
649
0
        let ptr = Ptr::from_ref(b.into_byte_slice())
650
0
            .try_cast_into_no_leftover::<T, BecauseImmutable>(None)
651
0
            .expect("zerocopy internal error: into_ref should be infallible");
652
0
        let ptr = ptr.recall_validity();
653
0
        ptr.as_ref()
654
0
    }
655
}
656
657
impl<'a, B, T> Ref<B, T>
658
where
659
    B: 'a + IntoByteSliceMut<'a>,
660
    T: FromBytes + IntoBytes + KnownLayout + ?Sized,
661
{
662
    /// Converts this `Ref` into a mutable reference.
663
    ///
664
    /// `into_mut` consumes the `Ref`, and returns a mutable reference to `T`.
665
    ///
666
    /// Note: this is an associated function, which means that you have to call
667
    /// it as `Ref::into_mut(r)` instead of `r.into_mut()`. This is so that
668
    /// there is no conflict with a method on the inner type.
669
    #[must_use = "has no side effects"]
670
    #[inline(always)]
671
0
    pub fn into_mut(r: Self) -> &'a mut T {
672
        // Presumably unreachable, since we've guarded each constructor of `Ref`.
673
0
        static_assert_dst_is_not_zst!(T);
674
675
        // SAFETY: We don't call any methods on `b` other than those provided by
676
        // `IntoByteSliceMut`.
677
0
        let b = unsafe { r.into_byte_slice_mut() };
678
0
        let b = b.into_byte_slice_mut();
679
680
0
        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
681
0
            let ptr = Ptr::from_mut(b);
682
            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
683
            // `b`'s size is equal to `size_of::<T>()`.
684
0
            let ptr = unsafe {
685
0
                cast_for_sized::<
686
0
                    T,
687
0
                    _,
688
0
                    (BecauseRead, BecauseExclusive),
689
0
                    (BecauseMutationCompatible, BecauseInvariantsEq),
690
0
                >(ptr)
691
            };
692
693
            // SAFETY: None of the preceding transformations modifies the
694
            // address of the pointer, and by invariant on `r`, we know that it
695
            // is validly-aligned.
696
0
            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
697
0
            return ptr.as_mut();
698
0
        }
699
700
        // PANICS: By post-condition on `into_byte_slice_mut`, `b`'s size and
701
        // alignment are valid for `T`. By post-condition,
702
        // `b.into_byte_slice_mut()` produces a byte slice with identical
703
        // address and length to that produced by `b.deref_mut()`.
704
0
        let ptr = Ptr::from_mut(b.into_byte_slice_mut())
705
0
            .try_cast_into_no_leftover::<T, BecauseExclusive>(None)
706
0
            .expect("zerocopy internal error: into_ref should be infallible");
707
0
        let ptr = ptr.recall_validity::<_, (_, (_, _))>();
708
0
        ptr.as_mut()
709
0
    }
710
}
711
712
impl<B, T> Ref<B, T>
713
where
714
    B: ByteSlice,
715
    T: ?Sized,
716
{
717
    /// Gets the underlying bytes.
718
    ///
719
    /// Note: this is an associated function, which means that you have to call
720
    /// it as `Ref::bytes(r)` instead of `r.bytes()`. This is so that there is
721
    /// no conflict with a method on the inner type.
722
    #[inline]
723
0
    pub fn bytes(r: &Self) -> &[u8] {
724
        // SAFETY: We don't call any methods on `b` other than those provided by
725
        // `ByteSlice`.
726
0
        unsafe { r.as_byte_slice().deref() }
727
0
    }
728
}
729
730
impl<B, T> Ref<B, T>
731
where
732
    B: ByteSliceMut,
733
    T: ?Sized,
734
{
735
    /// Gets the underlying bytes mutably.
736
    ///
737
    /// Note: this is an associated function, which means that you have to call
738
    /// it as `Ref::bytes_mut(r)` instead of `r.bytes_mut()`. This is so that
739
    /// there is no conflict with a method on the inner type.
740
    #[inline]
741
0
    pub fn bytes_mut(r: &mut Self) -> &mut [u8] {
742
        // SAFETY: We don't call any methods on `b` other than those provided by
743
        // `ByteSliceMut`.
744
0
        unsafe { r.as_byte_slice_mut().deref_mut() }
745
0
    }
746
}
747
748
impl<B, T> Ref<B, T>
749
where
750
    B: ByteSlice,
751
    T: FromBytes,
752
{
753
    /// Reads a copy of `T`.
754
    ///
755
    /// Note: this is an associated function, which means that you have to call
756
    /// it as `Ref::read(r)` instead of `r.read()`. This is so that there is no
757
    /// conflict with a method on the inner type.
758
    #[must_use = "has no side effects"]
759
    #[inline]
760
0
    pub fn read(r: &Self) -> T {
761
        // SAFETY: We don't call any methods on `b` other than those provided by
762
        // `ByteSlice`.
763
0
        let b = unsafe { r.as_byte_slice() };
764
765
        // SAFETY: By postcondition on `as_byte_slice`, we know that `b` is a
766
        // valid size and alignment for `T`. By safety invariant on `ByteSlice`,
767
        // we know that this is preserved via `.deref()`. Because `T:
768
        // FromBytes`, it is sound to interpret these bytes as a `T`.
769
0
        unsafe { ptr::read(b.deref().as_ptr().cast::<T>()) }
770
0
    }
Unexecuted instantiation: <zerocopy::ref::def::Ref<_, _>>::read
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Request>>>>::read
Unexecuted instantiation: <zerocopy::ref::def::Ref<&[u8], zerocopy::wrappers::Unalign<core::mem::maybe_uninit::MaybeUninit<vm_migration::protocol::Response>>>>::read
771
}
772
773
impl<B, T> Ref<B, T>
774
where
775
    B: ByteSliceMut,
776
    T: IntoBytes,
777
{
778
    /// Writes the bytes of `t` and then forgets `t`.
779
    ///
780
    /// Note: this is an associated function, which means that you have to call
781
    /// it as `Ref::write(r, t)` instead of `r.write(t)`. This is so that there
782
    /// is no conflict with a method on the inner type.
783
    #[inline]
784
0
    pub fn write(r: &mut Self, t: T) {
785
        // SAFETY: We don't call any methods on `b` other than those provided by
786
        // `ByteSliceMut`.
787
0
        let b = unsafe { r.as_byte_slice_mut() };
788
789
        // SAFETY: By postcondition on `as_byte_slice_mut`, we know that `b` is
790
        // a valid size and alignment for `T`. By safety invariant on
791
        // `ByteSlice`, we know that this is preserved via `.deref()`. Writing
792
        // `t` to the buffer will allow all of the bytes of `t` to be accessed
793
        // as a `[u8]`, but because `T: IntoBytes`, we know that this is sound.
794
0
        unsafe { ptr::write(b.deref_mut().as_mut_ptr().cast::<T>(), t) }
795
0
    }
796
}
797
798
impl<B, T> Deref for Ref<B, T>
799
where
800
    B: ByteSlice,
801
    T: FromBytes + KnownLayout + Immutable + ?Sized,
802
{
803
    type Target = T;
804
    #[inline]
805
0
    fn deref(&self) -> &T {
806
        // Presumably unreachable, since we've guarded each constructor of `Ref`.
807
0
        static_assert_dst_is_not_zst!(T);
808
809
        // SAFETY: We don't call any methods on `b` other than those provided by
810
        // `ByteSlice`.
811
0
        let b = unsafe { self.as_byte_slice() };
812
0
        let b = b.deref();
813
814
0
        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
815
0
            let ptr = Ptr::from_ref(b);
816
            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
817
            // `b`'s size is equal to `size_of::<T>()`.
818
0
            let ptr = unsafe { cast_for_sized::<T, _, _, _>(ptr) };
819
820
            // SAFETY: None of the preceding transformations modifies the
821
            // address of the pointer, and by invariant on `r`, we know that it
822
            // is validly-aligned.
823
0
            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
824
0
            return ptr.as_ref();
825
0
        }
826
827
        // PANICS: By postcondition on `as_byte_slice`, `b`'s size and alignment
828
        // are valid for `T`, and by invariant on `ByteSlice`, these are
829
        // preserved through `.deref()`, so this `unwrap` will not panic.
830
0
        let ptr = Ptr::from_ref(b)
831
0
            .try_cast_into_no_leftover::<T, BecauseImmutable>(None)
832
0
            .expect("zerocopy internal error: Deref::deref should be infallible");
833
0
        let ptr = ptr.recall_validity();
834
0
        ptr.as_ref()
835
0
    }
836
}
837
838
impl<B, T> DerefMut for Ref<B, T>
839
where
840
    B: ByteSliceMut,
841
    // FIXME(#251): We can't remove `Immutable` here because it's required by
842
    // the impl of `Deref`, which is a super-trait of `DerefMut`. Maybe we can
843
    // add a separate inherent method for this?
844
    T: FromBytes + IntoBytes + KnownLayout + Immutable + ?Sized,
845
{
846
    #[inline]
847
0
    fn deref_mut(&mut self) -> &mut T {
848
        // Presumably unreachable, since we've guarded each constructor of `Ref`.
849
0
        static_assert_dst_is_not_zst!(T);
850
851
        // SAFETY: We don't call any methods on `b` other than those provided by
852
        // `ByteSliceMut`.
853
0
        let b = unsafe { self.as_byte_slice_mut() };
854
0
        let b = b.deref_mut();
855
856
0
        if let crate::layout::SizeInfo::Sized { .. } = T::LAYOUT.size_info {
857
0
            let ptr = Ptr::from_mut(b);
858
            // SAFETY: We just checked that `T: Sized`. By invariant on `r`,
859
            // `b`'s size is equal to `size_of::<T>()`.
860
0
            let ptr = unsafe {
861
0
                cast_for_sized::<
862
0
                    T,
863
0
                    _,
864
0
                    (BecauseRead, BecauseExclusive),
865
0
                    (BecauseMutationCompatible, BecauseInvariantsEq),
866
0
                >(ptr)
867
            };
868
869
            // SAFETY: None of the preceding transformations modifies the
870
            // address of the pointer, and by invariant on `r`, we know that it
871
            // is validly-aligned.
872
0
            let ptr = unsafe { ptr.assume_alignment::<Aligned>() };
873
0
            return ptr.as_mut();
874
0
        }
875
876
        // PANICS: By postcondition on `as_byte_slice_mut`, `b`'s size and
877
        // alignment are valid for `T`, and by invariant on `ByteSlice`, these
878
        // are preserved through `.deref_mut()`, so this `unwrap` will not
879
        // panic.
880
0
        let ptr = Ptr::from_mut(b)
881
0
            .try_cast_into_no_leftover::<T, BecauseExclusive>(None)
882
0
            .expect("zerocopy internal error: DerefMut::deref_mut should be infallible");
883
0
        let ptr = ptr.recall_validity::<_, (_, (_, BecauseExclusive))>();
884
0
        ptr.as_mut()
885
0
    }
886
}
887
888
impl<T, B> Display for Ref<B, T>
889
where
890
    B: ByteSlice,
891
    T: FromBytes + Display + KnownLayout + Immutable + ?Sized,
892
{
893
    #[inline]
894
0
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
895
0
        let inner: &T = self;
896
0
        inner.fmt(fmt)
897
0
    }
898
}
899
900
impl<T, B> Debug for Ref<B, T>
901
where
902
    B: ByteSlice,
903
    T: FromBytes + Debug + KnownLayout + Immutable + ?Sized,
904
{
905
    #[inline]
906
0
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
907
0
        let inner: &T = self;
908
0
        fmt.debug_tuple("Ref").field(&inner).finish()
909
0
    }
910
}
911
912
impl<T, B> Eq for Ref<B, T>
913
where
914
    B: ByteSlice,
915
    T: FromBytes + Eq + KnownLayout + Immutable + ?Sized,
916
{
917
}
918
919
impl<T, B> PartialEq for Ref<B, T>
920
where
921
    B: ByteSlice,
922
    T: FromBytes + PartialEq + KnownLayout + Immutable + ?Sized,
923
{
924
    #[inline]
925
0
    fn eq(&self, other: &Self) -> bool {
926
0
        self.deref().eq(other.deref())
927
0
    }
928
}
929
930
impl<T, B> Ord for Ref<B, T>
931
where
932
    B: ByteSlice,
933
    T: FromBytes + Ord + KnownLayout + Immutable + ?Sized,
934
{
935
    #[inline]
936
0
    fn cmp(&self, other: &Self) -> Ordering {
937
0
        let inner: &T = self;
938
0
        let other_inner: &T = other;
939
0
        inner.cmp(other_inner)
940
0
    }
941
}
942
943
impl<T, B> PartialOrd for Ref<B, T>
944
where
945
    B: ByteSlice,
946
    T: FromBytes + PartialOrd + KnownLayout + Immutable + ?Sized,
947
{
948
    #[inline]
949
0
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
950
0
        let inner: &T = self;
951
0
        let other_inner: &T = other;
952
0
        inner.partial_cmp(other_inner)
953
0
    }
954
}
955
956
/// # Safety
957
///
958
/// `T: Sized` and `ptr`'s referent must have size `size_of::<T>()`.
959
#[inline(always)]
960
0
unsafe fn cast_for_sized<'a, T, A, R, S>(
961
0
    ptr: Ptr<'a, [u8], (A, Aligned, Valid)>,
962
0
) -> Ptr<'a, T, (A, Unaligned, Valid)>
963
0
where
964
0
    T: FromBytes + KnownLayout + ?Sized,
965
0
    A: crate::invariant::Aliasing,
966
0
    [u8]: MutationCompatible<T, A, Initialized, Initialized, R>,
967
0
    T: TransmuteFromPtr<T, A, Initialized, Valid, crate::pointer::cast::IdCast, S>,
968
{
969
    use crate::pointer::cast::{Cast, Project};
970
971
    enum CastForSized {}
972
973
    // SAFETY: `CastForSized` is only used below with the input `ptr`, which the
974
    // caller promises has size `size_of::<T>()`. Thus, the referent produced in
975
    // this cast has the same size as `ptr`'s referent. All operations preserve
976
    // provenance.
977
    unsafe impl<T: ?Sized + KnownLayout> Project<[u8], T> for CastForSized {
978
        #[inline(always)]
979
0
        fn project(src: PtrInner<'_, [u8]>) -> *mut T {
980
0
            T::raw_from_ptr_len(
981
0
                src.as_non_null().cast(),
982
0
                <T::PointerMetadata as crate::PointerMetadata>::from_elem_count(0),
983
            )
984
0
            .as_ptr()
985
0
        }
986
    }
987
988
    // SAFETY: The `Project::project` impl preserves referent address.
989
    unsafe impl<T: ?Sized + KnownLayout> Cast<[u8], T> for CastForSized {}
990
991
0
    ptr.recall_validity::<Initialized, (_, (_, _))>()
992
0
        .cast::<_, CastForSized, _>()
993
0
        .recall_validity::<Valid, _>()
994
0
}
995
996
#[cfg(test)]
997
#[allow(clippy::assertions_on_result_states)]
998
mod tests {
999
    use core::convert::TryInto as _;
1000
1001
    use super::*;
1002
    use crate::util::testutil::*;
1003
1004
    #[test]
1005
    fn test_mut_slice_into_ref() {
1006
        // Prior to #1260/#1299, calling `into_ref` on a `&mut [u8]`-backed
1007
        // `Ref` was not supported.
1008
        let mut buf = [0u8];
1009
        let r = Ref::<&mut [u8], u8>::from_bytes(&mut buf).unwrap();
1010
        assert_eq!(Ref::into_ref(r), &0);
1011
    }
1012
1013
    #[test]
1014
    fn test_address() {
1015
        // Test that the `Deref` and `DerefMut` implementations return a
1016
        // reference which points to the right region of memory.
1017
1018
        let buf = [0];
1019
        let r = Ref::<_, u8>::from_bytes(&buf[..]).unwrap();
1020
        let buf_ptr = buf.as_ptr();
1021
        let deref_ptr: *const u8 = r.deref();
1022
        assert_eq!(buf_ptr, deref_ptr);
1023
1024
        let buf = [0];
1025
        let r = Ref::<_, [u8]>::from_bytes(&buf[..]).unwrap();
1026
        let buf_ptr = buf.as_ptr();
1027
        let deref_ptr = r.deref().as_ptr();
1028
        assert_eq!(buf_ptr, deref_ptr);
1029
    }
1030
1031
    // Verify that values written to a `Ref` are properly shared between the
1032
    // typed and untyped representations, that reads via `deref` and `read`
1033
    // behave the same, and that writes via `deref_mut` and `write` behave the
1034
    // same.
1035
    fn test_new_helper(mut r: Ref<&mut [u8], AU64>) {
1036
        // assert that the value starts at 0
1037
        assert_eq!(*r, AU64(0));
1038
        assert_eq!(Ref::read(&r), AU64(0));
1039
1040
        // Assert that values written to the typed value are reflected in the
1041
        // byte slice.
1042
        const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
1043
        *r = VAL1;
1044
        assert_eq!(Ref::bytes(&r), &VAL1.to_bytes());
1045
        *r = AU64(0);
1046
        Ref::write(&mut r, VAL1);
1047
        assert_eq!(Ref::bytes(&r), &VAL1.to_bytes());
1048
1049
        // Assert that values written to the byte slice are reflected in the
1050
        // typed value.
1051
        const VAL2: AU64 = AU64(!VAL1.0); // different from `VAL1`
1052
        Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.to_bytes()[..]);
1053
        assert_eq!(*r, VAL2);
1054
        assert_eq!(Ref::read(&r), VAL2);
1055
    }
1056
1057
    // Verify that values written to a `Ref` are properly shared between the
1058
    // typed and untyped representations; pass a value with `typed_len` `AU64`s
1059
    // backed by an array of `typed_len * 8` bytes.
1060
    fn test_new_helper_slice(mut r: Ref<&mut [u8], [AU64]>, typed_len: usize) {
1061
        // Assert that the value starts out zeroed.
1062
        assert_eq!(&*r, vec![AU64(0); typed_len].as_slice());
1063
1064
        // Check the backing storage is the exact same slice.
1065
        let untyped_len = typed_len * 8;
1066
        assert_eq!(Ref::bytes(&r).len(), untyped_len);
1067
        assert_eq!(Ref::bytes(&r).as_ptr(), r.as_ptr().cast::<u8>());
1068
1069
        // Assert that values written to the typed value are reflected in the
1070
        // byte slice.
1071
        const VAL1: AU64 = AU64(0xFF00FF00FF00FF00);
1072
        for typed in &mut *r {
1073
            *typed = VAL1;
1074
        }
1075
        assert_eq!(Ref::bytes(&r), VAL1.0.to_ne_bytes().repeat(typed_len).as_slice());
1076
1077
        // Assert that values written to the byte slice are reflected in the
1078
        // typed value.
1079
        const VAL2: AU64 = AU64(!VAL1.0); // different from VAL1
1080
        Ref::bytes_mut(&mut r).copy_from_slice(&VAL2.0.to_ne_bytes().repeat(typed_len));
1081
        assert!(r.iter().copied().all(|x| x == VAL2));
1082
    }
1083
1084
    #[test]
1085
    fn test_new_aligned_sized() {
1086
        // Test that a properly-aligned, properly-sized buffer works for new,
1087
        // new_from_prefix, and new_from_suffix, and that new_from_prefix and
1088
        // new_from_suffix return empty slices. Test that a properly-aligned
1089
        // buffer whose length is a multiple of the element size works for
1090
        // new_slice.
1091
1092
        // A buffer with an alignment of 8.
1093
        let mut buf = Align::<[u8; 8], AU64>::default();
1094
        // `buf.t` should be aligned to 8, so this should always succeed.
1095
        test_new_helper(Ref::<_, AU64>::from_bytes(&mut buf.t[..]).unwrap());
1096
        {
1097
            // In a block so that `r` and `suffix` don't live too long.
1098
            buf.set_default();
1099
            let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap();
1100
            assert!(suffix.is_empty());
1101
            test_new_helper(r);
1102
        }
1103
        {
1104
            buf.set_default();
1105
            let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap();
1106
            assert!(prefix.is_empty());
1107
            test_new_helper(r);
1108
        }
1109
1110
        // A buffer with alignment 8 and length 24. We choose this length very
1111
        // intentionally: if we instead used length 16, then the prefix and
1112
        // suffix lengths would be identical. In the past, we used length 16,
1113
        // which resulted in this test failing to discover the bug uncovered in
1114
        // #506.
1115
        let mut buf = Align::<[u8; 24], AU64>::default();
1116
        // `buf.t` should be aligned to 8 and have a length which is a multiple
1117
        // of `size_of::<AU64>()`, so this should always succeed.
1118
        test_new_helper_slice(Ref::<_, [AU64]>::from_bytes(&mut buf.t[..]).unwrap(), 3);
1119
        buf.set_default();
1120
        let r = Ref::<_, [AU64]>::from_bytes_with_elems(&mut buf.t[..], 3).unwrap();
1121
        test_new_helper_slice(r, 3);
1122
1123
        let ascending: [u8; 24] = (0..24).collect::<Vec<_>>().try_into().unwrap();
1124
        // 16 ascending bytes followed by 8 zeros.
1125
        let mut ascending_prefix = ascending;
1126
        ascending_prefix[16..].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
1127
        // 8 zeros followed by 16 ascending bytes.
1128
        let mut ascending_suffix = ascending;
1129
        ascending_suffix[..8].copy_from_slice(&[0, 0, 0, 0, 0, 0, 0, 0]);
1130
        {
1131
            buf.t = ascending_suffix;
1132
            let (r, suffix) = Ref::<_, [AU64]>::from_prefix_with_elems(&mut buf.t[..], 1).unwrap();
1133
            assert_eq!(suffix, &ascending[8..]);
1134
            test_new_helper_slice(r, 1);
1135
        }
1136
        {
1137
            buf.t = ascending_prefix;
1138
            let (prefix, r) = Ref::<_, [AU64]>::from_suffix_with_elems(&mut buf.t[..], 1).unwrap();
1139
            assert_eq!(prefix, &ascending[..16]);
1140
            test_new_helper_slice(r, 1);
1141
        }
1142
    }
1143
1144
    #[test]
1145
    fn test_new_oversized() {
1146
        // Test that a properly-aligned, overly-sized buffer works for
1147
        // `new_from_prefix` and `new_from_suffix`, and that they return the
1148
        // remainder and prefix of the slice respectively.
1149
1150
        let mut buf = Align::<[u8; 16], AU64>::default();
1151
        {
1152
            // In a block so that `r` and `suffix` don't live too long. `buf.t`
1153
            // should be aligned to 8, so this should always succeed.
1154
            let (r, suffix) = Ref::<_, AU64>::from_prefix(&mut buf.t[..]).unwrap();
1155
            assert_eq!(suffix.len(), 8);
1156
            test_new_helper(r);
1157
        }
1158
        {
1159
            buf.set_default();
1160
            // `buf.t` should be aligned to 8, so this should always succeed.
1161
            let (prefix, r) = Ref::<_, AU64>::from_suffix(&mut buf.t[..]).unwrap();
1162
            assert_eq!(prefix.len(), 8);
1163
            test_new_helper(r);
1164
        }
1165
    }
1166
1167
    #[test]
1168
    #[allow(clippy::cognitive_complexity)]
1169
    fn test_new_error() {
1170
        // Fail because the buffer is too large.
1171
1172
        // A buffer with an alignment of 8.
1173
        let buf = Align::<[u8; 16], AU64>::default();
1174
        // `buf.t` should be aligned to 8, so only the length check should fail.
1175
        assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
1176
1177
        // Fail because the buffer is too small.
1178
1179
        // A buffer with an alignment of 8.
1180
        let buf = Align::<[u8; 4], AU64>::default();
1181
        // `buf.t` should be aligned to 8, so only the length check should fail.
1182
        assert!(Ref::<_, AU64>::from_bytes(&buf.t[..]).is_err());
1183
        assert!(Ref::<_, AU64>::from_prefix(&buf.t[..]).is_err());
1184
        assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
1185
1186
        // Fail because the length is not a multiple of the element size.
1187
1188
        let buf = Align::<[u8; 12], AU64>::default();
1189
        // `buf.t` has length 12, but element size is 8.
1190
        assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[..]).is_err());
1191
1192
        // Fail because the buffer is too short.
1193
        let buf = Align::<[u8; 12], AU64>::default();
1194
        // `buf.t` has length 12, but the element size is 8 (and we're expecting
1195
        // two of them). For each function, we test with a length that would
1196
        // cause the size to overflow `usize`, and with a normal length that
1197
        // will fail thanks to the buffer being too short; these are different
1198
        // error paths, and while the error types are the same, the distinction
1199
        // shows up in code coverage metrics.
1200
        let n = (usize::MAX / mem::size_of::<AU64>()) + 1;
1201
        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], n).is_err());
1202
        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[..], 2).is_err());
1203
        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], n).is_err());
1204
        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], 2).is_err());
1205
        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], n).is_err());
1206
        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], 2).is_err());
1207
1208
        // Fail because the alignment is insufficient.
1209
1210
        // A buffer with an alignment of 8. An odd buffer size is chosen so that
1211
        // the last byte of the buffer has odd alignment.
1212
        let buf = Align::<[u8; 13], AU64>::default();
1213
        // Slicing from 1, we get a buffer with size 12 (so the length check
1214
        // should succeed) but an alignment of only 1, which is insufficient.
1215
        assert!(Ref::<_, AU64>::from_bytes(&buf.t[1..]).is_err());
1216
        assert!(Ref::<_, AU64>::from_prefix(&buf.t[1..]).is_err());
1217
        assert!(Ref::<_, [AU64]>::from_bytes(&buf.t[1..]).is_err());
1218
        assert!(Ref::<_, [AU64]>::from_bytes_with_elems(&buf.t[1..], 1).is_err());
1219
        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[1..], 1).is_err());
1220
        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[1..], 1).is_err());
1221
        // Slicing is unnecessary here because `new_from_suffix` uses the suffix
1222
        // of the slice, which has odd alignment.
1223
        assert!(Ref::<_, AU64>::from_suffix(&buf.t[..]).is_err());
1224
1225
        // Fail due to arithmetic overflow.
1226
1227
        let buf = Align::<[u8; 16], AU64>::default();
1228
        let unreasonable_len = usize::MAX / mem::size_of::<AU64>() + 1;
1229
        assert!(Ref::<_, [AU64]>::from_prefix_with_elems(&buf.t[..], unreasonable_len).is_err());
1230
        assert!(Ref::<_, [AU64]>::from_suffix_with_elems(&buf.t[..], unreasonable_len).is_err());
1231
    }
1232
1233
    #[test]
1234
    #[allow(unstable_name_collisions)]
1235
    #[allow(clippy::as_conversions)]
1236
    fn test_into_ref_mut() {
1237
        #[allow(unused)]
1238
        use crate::util::AsAddress as _;
1239
1240
        let mut buf = Align::<[u8; 8], u64>::default();
1241
        let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap();
1242
        let rf = Ref::into_ref(r);
1243
        assert_eq!(rf, &0u64);
1244
        let buf_addr = (&buf.t as *const [u8; 8]).addr();
1245
        assert_eq!((rf as *const u64).addr(), buf_addr);
1246
1247
        let r = Ref::<_, u64>::from_bytes(&mut buf.t[..]).unwrap();
1248
        let rf = Ref::into_mut(r);
1249
        assert_eq!(rf, &mut 0u64);
1250
        assert_eq!((rf as *mut u64).addr(), buf_addr);
1251
1252
        *rf = u64::MAX;
1253
        assert_eq!(buf.t, [0xFF; 8]);
1254
    }
1255
1256
    #[test]
1257
    fn test_display_debug() {
1258
        let buf = Align::<[u8; 8], u64>::default();
1259
        let r = Ref::<_, u64>::from_bytes(&buf.t[..]).unwrap();
1260
        assert_eq!(format!("{}", r), "0");
1261
        assert_eq!(format!("{:?}", r), "Ref(0)");
1262
1263
        let buf = Align::<[u8; 8], u64>::default();
1264
        let r = Ref::<_, [u64]>::from_bytes(&buf.t[..]).unwrap();
1265
        assert_eq!(format!("{:?}", r), "Ref([0])");
1266
    }
1267
1268
    #[test]
1269
    fn test_eq() {
1270
        let buf1 = 0_u64;
1271
        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1272
        let buf2 = 0_u64;
1273
        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1274
        assert_eq!(r1, r2);
1275
    }
1276
1277
    #[test]
1278
    fn test_ne() {
1279
        let buf1 = 0_u64;
1280
        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1281
        let buf2 = 1_u64;
1282
        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1283
        assert_ne!(r1, r2);
1284
    }
1285
1286
    #[test]
1287
    fn test_ord() {
1288
        let buf1 = 0_u64;
1289
        let r1 = Ref::<_, u64>::from_bytes(buf1.as_bytes()).unwrap();
1290
        let buf2 = 1_u64;
1291
        let r2 = Ref::<_, u64>::from_bytes(buf2.as_bytes()).unwrap();
1292
        assert!(r1 < r2);
1293
        assert_eq!(PartialOrd::partial_cmp(&r1, &r2), Some(Ordering::Less));
1294
        assert_eq!(Ord::cmp(&r1, &r2), Ordering::Less);
1295
    }
1296
}
1297
1298
#[cfg(all(test, __ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS))]
1299
mod benches {
1300
    use test::{self, Bencher};
1301
1302
    use super::*;
1303
    use crate::util::testutil::*;
1304
1305
    #[bench]
1306
    fn bench_from_bytes_sized(b: &mut Bencher) {
1307
        let buf = Align::<[u8; 8], AU64>::default();
1308
        // `buf.t` should be aligned to 8, so this should always succeed.
1309
        let bytes = &buf.t[..];
1310
        b.iter(|| test::black_box(Ref::<_, AU64>::from_bytes(test::black_box(bytes)).unwrap()));
1311
    }
1312
1313
    #[bench]
1314
    fn bench_into_ref_sized(b: &mut Bencher) {
1315
        let buf = Align::<[u8; 8], AU64>::default();
1316
        let bytes = &buf.t[..];
1317
        let r = Ref::<_, AU64>::from_bytes(bytes).unwrap();
1318
        b.iter(|| test::black_box(Ref::into_ref(test::black_box(r))));
1319
    }
1320
1321
    #[bench]
1322
    fn bench_into_mut_sized(b: &mut Bencher) {
1323
        let mut buf = Align::<[u8; 8], AU64>::default();
1324
        let buf = &mut buf.t[..];
1325
        let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap();
1326
        b.iter(move || {
1327
            // SAFETY: The preceding `from_bytes` succeeded, and so we know that
1328
            // `buf` is validly-aligned and has the correct length.
1329
            let r = unsafe { Ref::<&mut [u8], AU64>::new_unchecked(&mut *buf) };
1330
            test::black_box(Ref::into_mut(test::black_box(r)));
1331
        });
1332
    }
1333
1334
    #[bench]
1335
    fn bench_deref_sized(b: &mut Bencher) {
1336
        let buf = Align::<[u8; 8], AU64>::default();
1337
        let bytes = &buf.t[..];
1338
        let r = Ref::<_, AU64>::from_bytes(bytes).unwrap();
1339
        b.iter(|| {
1340
            let temp = test::black_box(r);
1341
            test::black_box(temp.deref());
1342
        });
1343
    }
1344
1345
    #[bench]
1346
    fn bench_deref_mut_sized(b: &mut Bencher) {
1347
        let mut buf = Align::<[u8; 8], AU64>::default();
1348
        let buf = &mut buf.t[..];
1349
        let _ = Ref::<_, AU64>::from_bytes(&mut *buf).unwrap();
1350
        b.iter(|| {
1351
            // SAFETY: The preceding `from_bytes` succeeded, and so we know that
1352
            // `buf` is validly-aligned and has the correct length.
1353
            let r = unsafe { Ref::<&mut [u8], AU64>::new_unchecked(&mut *buf) };
1354
            let mut temp = test::black_box(r);
1355
            test::black_box(temp.deref_mut());
1356
        });
1357
    }
1358
}