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}