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}