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