Skip to main content

ab_io_type/
trivial_type.rs

1use crate::IoType;
2use crate::alignment::Alignment;
3use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
4use crate::unaligned::Unaligned;
5pub use ab_io_type_derive::TrivialType;
6use core::ops::{Deref, DerefMut};
7use core::ptr::NonNull;
8use core::{ptr, slice};
9
10const SIZE_OF<T>: usize = size_of::<T>();
11/// Ensures the number of array elements (encoded in metadata) and array size fit into `u32`
12const SUPPORTED_ARRAY<T, const N: usize>: usize = {
13    assert!(
14        u32::MAX as usize >= N,
15        "Number of array elements must be smaller than 2^32"
16    );
17    assert!(
18        u32::MAX as usize >= size_of::<[T; N]>(),
19        "Type size must be smaller than 2^32"
20    );
21    0
22};
23/// Ensures `T` is not zero-sized, which some containers can't represent
24pub(crate) const NON_ZERO_SIZED<T: TrivialType>: usize = {
25    assert!(T::SIZE > 0, "Zero-sized types are not supported");
26    0
27};
28
29// TODO: Make this a `const` trait, with `const` impls generated by the derive, once const traits
30//  are stable, deriving crates would need `#![feature(const_trait_impl)]` otherwise:
31//  https://github.com/rust-lang/rust/issues/143874
32/// Simple wrapper data type that is designed in such a way that its serialization/deserialization
33/// is the same as the type itself.
34///
35/// Serialization takes the bytes of a value. Deserialization parses bytes: the parsing step
36/// [`Self::try_from_bytes_unaligned()`] checks that they are a valid value of the type, which is
37/// a length check for types that accept every bit pattern (see [`AnyBitPattern`]).
38///
39/// A valid value is one whose every field is a valid value of its type, like `0` or `1` for a
40/// `bool` and the index of a variant for the discriminant of an enum, and that satisfies the
41/// invariants `unsafe` code relies on. Parsing may reject more, like a length of
42/// `FixedCapacityElements` above its capacity, but doesn't check encoding rules, like the bytes of
43/// its length prefix after the length.
44///
45/// # Safety
46/// * There is no padding, every byte is initialized and there is no interior mutability
47/// * The alignment is at most [`Alignment::MAX`]
48/// * [`Self::SIZE`] is not overridden
49/// * [`Self::ALIGNMENT`] is the alignment that [`Self::METADATA`] decodes to, and it is at least
50///   `align_of::<Self>()`
51/// * [`Self::try_from_bytes_unaligned()`] returns `Some((value, remainder))` only if `bytes` start
52///   with `size_of::<Self>()` bytes that are a valid value of `Self`, `value` points to the
53///   beginning of `bytes` and `remainder` is the rest of `bytes` after those bytes
54///
55/// Implementations are expected to be composites of existing `TrivialType`s without custom
56/// alignment, whose alignment is then at most [`Alignment::MAX`] as well. Prefer
57/// `#[derive(TrivialType)]`, which upholds this contract.
58///
59/// # Deriving
60/// `#[derive(TrivialType)]` supports structs and enums and checks the following requirements at
61/// compile time:
62/// * no generic parameters, and types of all fields implement `TrivialType`
63/// * structs are `#[repr(C)]` or `#[repr(transparent)]` without other options
64/// * enums are `#[repr(u8)]` without other options
65/// * no `#[repr(align(N))]` or `#[repr(packed)]` in any `#[repr(..)]` attribute, [`Unaligned`] can
66///   be used to reduce the alignment of a field to one byte instead
67/// * no implicit padding, explicit `padding: [u8; N]` fields can be added where necessary. Padding
68///   is determined by [`TrivialType::ALIGNMENT`] of the field types. Each variant of an enum is
69///   laid out like a `#[repr(C)]` struct with the discriminant as the first field, so fields of all
70///   variants must have the same total size
71/// * explicit discriminants of enum variants are equal to the index of the variant, metadata
72///   identifies variants by their index and doesn't record discriminants
73/// * at most 255 fields in a struct or enum variant and at most 255 variants in an enum, names of
74///   the type, its fields and variants are at most 255 bytes long
75/// * size is smaller than 2^32 bytes
76/// * metadata, including metadata of field types, is at most [`MAX_METADATA_CAPACITY`] bytes,
77///   otherwise const evaluation panics with an opaque error
78/// * structs parse their fields in order, enums check the discriminant and parse the fields of that
79///   variant
80/// * deriving means that any combination of valid field values is a valid value of the type,
81///   private fields and `#[non_exhaustive]` included, because parsing creates values without
82///   calling constructors, unless `#[trivial_type(validate = path)]` rejects it
83/// * structs implement [`AnyBitPatternMarker`] when all their fields do, unless they use
84///   `#[trivial_type(validate = path)]`
85///
86/// Invariants that `unsafe` code relies on are checked with `#[trivial_type(validate = path)]`.
87/// `path` is called as `path(value: Self) -> bool` after all fields were parsed and must return
88/// `false` for every value that `unsafe` code relying on the invariants can't handle. It must not
89/// panic, since parsing is used in code that is verified not to panic, and a `const fn` is
90/// recommended, the derive may become `const` later. Such types don't implement
91/// [`AnyBitPatternMarker`].
92///
93/// It is called by every parsing method, including those of arrays of the type, of [`Unaligned`]
94/// and of containers through [`IoType::try_from_ptr()`] and [`IoType::try_from_mut_ptr()`]. The
95/// unsafe methods that skip parsing, [`IoType::from_ptr()`], [`IoType::from_mut_ptr()`] and derives
96/// of other crates, like SCALE's `Decode` and serde's `Deserialize`, don't call it.
97pub unsafe trait TrivialType
98where
99    Self: Copy + 'static,
100{
101    // TODO: Make it `final` once supported:
102    //  https://internals.rust-lang.org/t/final-associated-constants/24655
103    const SIZE: u32 = {
104        assert!(
105            u32::MAX as usize >= size_of::<Self>(),
106            "Type size must be smaller than 2^32"
107        );
108        size_of::<Self>() as u32
109    };
110    /// Alignment of the type in metadata.
111    ///
112    /// Integers and `bool` are aligned to their size, `()` and [`Unaligned`] to 1 byte, other types
113    /// to the largest alignment of their contents. It is never smaller than `align_of::<Self>()`,
114    /// so memory aligned to it is aligned for `Self`.
115    const ALIGNMENT: Alignment;
116    /// Data structure metadata in binary form, describing shape and types of the contents, see
117    /// [`IoTypeMetadataKind`] for encoding details.
118    const METADATA: &[u8];
119
120    /// Parse the beginning of `bytes`, which don't need to be aligned.
121    ///
122    /// Returns the value and the remaining bytes, or `None` if `bytes` are shorter than the type or
123    /// don't start with a valid value. `#[derive(TrivialType)]` implements it, the other parsing
124    /// methods are built on it.
125    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])>;
126
127    /// Parse the beginning of aligned `bytes`, returns the value and the remaining bytes.
128    ///
129    /// Returns `None` if `bytes` are not aligned for `Self`, are too short or don't start with a
130    /// valid value.
131    #[inline(always)]
132    final fn try_from_bytes(bytes: &[u8]) -> Option<(&Self, &[u8])> {
133        if !bytes.as_ptr().cast::<Self>().is_aligned() {
134            return None;
135        }
136        let (_value, remainder) = Self::try_from_bytes_unaligned(bytes)?;
137        // SAFETY: `bytes` start with a valid value of `Self` (parsing step contract), aligned as
138        // checked above
139        let value = unsafe { bytes.as_ptr().cast::<Self>().as_ref_unchecked() };
140        Some((value, remainder))
141    }
142
143    /// Like [`Self::try_from_bytes()`], but returns `None` if there are more bytes than the value
144    #[inline(always)]
145    final fn try_from_bytes_exact(bytes: &[u8]) -> Option<&Self> {
146        let (value, remainder) = Self::try_from_bytes(bytes)?;
147        remainder.is_empty().then_some(value)
148    }
149
150    /// Like [`Self::try_from_bytes()`], but returns an exclusive reference.
151    ///
152    /// Only valid values of `Self` can be written through it, so the bytes stay a valid value.
153    #[inline(always)]
154    final fn try_from_bytes_mut(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])> {
155        if !bytes.as_ptr().cast::<Self>().is_aligned() {
156            return None;
157        }
158        Self::try_from_bytes_unaligned(bytes)?;
159        let (value, remainder) = bytes.split_at_mut_checked(size_of::<Self>())?;
160        // SAFETY: `bytes` start with a valid value of `Self` (parsing step contract), aligned as
161        // checked above, only valid values of `Self` can be written through the reference, and
162        // they have no padding, so the bytes stay initialized. It is derived from `bytes`, not
163        // from the shared reference the parsing step returned.
164        let value = unsafe { value.as_mut_ptr().cast::<Self>().as_mut_unchecked() };
165        Some((value, remainder))
166    }
167
168    /// Read a copy from the beginning of `bytes`, which don't need to be aligned, returns the value
169    /// and the remaining bytes
170    #[inline(always)]
171    final fn try_read_unaligned(bytes: &[u8]) -> Option<(Self, &[u8])> {
172        let (value, remainder) = Self::try_from_bytes_unaligned(bytes)?;
173        Some((value.as_inner(), remainder))
174    }
175
176    /// Like [`Self::try_read_unaligned()`], but returns `None` if there are more bytes than the
177    /// value
178    #[inline(always)]
179    final fn try_read_unaligned_exact(bytes: &[u8]) -> Option<Self> {
180        let (value, remainder) = Self::try_read_unaligned(bytes)?;
181        remainder.is_empty().then_some(value)
182    }
183
184    /// Read unaligned value from memory.
185    ///
186    /// Returns `None` if the number of input bytes is not sufficient to represent the type. Prefer
187    /// [`Self::try_read_unaligned()`], which checks the bytes.
188    ///
189    /// # Safety
190    /// `bytes` start with a valid value of `Self` (see [`TrivialType`]), for example bytes that
191    /// [`Self::try_read_unaligned()`] accepts.
192    #[inline(always)]
193    final unsafe fn read_unaligned(bytes: &[u8]) -> Option<Self> {
194        // SAFETY: Guaranteed by function contract
195        Some(unsafe { Unaligned::<Self>::from_bytes(bytes)?.as_inner() })
196    }
197
198    /// Similar to [`Self::read_unaligned()`], but doesn't do any checks at all.
199    ///
200    /// # Safety
201    /// `bytes` start with a valid value of `Self`.
202    #[inline(always)]
203    final unsafe fn read_unaligned_unchecked(bytes: &[u8]) -> Self {
204        // SAFETY: Guaranteed by function contract
205        unsafe { Unaligned::<Self>::from_bytes_unchecked(bytes).as_inner() }
206    }
207
208    /// Create a reference to a type, which is represented by provided memory.
209    ///
210    /// Memory must be correctly aligned, or else `None` will be returned. Size must be sufficient,
211    /// padding beyond the size of the type is allowed. Prefer [`Self::try_from_bytes()`], which
212    /// checks the bytes.
213    ///
214    /// # Safety
215    /// `bytes` start with a valid value of `Self` (see [`TrivialType`]), for example bytes that
216    /// [`Self::try_from_bytes()`] accepts.
217    #[inline(always)]
218    final unsafe fn from_bytes(bytes: &[u8]) -> Option<&Self> {
219        let bytes = bytes.get(..size_of::<Self>())?;
220        // SAFETY: `bytes` are a valid value of `Self` (function contract), which is the only
221        // element of the middle slice if it is aligned
222        let (before, slice, _) = unsafe { bytes.align_to::<Self>() };
223
224        before.is_empty().then(|| slice.first()).flatten()
225    }
226
227    /// Similar to [`Self::from_bytes()`], but doesn't do any checks at all.
228    ///
229    /// # Safety
230    /// `bytes` are aligned for `Self` and start with a valid value of `Self`.
231    #[inline(always)]
232    final unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
233        // SAFETY: Guaranteed by function contract
234        unsafe { bytes.as_ptr().cast::<Self>().as_ref_unchecked() }
235    }
236
237    /// Create a mutable reference to a type, which is represented by provided memory.
238    ///
239    /// Memory must be correctly aligned, or else `None` will be returned. Size must be sufficient,
240    /// padding beyond the size of the type is allowed. Prefer [`Self::try_from_bytes_mut()`], which
241    /// checks the bytes.
242    ///
243    /// # Safety
244    /// `bytes` start with a valid value of `Self` (see [`TrivialType`]), for example bytes that
245    /// [`Self::try_from_bytes_mut()`] accepts.
246    #[inline(always)]
247    final unsafe fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
248        let bytes = bytes.get_mut(..size_of::<Self>())?;
249        // SAFETY: `bytes` are a valid value of `Self` (function contract), which is the only
250        // element of the middle slice if it is aligned, only valid values of `Self` can be written
251        // through it, and they have no padding, so the bytes stay initialized
252        let (before, slice, _) = unsafe { bytes.align_to_mut::<Self>() };
253
254        before.is_empty().then(|| slice.first_mut()).flatten()
255    }
256
257    /// Similar to [`Self::from_bytes_mut()`], but doesn't do any checks at all.
258    ///
259    /// # Safety
260    /// `bytes` are aligned for `Self` and start with a valid value of `Self`.
261    #[inline(always)]
262    final unsafe fn from_bytes_mut_unchecked(bytes: &mut [u8]) -> &mut Self {
263        // SAFETY: Guaranteed by function contract
264        unsafe { bytes.as_mut_ptr().cast::<Self>().as_mut_unchecked() }
265    }
266
267    /// Access the underlying byte representation of a data structure
268    #[inline(always)]
269    final fn as_bytes(&self) -> &[u8; SIZE_OF::<Self>] {
270        // SAFETY: All bits are valid for reading as bytes, see `TrivialType` description
271        unsafe { ptr::from_ref(self).cast::<[u8; _]>().as_ref_unchecked() }
272    }
273
274    /// Access the underlying mutable byte representation of a data structure.
275    ///
276    /// # Safety
277    /// Only bytes of a valid value of `Self` may be written to the returned array.
278    #[inline(always)]
279    final unsafe fn as_bytes_mut(&mut self) -> &mut [u8; SIZE_OF::<Self>] {
280        // SAFETY: All bits are valid for reading as bytes, see `TrivialType` description, only
281        // bytes of a valid value are written (function contract)
282        unsafe { ptr::from_mut(self).cast::<[u8; _]>().as_mut_unchecked() }
283    }
284}
285
286// TODO: This trait only exists because `try_as_dyn()`, the only way to detect it in generic code,
287//  skips impls whose bounds mention a type parameter inside a constant, like the array size limit
288//  of `TrivialType for [T; N]`. Merge it into `AnyBitPattern` once that is fixed:
289//  https://github.com/rust-lang/rust/issues/164149
290/// Every bit pattern of the type is a valid value.
291///
292/// Together with [`TrivialType`] it provides [`AnyBitPattern`], which is the bound to use.
293/// `#[derive(TrivialType)]` implements it for structs whose fields all implement it, unless they
294/// use `#[trivial_type(validate = path)]`.
295///
296/// # Safety
297/// Every pattern of `size_of::<Self>()` initialized bytes is a valid value of `Self` that no
298/// invariant of `Self` excludes, not even one that only safe code relies on (like a length that
299/// must not exceed a capacity, or one that `#[trivial_type(validate = path)]` checks), so bytes of
300/// `Self` never need to be checked. If `Self` implements [`TrivialType`], its parsing step
301/// [`TrivialType::try_from_bytes_unaligned()`] accepts every such pattern.
302#[diagnostic::on_unimplemented(message = "`{Self}` doesn't accept every bit pattern")]
303pub unsafe trait AnyBitPatternMarker {}
304
305/// [`TrivialType`] whose every bit pattern is a valid value.
306///
307/// Implemented for every type that implements [`TrivialType`] and [`AnyBitPatternMarker`].
308#[diagnostic::on_unimplemented(message = "`{Self}` doesn't accept every bit pattern")]
309pub trait AnyBitPattern
310where
311    Self: TrivialType + AnyBitPatternMarker,
312{
313}
314
315impl<T> AnyBitPattern for T where T: TrivialType + AnyBitPatternMarker {}
316
317/// Parsing step of a type whose every bit pattern is a valid value
318#[inline(always)]
319fn try_from_bytes_any_bit_pattern<T>(bytes: &[u8]) -> Option<(&Unaligned<T>, &[u8])>
320where
321    T: TrivialType + AnyBitPatternMarker,
322{
323    let (bytes, remainder) = bytes.split_at_checked(size_of::<T>())?;
324    // SAFETY: `Unaligned<T>` has alignment 1 and the size of `T`, `bytes` are that many
325    // initialized bytes, and any of them are a valid value of `T` (`AnyBitPatternMarker`)
326    let value = unsafe { bytes.as_ptr().cast::<Unaligned<T>>().as_ref_unchecked() };
327    Some((value, remainder))
328}
329
330/// Returns the bytes after `count` valid values of `T` at the beginning of `bytes`
331#[inline(always)]
332pub(crate) fn try_skip_valid<T>(bytes: &[u8], count: usize) -> Option<&[u8]>
333where
334    T: TrivialType,
335{
336    // Zero-sized values have no bytes, so only a check like a `validate` hook can reject one, and
337    // it rejects either all of them or none, so one check replaces `count` steps that don't consume
338    // bytes
339    if size_of::<T>() == 0 {
340        if count > 0 {
341            T::try_from_bytes_unaligned(bytes)?;
342        }
343        return Some(bytes);
344    }
345    // With all elements split off first, every step gets exactly the bytes of one element, so for
346    // types whose step only checks the length the loop is optimized away
347    let (elements, remainder) = bytes.split_at_checked(count.checked_mul(size_of::<T>())?)?;
348    for element in elements.as_chunks::<{ SIZE_OF::<T> }>().0 {
349        T::try_from_bytes_unaligned(element)?;
350    }
351    Some(remainder)
352}
353
354// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
355unsafe impl TrivialType for () {
356    const ALIGNMENT: Alignment = Alignment::from_power(0)
357        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
358    const METADATA: &[u8] = &[IoTypeMetadataKind::Unit as u8];
359
360    #[inline(always)]
361    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
362        try_from_bytes_any_bit_pattern(bytes)
363    }
364}
365// SAFETY: Zero-sized, its only value has no bytes, the parsing step only checks the length
366unsafe impl AnyBitPatternMarker for () {}
367// SAFETY: One byte, the parsing step accepts only `0` and `1`, the valid values of `bool`
368unsafe impl TrivialType for bool {
369    const ALIGNMENT: Alignment = Alignment::from_power(0)
370        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
371    const METADATA: &[u8] = &[IoTypeMetadataKind::Bool as u8];
372
373    #[inline(always)]
374    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
375        let (&[0 | 1], remainder) = bytes.split_first_chunk::<1>()? else {
376            return None;
377        };
378        // SAFETY: `Unaligned<bool>` is one byte with alignment 1, the first byte is `0` or `1`
379        let value = unsafe { bytes.as_ptr().cast::<Unaligned<Self>>().as_ref_unchecked() };
380        Some((value, remainder))
381    }
382}
383// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
384unsafe impl TrivialType for u8 {
385    const ALIGNMENT: Alignment = Alignment::from_power(0)
386        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
387    const METADATA: &[u8] = &[IoTypeMetadataKind::U8 as u8];
388
389    #[inline(always)]
390    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
391        try_from_bytes_any_bit_pattern(bytes)
392    }
393}
394// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
395unsafe impl AnyBitPatternMarker for u8 {}
396// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
397unsafe impl TrivialType for u16 {
398    const ALIGNMENT: Alignment = Alignment::from_power(1)
399        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
400    const METADATA: &[u8] = &[IoTypeMetadataKind::U16 as u8];
401
402    #[inline(always)]
403    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
404        try_from_bytes_any_bit_pattern(bytes)
405    }
406}
407// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
408unsafe impl AnyBitPatternMarker for u16 {}
409// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
410unsafe impl TrivialType for u32 {
411    const ALIGNMENT: Alignment = Alignment::from_power(2)
412        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
413    const METADATA: &[u8] = &[IoTypeMetadataKind::U32 as u8];
414
415    #[inline(always)]
416    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
417        try_from_bytes_any_bit_pattern(bytes)
418    }
419}
420// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
421unsafe impl AnyBitPatternMarker for u32 {}
422// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
423unsafe impl TrivialType for u64 {
424    const ALIGNMENT: Alignment = Alignment::from_power(3)
425        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
426    const METADATA: &[u8] = &[IoTypeMetadataKind::U64 as u8];
427
428    #[inline(always)]
429    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
430        try_from_bytes_any_bit_pattern(bytes)
431    }
432}
433// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
434unsafe impl AnyBitPatternMarker for u64 {}
435// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
436unsafe impl TrivialType for u128 {
437    // `Alignment::MAX` because native alignment for `u128` is 8 bytes (instead of 16) on 32-bit
438    // platforms
439    const ALIGNMENT: Alignment = Alignment::MAX;
440    const METADATA: &[u8] = &[IoTypeMetadataKind::U128 as u8];
441
442    #[inline(always)]
443    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
444        try_from_bytes_any_bit_pattern(bytes)
445    }
446}
447// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
448unsafe impl AnyBitPatternMarker for u128 {}
449// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
450unsafe impl TrivialType for i8 {
451    const ALIGNMENT: Alignment = Alignment::from_power(0)
452        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
453    const METADATA: &[u8] = &[IoTypeMetadataKind::I8 as u8];
454
455    #[inline(always)]
456    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
457        try_from_bytes_any_bit_pattern(bytes)
458    }
459}
460// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
461unsafe impl AnyBitPatternMarker for i8 {}
462// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
463unsafe impl TrivialType for i16 {
464    const ALIGNMENT: Alignment = Alignment::from_power(1)
465        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
466    const METADATA: &[u8] = &[IoTypeMetadataKind::I16 as u8];
467
468    #[inline(always)]
469    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
470        try_from_bytes_any_bit_pattern(bytes)
471    }
472}
473// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
474unsafe impl AnyBitPatternMarker for i16 {}
475// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
476unsafe impl TrivialType for i32 {
477    const ALIGNMENT: Alignment = Alignment::from_power(2)
478        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
479    const METADATA: &[u8] = &[IoTypeMetadataKind::I32 as u8];
480
481    #[inline(always)]
482    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
483        try_from_bytes_any_bit_pattern(bytes)
484    }
485}
486// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
487unsafe impl AnyBitPatternMarker for i32 {}
488// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
489unsafe impl TrivialType for i64 {
490    const ALIGNMENT: Alignment = Alignment::from_power(3)
491        .expect("Alignment of a primitive type is larger than `Alignment::MAX`");
492    const METADATA: &[u8] = &[IoTypeMetadataKind::I64 as u8];
493
494    #[inline(always)]
495    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
496        try_from_bytes_any_bit_pattern(bytes)
497    }
498}
499// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
500unsafe impl AnyBitPatternMarker for i64 {}
501// SAFETY: Any bit pattern is valid, so it is safe to implement `TrivialType` for this type
502unsafe impl TrivialType for i128 {
503    // `Alignment::MAX` because native alignment for `i128` is 8 bytes (instead of 16) on 32-bit
504    // platforms
505    const ALIGNMENT: Alignment = Alignment::MAX;
506    const METADATA: &[u8] = &[IoTypeMetadataKind::I128 as u8];
507
508    #[inline(always)]
509    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
510        try_from_bytes_any_bit_pattern(bytes)
511    }
512}
513// SAFETY: Any bit pattern is a valid value of integers, the parsing step only checks the length
514unsafe impl AnyBitPatternMarker for i128 {}
515
516const fn array_metadata(size: u32, inner_metadata: &[u8]) -> ([u8; MAX_METADATA_CAPACITY], usize) {
517    concat_metadata_sources(&[
518        &[IoTypeMetadataKind::Array as u8],
519        &size.to_le_bytes(),
520        inner_metadata,
521    ])
522}
523
524// TODO: Change `usize` to `u32` once it is possible:
525//  https://github.com/rust-lang/rust/issues/156745
526// SAFETY: Elements follow each other without padding and are `TrivialType`, the parsing step checks
527// every element
528unsafe impl<const SIZE: usize, T> TrivialType for [T; SIZE]
529where
530    T: TrivialType,
531    [(); SUPPORTED_ARRAY::<T, SIZE>]:,
532{
533    const ALIGNMENT: Alignment = T::ALIGNMENT;
534    // Casting `SIZE` to `u32` is lossless, which is checked by the `SUPPORTED_ARRAY` bound
535    const METADATA: &[u8] = {
536        // The reference extends the lifetime of metadata scratch to that of the constant
537        let (metadata_scratch, metadata_size) = &array_metadata(SIZE as u32, T::METADATA);
538        metadata_scratch.split_at(*metadata_size).0
539    };
540
541    #[inline(always)]
542    fn try_from_bytes_unaligned(bytes: &[u8]) -> Option<(&Unaligned<Self>, &[u8])> {
543        let (bytes, remainder) = bytes.split_at_checked(size_of::<Self>())?;
544        try_skip_valid::<T>(bytes, SIZE)?;
545        // SAFETY: Elements follow each other without padding and each of them is a valid value as
546        // checked above, `Unaligned<Self>` has alignment 1 and the size of `Self`
547        let value = unsafe { bytes.as_ptr().cast::<Unaligned<Self>>().as_ref_unchecked() };
548        Some((value, remainder))
549    }
550}
551
552// SAFETY: Elements follow each other without padding, any bit pattern of each is a valid value,
553// which the parsing step of elements accepts. There is no array size limit here, `AnyBitPattern`
554// requires `[T; N]: TrivialType`, which has it.
555unsafe impl<const SIZE: usize, T> AnyBitPatternMarker for [T; SIZE] where T: AnyBitPatternMarker {}
556
557// SAFETY: All `TrivialType` instances are valid for `IoType`
558unsafe impl<T> IoType for T
559where
560    T: TrivialType,
561{
562    const METADATA: &[u8] = T::METADATA;
563
564    type PointerType = T;
565
566    #[inline(always)]
567    fn size(&self) -> u32 {
568        T::SIZE
569    }
570
571    #[inline(always)]
572    fn capacity(&self) -> u32 {
573        self.size()
574    }
575
576    #[inline(always)]
577    #[track_caller]
578    unsafe fn set_size(&mut self, size: u32) {
579        debug_assert_eq!(size, T::SIZE, "`set_size` called with invalid input");
580    }
581
582    #[inline(always)]
583    #[track_caller]
584    unsafe fn from_ptr<'a>(
585        ptr: &'a NonNull<Self::PointerType>,
586        size: &'a u32,
587        capacity: u32,
588    ) -> impl Deref<Target = Self> + 'a {
589        debug_assert!(ptr.is_aligned(), "Misaligned pointer");
590        debug_assert_eq!(*size, T::SIZE, "Invalid size");
591        debug_assert!(
592            *size <= capacity,
593            "Size {size} must not exceed capacity {capacity}"
594        );
595
596        // SAFETY: guaranteed by this function signature
597        unsafe { ptr.as_ref() }
598    }
599
600    #[inline(always)]
601    #[track_caller]
602    unsafe fn from_mut_ptr<'a>(
603        ptr: &'a mut NonNull<Self::PointerType>,
604        _size: &'a mut u32,
605        capacity: u32,
606    ) -> impl DerefMut<Target = Self> + 'a {
607        debug_assert!(ptr.is_aligned(), "Misaligned pointer");
608        debug_assert!(
609            Self::SIZE <= capacity,
610            "Size {} must not exceed capacity {capacity}",
611            Self::SIZE
612        );
613
614        // SAFETY: guaranteed by this function signature
615        unsafe { ptr.as_mut() }
616    }
617
618    #[inline(always)]
619    #[track_caller]
620    unsafe fn try_from_ptr<'a>(
621        ptr: &'a NonNull<Self::PointerType>,
622        size: &'a u32,
623        capacity: u32,
624    ) -> Option<impl Deref<Target = Self> + 'a> {
625        debug_assert!(ptr.is_aligned(), "Misaligned pointer");
626        debug_assert_eq!(*size, T::SIZE, "Invalid size");
627        debug_assert!(
628            *size <= capacity,
629            "Size {size} must not exceed capacity {capacity}"
630        );
631        // SAFETY: `ptr` is valid for reads of `size` bytes, which is the size of `T`, initialized
632        // and not written to during the call (function contract)
633        let bytes = unsafe { slice::from_raw_parts(ptr.as_ptr().cast::<u8>(), size_of::<T>()) };
634        T::try_from_bytes_unaligned(bytes)?;
635
636        // SAFETY: `size` is the size of `T` and doesn't exceed `capacity`, `ptr` is aligned and the
637        // memory is not written to while the returned value exists (function contract), and it
638        // holds a valid value of `T` as checked above
639        Some(unsafe { Self::from_ptr(ptr, size, capacity) })
640    }
641
642    #[inline(always)]
643    #[track_caller]
644    unsafe fn try_from_mut_ptr<'a>(
645        ptr: &'a mut NonNull<Self::PointerType>,
646        size: &'a mut u32,
647        capacity: u32,
648    ) -> Option<impl DerefMut<Target = Self> + 'a> {
649        debug_assert!(ptr.is_aligned(), "Misaligned pointer");
650        debug_assert_eq!(*size, T::SIZE, "Invalid size");
651        debug_assert!(
652            *size <= capacity,
653            "Size {size} must not exceed capacity {capacity}"
654        );
655        // SAFETY: `ptr` is valid for reads of `size` bytes, which is the size of `T`, initialized
656        // and not accessed otherwise during the call (function contract), the slice is not used
657        // after parsing
658        let bytes = unsafe { slice::from_raw_parts(ptr.as_ptr().cast::<u8>(), size_of::<T>()) };
659        T::try_from_bytes_unaligned(bytes)?;
660
661        // SAFETY: `size` is the size of `T` and doesn't exceed `capacity`, `ptr` is aligned and the
662        // memory is not accessed otherwise while the returned value exists (function contract),
663        // and it holds a valid value of `T` as checked above
664        Some(unsafe { Self::from_mut_ptr(ptr, size, capacity) })
665    }
666
667    #[inline(always)]
668    fn as_ptr(&self) -> NonNull<Self::PointerType> {
669        NonNull::from_ref(self)
670    }
671
672    #[inline(always)]
673    fn as_mut_ptr(&mut self) -> NonNull<Self::PointerType> {
674        NonNull::from_mut(self)
675    }
676}