ab_io_type/
trivial_type.rs1use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
2use crate::unaligned::Unaligned;
3use crate::{DerefWrapper, IoType};
4pub use ab_io_type_derive::TrivialType;
5use core::ops::{Deref, DerefMut};
6use core::ptr;
7use core::ptr::NonNull;
8
9const SIZE_OF<T>: usize = size_of::<T>();
10
11pub unsafe trait TrivialType
28where
29 Self: Copy,
30{
31 const SIZE: u32 = size_of::<Self>() as u32;
32 const METADATA: &[u8];
35
36 #[inline(always)]
45 unsafe fn read_unaligned(bytes: &[u8]) -> Option<Self> {
46 Some(unsafe { Unaligned::<Self>::from_bytes(bytes)?.as_inner() })
48 }
49
50 #[inline(always)]
55 unsafe fn read_unaligned_unchecked(bytes: &[u8]) -> Self {
56 unsafe { Unaligned::<Self>::from_bytes_unchecked(bytes).as_inner() }
58 }
59
60 #[inline(always)]
70 unsafe fn from_bytes(bytes: &[u8]) -> Option<&Self> {
71 let (before, slice, _) = unsafe { bytes.align_to::<Self>() };
73
74 before.is_empty().then(|| slice.first()).flatten()
75 }
76
77 #[inline(always)]
82 unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
83 unsafe { bytes.as_ptr().cast::<Self>().as_ref_unchecked() }
85 }
86
87 #[inline(always)]
97 unsafe fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
98 let (before, slice, _) = unsafe { bytes.align_to_mut::<Self>() };
100
101 before.is_empty().then(|| slice.first_mut()).flatten()
102 }
103
104 #[inline(always)]
109 unsafe fn from_bytes_mut_unchecked(bytes: &mut [u8]) -> &mut Self {
110 unsafe { bytes.as_mut_ptr().cast::<Self>().as_mut_unchecked() }
112 }
113
114 #[inline(always)]
116 fn as_bytes(&self) -> &[u8; SIZE_OF::<Self>] {
117 unsafe { ptr::from_ref(self).cast::<[u8; _]>().as_ref_unchecked() }
119 }
120
121 #[inline(always)]
127 unsafe fn as_bytes_mut(&mut self) -> &mut [u8; SIZE_OF::<Self>] {
128 unsafe { ptr::from_mut(self).cast::<[u8; _]>().as_mut_unchecked() }
130 }
131}
132
133unsafe impl TrivialType for () {
135 const METADATA: &[u8] = &[IoTypeMetadataKind::Unit as u8];
136}
137unsafe impl TrivialType for u8 {
139 const METADATA: &[u8] = &[IoTypeMetadataKind::U8 as u8];
140}
141unsafe impl TrivialType for u16 {
143 const METADATA: &[u8] = &[IoTypeMetadataKind::U16 as u8];
144}
145unsafe impl TrivialType for u32 {
147 const METADATA: &[u8] = &[IoTypeMetadataKind::U32 as u8];
148}
149unsafe impl TrivialType for u64 {
151 const METADATA: &[u8] = &[IoTypeMetadataKind::U64 as u8];
152}
153unsafe impl TrivialType for u128 {
155 const METADATA: &[u8] = &[IoTypeMetadataKind::U128 as u8];
156}
157unsafe impl TrivialType for i8 {
159 const METADATA: &[u8] = &[IoTypeMetadataKind::I8 as u8];
160}
161unsafe impl TrivialType for i16 {
163 const METADATA: &[u8] = &[IoTypeMetadataKind::I16 as u8];
164}
165unsafe impl TrivialType for i32 {
167 const METADATA: &[u8] = &[IoTypeMetadataKind::I32 as u8];
168}
169unsafe impl TrivialType for i64 {
171 const METADATA: &[u8] = &[IoTypeMetadataKind::I64 as u8];
172}
173unsafe impl TrivialType for i128 {
175 const METADATA: &[u8] = &[IoTypeMetadataKind::I128 as u8];
176}
177
178const fn array_metadata(size: u32, inner_metadata: &[u8]) -> ([u8; MAX_METADATA_CAPACITY], usize) {
179 if inner_metadata.len() == 1 && inner_metadata[0] == IoTypeMetadataKind::U8 as u8 {
180 if size == 8 {
181 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x8 as u8]]);
182 } else if size == 16 {
183 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x16 as u8]]);
184 } else if size == 32 {
185 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x32 as u8]]);
186 } else if size == 64 {
187 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x64 as u8]]);
188 } else if size == 128 {
189 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x128 as u8]]);
190 } else if size == 256 {
191 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x256 as u8]]);
192 } else if size == 512 {
193 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x512 as u8]]);
194 } else if size == 1024 {
195 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x1024 as u8]]);
196 } else if size == 2028 {
197 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x2028 as u8]]);
198 } else if size == 4096 {
199 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x4096 as u8]]);
200 }
201 }
202
203 let (io_type, size_bytes) = if size < 2u32.pow(8) {
204 (IoTypeMetadataKind::Array8b, 1)
205 } else if size < 2u32.pow(16) {
206 (IoTypeMetadataKind::Array16b, 2)
207 } else {
208 (IoTypeMetadataKind::Array32b, 4)
209 };
210
211 concat_metadata_sources(&[
212 &[io_type as u8],
213 size.to_le_bytes().split_at(size_bytes).0,
214 inner_metadata,
215 ])
216}
217
218unsafe impl<const SIZE: usize, T> TrivialType for [T; SIZE]
222where
223 T: TrivialType,
224{
225 const METADATA: &[u8] = {
226 array_metadata(SIZE as u32, T::METADATA)
228 .0
229 .split_at(array_metadata(SIZE as u32, T::METADATA).1)
230 .0
231 };
232}
233
234unsafe impl<T> IoType for T
236where
237 T: TrivialType,
238{
239 const METADATA: &[u8] = T::METADATA;
240
241 type PointerType = T;
242
243 #[inline(always)]
244 fn size(&self) -> u32 {
245 size_of::<T>() as u32
246 }
247
248 #[inline(always)]
249 fn capacity(&self) -> u32 {
250 self.size()
251 }
252
253 #[inline(always)]
254 #[track_caller]
255 unsafe fn set_size(&mut self, size: u32) {
256 debug_assert_eq!(size, T::SIZE, "`set_size` called with invalid input");
257 }
258
259 #[inline(always)]
260 #[track_caller]
261 unsafe fn from_ptr<'a>(
262 ptr: &'a NonNull<Self::PointerType>,
263 size: &'a u32,
264 capacity: u32,
265 ) -> impl Deref<Target = Self> + 'a {
266 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
267 debug_assert_eq!(*size, T::SIZE, "Invalid size");
268 debug_assert!(
269 *size <= capacity,
270 "Size {size} must not exceed capacity {capacity}"
271 );
272
273 unsafe { ptr.as_ref() }
275 }
276
277 #[inline(always)]
278 #[track_caller]
279 unsafe fn from_mut_ptr<'a>(
280 ptr: &'a mut NonNull<Self::PointerType>,
281 _size: &'a mut u32,
282 capacity: u32,
283 ) -> impl DerefMut<Target = Self> + 'a {
284 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
285 debug_assert!(
286 Self::SIZE <= capacity,
287 "Size {} must not exceed capacity {capacity}",
288 Self::SIZE
289 );
290
291 unsafe { ptr.as_mut() }
293 }
294
295 #[inline(always)]
296 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
297 DerefWrapper(NonNull::from_ref(self))
298 }
299
300 #[inline(always)]
301 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
302 DerefWrapper(NonNull::from_mut(self))
303 }
304}