Coverage Report

Created: 2026-01-22 07:28

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