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