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