musli_zerocopy/
traits.rs

1//! Traits that apply to types which can safely interact with Müsli's zero copy
2//! system.
3//!
4//! Note that all of these traits are `unsafe`, and require care to implement.
5//! Please see their corresponding safety documentation or use the
6//! [`ZeroCopy`][derive@crate::ZeroCopy] derive.
7//!
8//! * [`ZeroCopy`] for types which can safely be coerced from a [`Ref<T>`] to
9//!   `&T` or `&mut T`.
10//! * [`UnsizedZeroCopy`] for types which can safely be coerced from an
11//!   [`Ref<T>`] where `T: ?Sized` to `&T` or `&mut T`.
12//! * [`ZeroSized`] for types which can be ignored when deriving
13//!   [`ZeroCopy`][derive@crate::ZeroCopy] using `#[zero_copy(ignore)]`.
14//!
15//! [`Ref<T>`]: crate::pointer::Ref
16
17#![allow(clippy::missing_safety_doc)]
18
19use core::array;
20use core::marker::PhantomData;
21use core::mem::{align_of, size_of, transmute};
22use core::num::Wrapping;
23use core::ptr::NonNull;
24use core::slice;
25use core::str;
26
27use crate::buf::{Buf, Padder, Validator, Visit};
28use crate::endian::ByteOrder;
29use crate::error::{Error, ErrorKind};
30use crate::pointer::{Pointee, Size};
31
32mod sealed {
33    use crate::ZeroCopy;
34
35    pub trait Sealed {}
36    impl Sealed for str {}
37    impl<T> Sealed for [T] where T: ZeroCopy {}
38}
39
40/// Trait governing which `P` in [`Ref<T>`] where `P: ?Sized` the wrapper can
41/// handle.
42///
43/// We only support slice-like, unaligned unsized types, such as `str` and
44/// `[u8]`. We can't support types such as `dyn Debug` because metadata is a
45/// vtable which can't be serialized.
46///
47/// [`Ref<T>`]: crate::pointer::Ref
48///
49/// # Safety
50///
51/// This can only be implemented by types that:
52/// * Can only be implemented for base types which can inhabit any bit-pattern.
53///   All though custom validation can be performed during coercion (such as for
54///   `str`).
55/// * Must only be implemented for types which are not padded (as per
56///   [`ZeroCopy::PADDED`]).
57///
58/// # Examples
59///
60/// ```
61/// use musli_zerocopy::OwnedBuf;
62///
63/// let mut buf = OwnedBuf::with_alignment::<u8>();
64///
65/// let bytes = buf.store_unsized(&b"Hello World!"[..]);
66/// let buf = buf.as_ref();
67/// assert_eq!(buf.load(bytes)?, b"Hello World!");
68/// # Ok::<_, musli_zerocopy::Error>(())
69/// ```
70pub unsafe trait UnsizedZeroCopy: self::sealed::Sealed + Pointee {
71    /// Alignment of the pointed-to data
72    const ALIGN: usize;
73
74    /// If the pointed-to data contains any padding.
75    const PADDED: bool;
76
77    /// Return a pointer to the base of the pointed-to value.
78    fn as_ptr(&self) -> *const u8;
79
80    /// Metadata associated with the unsized value that is embedded in the
81    /// pointer.
82    fn metadata(&self) -> Self::Metadata;
83
84    /// Apply padding as per the pointed-to value.
85    unsafe fn pad(&self, pad: &mut Padder<'_, Self>);
86
87    /// Validate the buffer with the given capacity and return the decoded
88    /// metadata.
89    unsafe fn validate_unsized<E, O>(
90        data: NonNull<u8>,
91        len: usize,
92        metadata: Self::Stored<O>,
93    ) -> Result<Self::Metadata, Error>
94    where
95        E: ByteOrder,
96        O: Size;
97
98    /// Construct a wide pointer from a pointer and its associated metadata.
99    ///
100    /// # Safety
101    ///
102    /// The caller is responsible for ensuring that the pointer is valid. The
103    /// base pointer `ptr` has to point to a region of memory that is
104    /// initialized per `P::Metadata` requirements. Practically that means it's
105    /// passed a call to [`validate_unsized()`].
106    ///
107    /// [`validate_unsized()`]: Self::validate_unsized
108    unsafe fn with_metadata(data: NonNull<u8>, metadata: Self::Metadata) -> *const Self;
109
110    /// Construct a wide mutable pointer from a pointer and its associated
111    /// metadata.
112    ///
113    /// # Safety
114    ///
115    /// The caller is responsible for ensuring that the pointer is valid. The
116    /// base pointer `ptr` has to point to a region of memory that is
117    /// initialized per `P::Metadata` requirements. Practically that means it's
118    /// passed a call to [`validate_unsized()`].
119    ///
120    /// [`validate_unsized()`]: Self::validate_unsized
121    unsafe fn with_metadata_mut(data: NonNull<u8>, metadata: Self::Metadata) -> *mut Self;
122}
123
124/// This is a marker trait that must be implemented for a type in order to use
125/// the `#[zero_copy(ignore)]` attribute when deriving the [`ZeroCopy`] trait.
126///
127/// Using the attribute incorrectly might lead to unsoundness.
128///
129/// # Safety
130///
131/// Any type implementing this trait must be zero-sized.
132///
133/// # Examples
134///
135/// Using `#[zero_copy(ignore)]` on generic fields that implements
136/// [`ZeroSized`]:
137///
138/// ```
139/// use musli_zerocopy::{ZeroCopy, ZeroSized};
140///
141/// #[derive(ZeroCopy)]
142/// #[repr(transparent)]
143/// struct Struct<T> where T: ZeroSized {
144///     #[zero_copy(ignore)]
145///     field: T,
146/// }
147/// ```
148///
149/// Types which derive [`ZeroCopy`] also implement [`ZeroSized`] if they are
150/// zero-sized:
151///
152/// ```
153/// use std::marker::PhantomData;
154/// use std::mem::size_of;
155///
156/// use musli_zerocopy::{ZeroCopy, ZeroSized};
157///
158/// #[derive(ZeroCopy)]
159/// #[repr(transparent)]
160/// struct Struct<T> where T: ZeroSized {
161///     #[zero_copy(ignore)]
162///     field: T,
163/// }
164///
165/// #[derive(ZeroCopy)]
166/// #[repr(transparent)]
167/// struct OtherStruct {
168///     #[zero_copy(ignore)]
169///     field: Struct<()>,
170/// }
171///
172/// fn assert_zero_sized<T: ZeroSized>() {
173///     assert_eq!(size_of::<T>(), 0);
174/// }
175///
176/// assert_zero_sized::<()>();
177/// assert_zero_sized::<PhantomData<u32>>();
178/// assert_zero_sized::<OtherStruct>();
179/// assert_zero_sized::<Struct<OtherStruct>>();
180/// ```
181pub unsafe trait ZeroSized {}
182
183/// [`ZeroCopy`] implementation for `Wrapping<T>`.
184///
185/// # Examples
186///
187/// ```
188/// use std::num::Wrapping;
189///
190/// use musli_zerocopy::{buf, Ref, ZeroCopy};
191///
192/// #[derive(ZeroCopy)]
193/// #[repr(C)]
194/// struct Struct {
195///     field: Wrapping<u32>,
196/// }
197///
198/// let zero = u32::to_ne_bytes(0);
199/// let zero = buf::aligned_buf::<u32>(&zero);
200/// let one = u32::to_ne_bytes(1);
201/// let one = buf::aligned_buf::<u32>(&one);
202///
203/// let st = zero.load(Ref::<Struct>::zero())?;
204/// assert_eq!(st.field.0, 0);
205///
206/// let st = one.load(Ref::<Struct>::zero())?;
207/// assert_eq!(st.field.0, 1);
208/// # Ok::<_, musli_zerocopy::Error>(())
209/// ```
210// SAFETY: `Wrapping<T>` is repr-transparent.
211unsafe impl<T> ZeroSized for Wrapping<T> where T: ZeroSized {}
212
213unsafe impl<T> ZeroCopy for Wrapping<T>
214where
215    T: ZeroCopy,
216{
217    const ANY_BITS: bool = T::ANY_BITS;
218    const PADDED: bool = T::PADDED;
219    const CAN_SWAP_BYTES: bool = T::CAN_SWAP_BYTES;
220
221    #[inline]
222    unsafe fn pad(padder: &mut Padder<'_, Self>) {
223        padder.pad::<T>();
224    }
225
226    #[inline]
227    unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error> {
228        validator.validate::<T>()
229    }
230
231    #[inline]
232    fn swap_bytes<E>(self) -> Self
233    where
234        E: ByteOrder,
235    {
236        Wrapping(T::swap_bytes::<E>(self.0))
237    }
238}
239
240/// `()` can be ignored as a zero-sized field.
241///
242/// # Examples
243///
244/// ```
245/// use musli_zerocopy::ZeroCopy;
246///
247/// #[derive(ZeroCopy)]
248/// #[repr(transparent)]
249/// struct Struct {
250///     #[zero_copy(ignore)]
251///     field: (),
252/// }
253/// ```
254// SAFETY: `()` is zero-sized.
255unsafe impl ZeroSized for () {}
256
257/// `[T; 0]` can be ignored as a zero-sized field.
258///
259/// # Examples
260///
261/// ```
262/// use musli_zerocopy::ZeroCopy;
263///
264/// #[derive(ZeroCopy)]
265/// #[repr(transparent)]
266/// struct Struct<T> {
267///     #[zero_copy(ignore)]
268///     field: [T; 0],
269/// }
270/// ```
271// SAFETY: `[T; 0]` is zero-sized.
272unsafe impl<T> ZeroSized for [T; 0] {}
273
274/// `PhantomData<T>` can be ignored as a zero-sized field.
275///
276/// # Examples
277///
278/// ```
279/// use std::marker::PhantomData;
280/// use musli_zerocopy::ZeroCopy;
281///
282/// #[derive(ZeroCopy)]
283/// #[repr(transparent)]
284/// struct Struct<T> {
285///     #[zero_copy(ignore)]
286///     field: PhantomData<T>,
287/// }
288/// ```
289// SAFETY: `PhantomData<T>` is zero-sized.
290unsafe impl<T: ?Sized> ZeroSized for PhantomData<T> {}
291
292/// Trait governing types can be safely coerced into a reference from a buffer.
293///
294/// It is not recommended to implement this trait manually, instead rely on the
295/// [`ZeroCopy`] derive.
296///
297/// [`ZeroCopy`]: derive@crate::ZeroCopy
298///
299/// # Safety
300///
301/// This can only be implemented correctly by types under certain conditions:
302/// * The type has a strict, well-defined layout like `repr(C)` or an enum with
303///   `repr(u32)`.
304/// * It's size and alignment must be known statically as per [`size_of`] and
305///   [`align_of`]. This excludes enums which are `#[repr(C)]` because for
306///   example their alignment depends on the range of values they can represent.
307///
308/// [`size_of`]: core::mem::size_of
309///
310/// # Notable types which cannot be `ZeroCopy`
311///
312/// Any type which does not have an explicit representation cannot implement
313/// `ZeroCopy`. Most Rust types use the Rust. Or `#[repr(Rust)]`. The Rust as a
314/// language is allowed to make arbitrary layout decisions for `#[repr(Rust)]`
315/// types.
316///
317/// The following is a list of common Rust types which *cannot* implements
318/// `ZeroCopy`, and the rationale for why:
319///
320/// * Non-zero sized tuples. Since tuples do not have a stable layout.
321/// * `Option<T>` since that is a `#[repr(Rust)]` type, except where [specific
322///   representation guarantees] are made such as with `Option<NonZero*>` types.
323///
324/// [specific representation guarantees]:
325///     https://doc.rust-lang.org/std/option/index.html#representation
326///
327/// # Examples
328///
329/// Using [`to_bytes`], [`from_bytes`], and [`from_bytes_mut`]:
330///
331/// [`to_bytes`]: Self::to_bytes
332/// [`from_bytes`]: Self::from_bytes
333/// [`from_bytes_mut`]: Self::from_bytes_mut
334///
335/// ```
336/// use musli_zerocopy::{buf, ZeroCopy};
337///
338/// #[derive(ZeroCopy, Debug, PartialEq)]
339/// #[repr(C)]
340/// struct Weapon {
341///     id: u8,
342///     damage: u32,
343/// }
344///
345/// let mut weapon = Weapon {
346///     id: 1,
347///     damage: 42u32,
348/// };
349///
350/// let original = weapon.to_bytes();
351///
352/// // Make a copy that we can play around with.
353/// let mut bytes = buf::aligned_buf::<Weapon>(original).into_owned();
354///
355/// assert_eq!(weapon.damage, 42);
356/// assert_eq!(&weapon, Weapon::from_bytes(&bytes[..])?);
357///
358/// # #[cfg(target_endian = "little")]
359/// assert_eq!(&bytes[..], &[1, 0, 0, 0, 42, 0, 0, 0]);
360/// Weapon::from_bytes_mut(&mut bytes[..])?.damage += 10;
361/// # #[cfg(target_endian = "little")]
362/// assert_eq!(&bytes[..], &[1, 0, 0, 0, 52, 0, 0, 0]);
363/// # Ok::<_, musli_zerocopy::Error>(())
364/// ```
365///
366/// Unsafely access an immutable reference by manually padding the struct using
367/// [`initialize_padding()`] and [`to_bytes_unchecked()`]:
368///
369/// [`initialize_padding()`]: Self::initialize_padding
370/// [`to_bytes_unchecked()`]: Self::to_bytes_unchecked
371///
372/// ```
373/// use musli_zerocopy::ZeroCopy;
374/// # #[derive(ZeroCopy, Debug, PartialEq)]
375/// # #[repr(C)]
376/// # struct Weapon { id: u8, damage: u32 }
377///
378/// let mut weapon = Weapon {
379///     id: 1,
380///     damage: 42u32,
381/// };
382///
383/// weapon.initialize_padding();
384///
385/// // SAFETY: Padding for the type has been initialized, and the type has not been moved since it was padded.
386/// let bytes = unsafe { weapon.to_bytes_unchecked() };
387/// # #[cfg(target_endian = "little")]
388/// assert_eq!(bytes, &[1, 0, 0, 0, 42, 0, 0, 0]);
389/// assert_eq!(Weapon::from_bytes(&bytes)?, &weapon);
390/// # Ok::<_, musli_zerocopy::Error>(())
391/// ```
392///
393/// Interacting with an [`OwnedBuf`]:
394///
395/// [`OwnedBuf`]: crate::buf::OwnedBuf
396///
397/// ```
398/// use musli_zerocopy::{OwnedBuf, ZeroCopy};
399///
400/// #[derive(Debug, PartialEq, ZeroCopy)]
401/// #[repr(C)]
402/// struct Custom { field: u32, #[zero_copy(ignore)] ignore: () }
403///
404/// let mut buf = OwnedBuf::new();
405/// let ptr = buf.store(&Custom { field: 42, ignore: () });
406/// buf.align_in_place();
407/// assert_eq!(buf.load(ptr)?, &Custom { field: 42, ignore: () });
408/// # Ok::<_, musli_zerocopy::Error>(())
409/// ```
410pub unsafe trait ZeroCopy: Sized {
411    /// Indicates if the type can inhabit all possible bit patterns within its
412    /// [`size_of::<Self>()`] bytes.
413    const ANY_BITS: bool;
414
415    /// Indicates if a type is padded.
416    const PADDED: bool;
417
418    /// Indicates if the type has a valid byte-ordered transformation.
419    ///
420    /// Most notably this is `false` for [`char`].
421    const CAN_SWAP_BYTES: bool;
422
423    /// Mark padding for the current type.
424    ///
425    /// The `this` receiver takes the current type as pointer instead of a
426    /// reference, because it might not be aligned in the case of packed types.
427    ///
428    /// # Safety
429    ///
430    /// The implementor is responsible for ensuring that every field is provided
431    /// to `padder`, including potentially hidden ones.
432    #[doc(hidden)]
433    unsafe fn pad(padder: &mut Padder<'_, Self>);
434
435    /// Validate the current type.
436    ///
437    /// # Safety
438    ///
439    /// This assumes that the provided validator is wrapping a buffer that is
440    /// appropriately sized and aligned.
441    #[doc(hidden)]
442    unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error>;
443
444    /// Ensure that the padding for the current value is initialized.
445    ///
446    /// This can be used in combination with [`to_bytes_unchecked()`] to relax
447    /// the borrowing requirement for [`to_bytes()`], but is `unsafe`.
448    ///
449    /// See the [type level documentation] for examples.
450    ///
451    /// [`to_bytes_unchecked()`]: Self::to_bytes_unchecked
452    /// [`to_bytes()`]: Self::to_bytes
453    /// [type level documentation]: Self
454    #[inline]
455    fn initialize_padding(&mut self) {
456        unsafe {
457            if Self::PADDED {
458                let ptr = NonNull::new_unchecked((self as *mut Self).cast::<u8>());
459                let mut padder = Padder::new(ptr);
460                Self::pad(&mut padder);
461                padder.remaining();
462            }
463        }
464    }
465
466    /// Convert a reference to a `ZeroCopy` type into bytes.
467    ///
468    /// This requires mutable access to `self`, since it must call
469    /// [`initialize_padding()`] to ensure that the returned buffer is fully
470    /// initialized.
471    ///
472    /// See the [type level documentation] for examples.
473    ///
474    /// [`initialize_padding()`]: Self::initialize_padding
475    /// [type level documentation]: Self
476    ///
477    /// # Examples
478    ///
479    /// ```
480    /// use musli_zerocopy::ZeroCopy;
481    ///
482    /// let mut value = 42u32;
483    /// assert_eq!(value.to_bytes(), 42u32.to_ne_bytes());
484    /// # Ok::<_, musli_zerocopy::Error>(())
485    /// ```
486    #[inline]
487    fn to_bytes(&mut self) -> &[u8] {
488        self.initialize_padding();
489
490        unsafe {
491            let ptr = (self as *mut Self).cast::<u8>();
492            slice::from_raw_parts(ptr, size_of::<Self>())
493        }
494    }
495
496    /// Convert a `ZeroCopy` type into bytes.
497    ///
498    /// This does not require mutable access to `self`, but the caller must
499    /// ensure that [`initialize_padding()`] has been called at some point before this
500    /// function and that the type that was padded has not been moved.
501    ///
502    /// See the [type level documentation] for examples.
503    ///
504    /// [`initialize_padding()`]: Self::initialize_padding
505    /// [type level documentation]: Self
506    #[inline]
507    unsafe fn to_bytes_unchecked(&self) -> &[u8] {
508        unsafe {
509            let ptr = (self as *const Self).cast::<u8>();
510            slice::from_raw_parts(ptr, size_of::<Self>())
511        }
512    }
513
514    /// Load bytes into a reference of `Self`.
515    ///
516    /// See the [type level documentation] for examples.
517    ///
518    /// [type level documentation]: Self
519    ///
520    /// # Errors
521    ///
522    /// This will ensure that `bytes` is aligned, appropriately sized, and valid
523    /// to inhabit `&Self`. Anything else will cause an [`Error`] detailing why
524    /// the conversion failed.
525    ///
526    /// # Examples
527    ///
528    /// ```
529    /// use musli_zerocopy::{OwnedBuf, ZeroCopy};
530    ///
531    /// let mut buf = OwnedBuf::new();
532    /// buf.extend_from_slice(&1u32.to_ne_bytes());
533    ///
534    /// let bytes: &[u8] = &buf[..];
535    /// assert_eq!(*u32::from_bytes(&bytes)?, 1);
536    /// # Ok::<_, musli_zerocopy::Error>(())
537    /// ```
538    #[inline]
539    fn from_bytes(bytes: &[u8]) -> Result<&Self, Error> {
540        Buf::new(bytes).load_at::<Self>(0)
541    }
542
543    /// Load bytes into a mutable reference of `Self`.
544    ///
545    /// See the [type level documentation] for examples.
546    ///
547    /// [type level documentation]: Self
548    ///
549    /// # Errors
550    ///
551    /// This will ensure that `bytes` is aligned, appropriately sized, and valid
552    /// to inhabit `&mut Self`. Anything else will cause an [`Error`] detailing
553    /// why the conversion failed.
554    ///
555    /// # Examples
556    ///
557    /// ```
558    /// use musli_zerocopy::{OwnedBuf, ZeroCopy};
559    ///
560    /// let mut buf = OwnedBuf::new();
561    /// buf.extend_from_slice(&1u32.to_ne_bytes());
562    ///
563    /// *u32::from_bytes_mut(&mut buf[..])? += 10;
564    ///
565    /// assert_eq!(*u32::from_bytes(&buf[..])?, 11);
566    /// # Ok::<_, musli_zerocopy::Error>(())
567    /// ```
568    #[inline]
569    fn from_bytes_mut(bytes: &mut [u8]) -> Result<&mut Self, Error> {
570        Buf::new_mut(bytes).load_at_mut::<Self>(0)
571    }
572
573    /// Swap the bytes of `self` using the specified byte ordering to match the
574    /// native byte ordering.
575    ///
576    /// If the specified [`ByteOrder`] matches the current ordering, this is a
577    /// no-op.
578    ///
579    /// This will cause any byte-order sensitive primitives to be converted to
580    /// the native byte order.
581    ///
582    /// # Complex types
583    ///
584    /// For complex types, this will walk the type hierarchy and swap each
585    /// composite field that is apart of that type.
586    ///
587    /// ```
588    /// use musli_zerocopy::{endian, Ref, ZeroCopy};
589    ///
590    /// #[derive(ZeroCopy)]
591    /// #[repr(C)]
592    /// struct Struct {
593    ///     number: u32,
594    ///     reference: Ref<u32, endian::Little, usize>,
595    /// }
596    ///
597    /// let st = Struct {
598    ///     number: 0x10203040u32.to_le(),
599    ///     reference: Ref::new(0x50607080usize.to_le()),
600    /// };
601    ///
602    /// assert_eq!(st.number, 0x10203040u32.to_le());
603    /// assert_eq!(st.reference.offset(), 0x50607080usize);
604    ///
605    /// let st2 = st.swap_bytes::<endian::Big>();
606    /// assert_eq!(st2.number, 0x10203040u32.to_be());
607    /// assert_eq!(st2.reference.offset(), 0x50607080usize);
608    /// ```
609    ///
610    /// # Safety
611    ///
612    /// There's nothing fundamentally unsafe about byte swapping, all though it
613    /// should be noted that the exact output is not guaranteed to be stable in
614    /// case a type cannot be safely byte-swapped. This is the case for
615    /// [`char`], since byte swapping one might cause it to inhabit an illegal
616    /// bit pattern.
617    ///
618    /// To test whether a type can be byte swapped, the [`CAN_SWAP_BYTES`]
619    /// constant should be advised.
620    ///
621    /// [`CAN_SWAP_BYTES`]: Self::CAN_SWAP_BYTES
622    fn swap_bytes<E>(self) -> Self
623    where
624        E: ByteOrder;
625}
626
627unsafe impl UnsizedZeroCopy for str {
628    const ALIGN: usize = align_of::<u8>();
629    const PADDED: bool = false;
630
631    #[inline]
632    fn as_ptr(&self) -> *const u8 {
633        str::as_ptr(self)
634    }
635
636    #[inline]
637    fn metadata(&self) -> Self::Metadata {
638        str::len(self)
639    }
640
641    #[inline]
642    unsafe fn pad(&self, _: &mut Padder<'_, Self>) {}
643
644    #[inline]
645    unsafe fn validate_unsized<E, O>(
646        data: NonNull<u8>,
647        len: usize,
648        metadata: Self::Stored<O>,
649    ) -> Result<Self::Metadata, Error>
650    where
651        E: ByteOrder,
652        O: Size,
653    {
654        let metadata = metadata.as_usize::<E>();
655
656        if metadata > len {
657            return Err(Error::new(ErrorKind::OutOfRangeBounds {
658                range: 0..metadata,
659                len,
660            }));
661        };
662
663        let buf = slice::from_raw_parts(data.as_ptr(), metadata);
664        str::from_utf8(buf).map_err(|error| Error::new(ErrorKind::Utf8Error { error }))?;
665        Ok(metadata)
666    }
667
668    #[inline]
669    unsafe fn with_metadata(data: NonNull<u8>, metadata: Self::Metadata) -> *const Self {
670        let slice = slice::from_raw_parts(data.as_ptr(), metadata);
671        str::from_utf8_unchecked(slice)
672    }
673
674    #[inline]
675    unsafe fn with_metadata_mut(data: NonNull<u8>, metadata: Self::Metadata) -> *mut Self {
676        let slice = slice::from_raw_parts_mut(data.as_ptr(), metadata);
677        str::from_utf8_unchecked_mut(slice)
678    }
679}
680
681unsafe impl<T> UnsizedZeroCopy for [T]
682where
683    T: ZeroCopy,
684{
685    const ALIGN: usize = align_of::<T>();
686    const PADDED: bool = T::PADDED;
687
688    #[inline]
689    fn as_ptr(&self) -> *const u8 {
690        <[T]>::as_ptr(self).cast()
691    }
692
693    #[inline]
694    unsafe fn pad(&self, padder: &mut Padder<'_, Self>) {
695        for _ in 0..self.len() {
696            padder.pad::<T>();
697        }
698    }
699
700    #[inline]
701    fn metadata(&self) -> Self::Metadata {
702        self.len()
703    }
704
705    #[inline]
706    unsafe fn validate_unsized<E, O>(
707        data: NonNull<u8>,
708        len: usize,
709        metadata: Self::Stored<O>,
710    ) -> Result<Self::Metadata, Error>
711    where
712        E: ByteOrder,
713        O: Size,
714    {
715        let metadata = metadata.as_usize::<E>();
716
717        let Some(size) = metadata.checked_mul(size_of::<T>()) else {
718            return Err(Error::new(ErrorKind::LengthOverflow {
719                len: metadata,
720                size: size_of::<T>(),
721            }));
722        };
723
724        if size > len {
725            return Err(Error::new(ErrorKind::OutOfRangeBounds {
726                range: 0..metadata,
727                len,
728            }));
729        };
730
731        if !T::ANY_BITS {
732            let mut validator = Validator::<[T]>::new(data);
733
734            for _ in 0..metadata {
735                validator.validate_only::<T>()?;
736            }
737        }
738
739        Ok(metadata)
740    }
741
742    #[inline]
743    unsafe fn with_metadata(data: NonNull<u8>, metadata: Self::Metadata) -> *const Self {
744        slice::from_raw_parts(data.cast().as_ptr(), metadata)
745    }
746
747    #[inline]
748    unsafe fn with_metadata_mut(data: NonNull<u8>, metadata: Self::Metadata) -> *mut Self {
749        slice::from_raw_parts_mut(data.cast().as_ptr(), metadata)
750    }
751}
752
753macro_rules! impl_number {
754    ($ty:ty, $from_be:path) => {
755        #[doc = concat!(" [`ZeroCopy`] implementation for `", stringify!($ty), "`")]
756        ///
757        /// # Examples
758        ///
759        /// ```
760        /// use std::slice;
761        /// use std::mem::size_of;
762        /// use musli_zerocopy::{buf, Ref, ZeroCopy};
763        ///
764        /// #[derive(ZeroCopy)]
765        /// #[repr(C)]
766        /// struct Struct {
767        #[doc = concat!("    field: ", stringify!($ty), ",")]
768        /// }
769        ///
770        #[doc = concat!("let zero: ", stringify!($ty), " = 0;")]
771        #[doc = concat!("let one: ", stringify!($ty), " = 1;")]
772        ///
773        #[doc = concat!("let zero = ", stringify!($ty), "::to_ne_bytes(0);")]
774        #[doc = concat!("let zero = buf::aligned_buf::<", stringify!($ty), ">(&zero);")]
775        #[doc = concat!("let one = ", stringify!($ty), "::to_ne_bytes(1);")]
776        #[doc = concat!("let one = buf::aligned_buf::<", stringify!($ty), ">(&one);")]
777        ///
778        /// let st = zero.load(Ref::<Struct>::zero())?;
779        /// assert_eq!(st.field, 0);
780        ///
781        /// let st = one.load(Ref::<Struct>::zero())?;
782        /// assert_eq!(st.field, 1);
783        /// # Ok::<_, musli_zerocopy::Error>(())
784        /// ```
785        unsafe impl ZeroCopy for $ty {
786            const ANY_BITS: bool = true;
787            const PADDED: bool = false;
788            const CAN_SWAP_BYTES: bool = true;
789
790            #[inline]
791            unsafe fn pad(_: &mut Padder<'_, Self>) {}
792
793            #[inline]
794            unsafe fn validate(_: &mut Validator<'_, Self>) -> Result<(), Error> {
795                Ok(())
796            }
797
798            #[inline]
799            fn swap_bytes<E>(self) -> Self
800            where
801                E: ByteOrder,
802            {
803                $from_be(self)
804            }
805        }
806
807        impl Visit for $ty {
808            type Target = $ty;
809
810            #[inline]
811            fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
812            where
813                V: FnOnce(&Self::Target) -> O,
814            {
815                Ok(visitor(self))
816            }
817        }
818    };
819}
820
821impl_number!(usize, E::swap_usize);
822impl_number!(isize, E::swap_isize);
823impl_number!(u8, core::convert::identity);
824impl_number!(u16, E::swap_u16);
825impl_number!(u32, E::swap_u32);
826impl_number!(u64, E::swap_u64);
827impl_number!(u128, E::swap_u128);
828impl_number!(i8, core::convert::identity);
829impl_number!(i16, E::swap_i16);
830impl_number!(i32, E::swap_i32);
831impl_number!(i64, E::swap_i64);
832impl_number!(i128, E::swap_i128);
833
834macro_rules! impl_float {
835    ($ty:ty, $from_fn:path) => {
836        unsafe impl ZeroCopy for $ty {
837            const ANY_BITS: bool = true;
838            const PADDED: bool = false;
839            const CAN_SWAP_BYTES: bool = true;
840
841            #[inline]
842            unsafe fn pad(_: &mut Padder<'_, Self>) {}
843
844            #[inline]
845            unsafe fn validate(_: &mut Validator<'_, Self>) -> Result<(), Error> {
846                Ok(())
847            }
848
849            fn swap_bytes<E>(self) -> Self
850            where
851                E: ByteOrder,
852            {
853                $from_fn(self)
854            }
855        }
856
857        impl Visit for $ty {
858            type Target = $ty;
859
860            #[inline]
861            fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
862            where
863                V: FnOnce(&Self::Target) -> O,
864            {
865                Ok(visitor(self))
866            }
867        }
868    };
869}
870
871impl_float!(f32, E::swap_f32);
872impl_float!(f64, E::swap_f64);
873
874/// The `ZeroCopy` implementation for `char`.
875///
876/// Validating this type is byte-order sensitive, since the bit-pattern it
877/// inhabits needs to align with the bit-patterns it can inhabit.
878unsafe impl ZeroCopy for char {
879    const ANY_BITS: bool = false;
880    const PADDED: bool = false;
881    const CAN_SWAP_BYTES: bool = false;
882
883    #[inline]
884    unsafe fn pad(_: &mut Padder<'_, Self>) {}
885
886    #[inline]
887    unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error> {
888        let repr = validator.load_unaligned::<u32>()?;
889
890        if char::try_from(repr).is_err() {
891            return Err(Error::new(ErrorKind::IllegalChar { repr }));
892        }
893
894        Ok(())
895    }
896
897    #[inline]
898    fn swap_bytes<E>(self) -> Self
899    where
900        E: ByteOrder,
901    {
902        self
903    }
904}
905
906impl Visit for char {
907    type Target = char;
908
909    #[inline]
910    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
911    where
912        V: FnOnce(&Self::Target) -> O,
913    {
914        Ok(visitor(self))
915    }
916}
917
918unsafe impl ZeroCopy for bool {
919    const ANY_BITS: bool = false;
920    const PADDED: bool = false;
921    const CAN_SWAP_BYTES: bool = true;
922
923    #[inline]
924    unsafe fn pad(_: &mut Padder<'_, Self>) {}
925
926    #[inline]
927    unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error> {
928        match validator.byte() {
929            0 | 1 => (),
930            repr => return Err(Error::new(ErrorKind::IllegalBool { repr })),
931        }
932
933        Ok(())
934    }
935
936    #[inline]
937    fn swap_bytes<E>(self) -> Self
938    where
939        E: ByteOrder,
940    {
941        self
942    }
943}
944
945impl Visit for bool {
946    type Target = bool;
947
948    #[inline]
949    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
950    where
951        V: FnOnce(&Self::Target) -> O,
952    {
953        Ok(visitor(self))
954    }
955}
956
957macro_rules! impl_nonzero_number {
958    ($ty:ident, $inner:ty) => {
959        #[doc = concat!(" [`ZeroCopy`] implementation for `", stringify!($ty), "`")]
960        ///
961        /// # Examples
962        ///
963        /// ```
964        #[doc = concat!("use std::num::", stringify!($ty), ";")]
965        /// use std::slice;
966        /// use std::mem::size_of;
967        /// use musli_zerocopy::{buf, Ref, ZeroCopy};
968        ///
969        /// #[derive(ZeroCopy)]
970        /// #[repr(C)]
971        /// struct Struct {
972        #[doc = concat!("    field: ", stringify!($ty), ",")]
973        /// }
974        ///
975        #[doc = concat!("let zero = ", stringify!($inner), "::to_ne_bytes(0);")]
976        #[doc = concat!("let zero = buf::aligned_buf::<", stringify!($ty), ">(&zero);")]
977        #[doc = concat!("let one = ", stringify!($inner), "::to_ne_bytes(1);")]
978        #[doc = concat!("let one = buf::aligned_buf::<", stringify!($ty), ">(&one);")]
979        ///
980        /// // Non-zero buffer works as expected.
981        /// let st = one.load(Ref::<Struct>::zero())?;
982        /// assert_eq!(st.field.get(), 1);
983        ///
984        /// // Trying to use a zeroed buffer with a non-zero type.
985        /// assert!(zero.load(Ref::<Struct>::zero()).is_err());
986        /// # Ok::<_, musli_zerocopy::Error>(())
987        /// ```
988        unsafe impl ZeroCopy for ::core::num::$ty {
989            const ANY_BITS: bool = false;
990            const PADDED: bool = false;
991            const CAN_SWAP_BYTES: bool = true;
992
993            #[inline]
994            unsafe fn pad(_: &mut Padder<'_, Self>) {}
995
996            #[inline]
997            unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error> {
998                // NB: A zeroed bit-pattern is byte-order independent.
999                if validator.load_unaligned::<$inner>()? == 0 {
1000                    return Err(Error::new(ErrorKind::NonZeroZeroed {
1001                        range: validator.range::<::core::num::$ty>(),
1002                    }));
1003                }
1004
1005                Ok(())
1006            }
1007
1008            #[inline]
1009            fn swap_bytes<E>(self) -> Self
1010            where
1011                E: ByteOrder,
1012            {
1013                // SAFETY: a value inhabiting zero is byte-order independent.
1014                unsafe {
1015                    ::core::num::$ty::new_unchecked(<$inner as ZeroCopy>::swap_bytes::<E>(
1016                        self.get(),
1017                    ))
1018                }
1019            }
1020        }
1021
1022        impl Visit for ::core::num::$ty {
1023            type Target = ::core::num::$ty;
1024
1025            #[inline]
1026            fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
1027            where
1028                V: FnOnce(&Self::Target) -> O,
1029            {
1030                Ok(visitor(self))
1031            }
1032        }
1033
1034        #[doc = concat!(" [`ZeroCopy`] implementation for `Option<", stringify!($ty), ">`")]
1035        ///
1036        /// # Examples
1037        ///
1038        /// ```
1039        #[doc = concat!("use std::num::", stringify!($ty), ";")]
1040        /// use std::slice;
1041        /// use std::mem::size_of;
1042        /// use musli_zerocopy::{buf, Ref, ZeroCopy};
1043        ///
1044        /// #[derive(ZeroCopy)]
1045        /// #[repr(C)]
1046        /// struct Struct {
1047        #[doc = concat!("    field: Option<", stringify!($ty), ">,")]
1048        /// }
1049        ///
1050        #[doc = concat!("let zero = ", stringify!($inner), "::to_ne_bytes(0);")]
1051        #[doc = concat!("let zero = buf::aligned_buf::<", stringify!($ty), ">(&zero);")]
1052        #[doc = concat!("let one = ", stringify!($inner), "::to_ne_bytes(1);")]
1053        #[doc = concat!("let one = buf::aligned_buf::<", stringify!($ty), ">(&one);")]
1054        ///
1055        /// let st = zero.load(Ref::<Struct>::zero())?;
1056        /// assert_eq!(st.field, None);
1057        ///
1058        /// let st = one.load(Ref::<Struct>::zero())?;
1059        #[doc = concat!("assert_eq!(st.field, ", stringify!($ty), "::new(1));")]
1060        /// # Ok::<_, musli_zerocopy::Error>(())
1061        /// ```
1062        unsafe impl ZeroCopy for Option<::core::num::$ty> {
1063            const ANY_BITS: bool = true;
1064            const PADDED: bool = false;
1065            const CAN_SWAP_BYTES: bool = true;
1066
1067            #[inline]
1068            unsafe fn pad(_: &mut Padder<'_, Self>) {}
1069
1070            #[inline]
1071            unsafe fn validate(_: &mut Validator<'_, Self>) -> Result<(), Error> {
1072                Ok(())
1073            }
1074
1075            #[inline]
1076            fn swap_bytes<E>(self) -> Self
1077            where
1078                E: ByteOrder,
1079            {
1080                // SAFETY: All bit-patterns are habitable, zero we can rely on
1081                // byte-order conversion from the inner type.
1082                unsafe {
1083                    transmute(<$inner as ZeroCopy>::swap_bytes::<E>(transmute::<
1084                        Self,
1085                        $inner,
1086                    >(self)))
1087                }
1088            }
1089        }
1090
1091        impl Visit for Option<::core::num::$ty> {
1092            type Target = Option<::core::num::$ty>;
1093
1094            #[inline]
1095            fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
1096            where
1097                V: FnOnce(&Self::Target) -> O,
1098            {
1099                Ok(visitor(self))
1100            }
1101        }
1102    };
1103}
1104
1105impl_nonzero_number!(NonZeroUsize, usize);
1106impl_nonzero_number!(NonZeroIsize, isize);
1107impl_nonzero_number!(NonZeroU8, u8);
1108impl_nonzero_number!(NonZeroU16, u16);
1109impl_nonzero_number!(NonZeroU32, u32);
1110impl_nonzero_number!(NonZeroU64, u64);
1111impl_nonzero_number!(NonZeroU128, u128);
1112impl_nonzero_number!(NonZeroI8, i8);
1113impl_nonzero_number!(NonZeroI16, i16);
1114impl_nonzero_number!(NonZeroI32, i32);
1115impl_nonzero_number!(NonZeroI64, i64);
1116impl_nonzero_number!(NonZeroI128, i128);
1117
1118macro_rules! impl_zst {
1119    ($({$($bounds:tt)*},)? $ty:ty, $expr:expr , {$example:ty $(, $import:path)?}) => {
1120        #[doc = concat!(" [`ZeroCopy`] implementation for `", stringify!($ty), "`")]
1121        ///
1122        /// # Examples
1123        ///
1124        /// ```
1125        $(#[doc = concat!("use ", stringify!($import), ";")])*
1126        /// use musli_zerocopy::{ZeroCopy, OwnedBuf};
1127        ///
1128        /// #[derive(Default, Clone, Copy, ZeroCopy)]
1129        /// #[repr(C)]
1130        /// struct Struct {
1131        #[doc = concat!("    field: ", stringify!($example), ",")]
1132        /// }
1133        ///
1134        /// let mut buf = OwnedBuf::new();
1135        /// let values = [Struct::default(); 100];
1136        /// let slice = buf.store_unsized(&values[..]);
1137        /// buf.align_in_place();
1138        /// assert_eq!(buf.len(), 0);
1139        ///
1140        /// let slice = buf.load(slice)?;
1141        /// assert_eq!(slice.len(), 100);
1142        /// # Ok::<_, musli_zerocopy::Error>(())
1143        /// ```
1144        unsafe impl $(<$($bounds)*>)* ZeroCopy for $ty {
1145            const ANY_BITS: bool = true;
1146            const PADDED: bool = false;
1147            const CAN_SWAP_BYTES: bool = true;
1148
1149            #[inline]
1150            unsafe fn pad(_: &mut Padder<'_, Self>) {
1151            }
1152
1153            #[inline]
1154            unsafe fn validate(_: &mut Validator<'_, Self>) -> Result<(), Error> {
1155                Ok(())
1156            }
1157
1158            #[inline]
1159            fn swap_bytes<E>(self) -> Self
1160            where
1161                E: ByteOrder,
1162            {
1163                self
1164            }
1165        }
1166
1167        impl $(<$($bounds)*>)* Visit for $ty {
1168            type Target = $ty;
1169
1170            #[inline]
1171            fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
1172            where
1173                V: FnOnce(&Self::Target) -> O,
1174            {
1175                Ok(visitor(self))
1176            }
1177        }
1178    };
1179}
1180
1181impl_zst!((), (), { () });
1182impl_zst!({T}, PhantomData<T>, PhantomData, {PhantomData<u32>, std::marker::PhantomData});
1183
1184/// [`ZeroCopy`] implementation for `[T; 0]`.
1185///
1186/// # Examples
1187///
1188/// ```
1189/// use std::mem::align_of;
1190///
1191/// use musli_zerocopy::{ZeroCopy, OwnedBuf};
1192///
1193/// #[derive(Default, Clone, Copy, ZeroCopy)]
1194/// #[repr(C)]
1195/// struct Struct<T> {
1196///     #[zero_copy(ignore)]
1197///     field: [T; 0],
1198/// }
1199///
1200/// let mut buf = OwnedBuf::with_alignment::<u128>();
1201/// let values = [Struct::<u128>::default(); 100];
1202/// let slice = buf.store_unsized(&values[..]);
1203/// buf.align_in_place();
1204/// assert_eq!(buf.len(), 0);
1205///
1206/// let slice = buf.load(slice)?;
1207/// assert_eq!(slice.len(), 100);
1208/// # Ok::<_, musli_zerocopy::Error>(())
1209/// ```
1210unsafe impl<T, const N: usize> ZeroCopy for [T; N]
1211where
1212    T: ZeroCopy,
1213{
1214    const ANY_BITS: bool = T::ANY_BITS;
1215    const PADDED: bool = T::PADDED;
1216    const CAN_SWAP_BYTES: bool = T::CAN_SWAP_BYTES;
1217
1218    #[inline]
1219    unsafe fn pad(padder: &mut Padder<'_, Self>) {
1220        for _ in 0..N {
1221            padder.pad::<T>();
1222        }
1223    }
1224
1225    #[inline]
1226    unsafe fn validate(validator: &mut Validator<'_, Self>) -> Result<(), Error> {
1227        for _ in 0..N {
1228            validator.validate_only::<T>()?;
1229        }
1230
1231        Ok(())
1232    }
1233
1234    #[inline]
1235    fn swap_bytes<E>(self) -> Self
1236    where
1237        E: ByteOrder,
1238    {
1239        let mut iter = self.into_iter();
1240        array::from_fn(move |_| T::swap_bytes::<E>(iter.next().unwrap()))
1241    }
1242}
1243
1244impl<T> Visit for [T; 0] {
1245    type Target = [T; 0];
1246
1247    #[inline]
1248    fn visit<V, O>(&self, _: &Buf, visitor: V) -> Result<O, Error>
1249    where
1250        V: FnOnce(&Self::Target) -> O,
1251    {
1252        Ok(visitor(self))
1253    }
1254}