ab_io_type/
trivial_type.rs1use crate::metadata::{IoTypeMetadataKind, MAX_METADATA_CAPACITY, concat_metadata_sources};
2use crate::{DerefWrapper, IoType};
3pub use ab_trivial_type_derive::TrivialType;
4use core::ops::{Deref, DerefMut};
5use core::ptr;
6use core::ptr::NonNull;
7
8pub unsafe trait TrivialType
25where
26 Self: Copy + 'static,
27{
28 const SIZE: u32 = size_of::<Self>() as u32;
29 const METADATA: &[u8];
33
34 #[inline(always)]
43 unsafe fn from_bytes(bytes: &[u8]) -> Option<&Self> {
44 let (before, slice, _) = unsafe { bytes.align_to::<Self>() };
46
47 before.is_empty().then(|| slice.first()).flatten()
48 }
49
50 #[inline(always)]
59 unsafe fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> {
60 let (before, slice, _) = unsafe { bytes.align_to_mut::<Self>() };
62
63 before.is_empty().then(|| slice.first_mut()).flatten()
64 }
65
66 #[inline(always)]
68 fn as_bytes(&self) -> &[u8; size_of::<Self>()] {
69 unsafe { ptr::from_ref(self).cast::<[u8; _]>().as_ref_unchecked() }
71 }
72
73 #[inline(always)]
79 unsafe fn as_bytes_mut(&mut self) -> &mut [u8; size_of::<Self>()] {
80 unsafe { ptr::from_mut(self).cast::<[u8; _]>().as_mut_unchecked() }
82 }
83}
84
85unsafe impl TrivialType for () {
87 const METADATA: &[u8] = &[IoTypeMetadataKind::Unit as u8];
88}
89unsafe impl TrivialType for u8 {
91 const METADATA: &[u8] = &[IoTypeMetadataKind::U8 as u8];
92}
93unsafe impl TrivialType for u16 {
95 const METADATA: &[u8] = &[IoTypeMetadataKind::U16 as u8];
96}
97unsafe impl TrivialType for u32 {
99 const METADATA: &[u8] = &[IoTypeMetadataKind::U32 as u8];
100}
101unsafe impl TrivialType for u64 {
103 const METADATA: &[u8] = &[IoTypeMetadataKind::U64 as u8];
104}
105unsafe impl TrivialType for u128 {
107 const METADATA: &[u8] = &[IoTypeMetadataKind::U128 as u8];
108}
109unsafe impl TrivialType for i8 {
111 const METADATA: &[u8] = &[IoTypeMetadataKind::I8 as u8];
112}
113unsafe impl TrivialType for i16 {
115 const METADATA: &[u8] = &[IoTypeMetadataKind::I16 as u8];
116}
117unsafe impl TrivialType for i32 {
119 const METADATA: &[u8] = &[IoTypeMetadataKind::I32 as u8];
120}
121unsafe impl TrivialType for i64 {
123 const METADATA: &[u8] = &[IoTypeMetadataKind::I64 as u8];
124}
125unsafe impl TrivialType for i128 {
127 const METADATA: &[u8] = &[IoTypeMetadataKind::I128 as u8];
128}
129
130const fn array_metadata(size: u32, inner_metadata: &[u8]) -> ([u8; MAX_METADATA_CAPACITY], usize) {
131 if inner_metadata.len() == 1 && inner_metadata[0] == IoTypeMetadataKind::U8 as u8 {
132 if size == 8 {
133 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x8 as u8]]);
134 } else if size == 16 {
135 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x16 as u8]]);
136 } else if size == 32 {
137 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x32 as u8]]);
138 } else if size == 64 {
139 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x64 as u8]]);
140 } else if size == 128 {
141 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x128 as u8]]);
142 } else if size == 256 {
143 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x256 as u8]]);
144 } else if size == 512 {
145 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x512 as u8]]);
146 } else if size == 1024 {
147 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x1024 as u8]]);
148 } else if size == 2028 {
149 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x2028 as u8]]);
150 } else if size == 4096 {
151 return concat_metadata_sources(&[&[IoTypeMetadataKind::ArrayU8x4096 as u8]]);
152 }
153 }
154
155 let (io_type, size_bytes) = if size < 2u32.pow(8) {
156 (IoTypeMetadataKind::Array8b, 1)
157 } else if size < 2u32.pow(16) {
158 (IoTypeMetadataKind::Array16b, 2)
159 } else {
160 (IoTypeMetadataKind::Array32b, 4)
161 };
162
163 concat_metadata_sources(&[
164 &[io_type as u8],
165 size.to_le_bytes().split_at(size_bytes).0,
166 inner_metadata,
167 ])
168}
169
170unsafe impl<const SIZE: usize, T> TrivialType for [T; SIZE]
174where
175 T: TrivialType,
176{
177 const METADATA: &[u8] = {
178 array_metadata(SIZE as u32, T::METADATA)
180 .0
181 .split_at(array_metadata(SIZE as u32, T::METADATA).1)
182 .0
183 };
184}
185
186unsafe impl<T> IoType for T
188where
189 T: TrivialType,
190{
191 const METADATA: &[u8] = T::METADATA;
192
193 type PointerType = T;
194
195 #[inline(always)]
196 fn size(&self) -> u32 {
197 size_of::<T>() as u32
198 }
199
200 #[inline(always)]
201 unsafe fn size_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
202 DerefWrapper(NonNull::from_ref(&T::SIZE))
203 }
204
205 #[inline(always)]
206 unsafe fn size_mut_ptr(&mut self) -> impl DerefMut<Target = *mut u32> {
207 DerefWrapper(ptr::null_mut())
208 }
209
210 #[inline(always)]
211 fn capacity(&self) -> u32 {
212 self.size()
213 }
214
215 #[inline(always)]
216 unsafe fn capacity_ptr(&self) -> impl Deref<Target = NonNull<u32>> {
217 DerefWrapper(NonNull::from_ref(&Self::SIZE))
218 }
219
220 #[inline(always)]
221 #[track_caller]
222 unsafe fn set_size(&mut self, size: u32) {
223 debug_assert_eq!(size, T::SIZE, "`set_size` called with invalid input");
224 }
225
226 #[inline(always)]
227 #[track_caller]
228 unsafe fn from_ptr<'a>(
229 ptr: &'a NonNull<Self::PointerType>,
230 size: &'a u32,
231 capacity: u32,
232 ) -> impl Deref<Target = Self> + 'a {
233 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
234 debug_assert_eq!(*size, T::SIZE, "Invalid size");
235 debug_assert!(
236 *size <= capacity,
237 "Size {size} must not exceed capacity {capacity}"
238 );
239
240 unsafe { ptr.as_ref() }
242 }
243
244 #[inline(always)]
245 #[track_caller]
246 unsafe fn from_mut_ptr<'a>(
247 ptr: &'a mut NonNull<Self::PointerType>,
248 _size: &'a mut *mut u32,
249 capacity: u32,
250 ) -> impl DerefMut<Target = Self> + 'a {
251 debug_assert!(ptr.is_aligned(), "Misaligned pointer");
252 debug_assert!(
253 Self::SIZE <= capacity,
254 "Size {} must not exceed capacity {capacity}",
255 Self::SIZE
256 );
257
258 unsafe { ptr.as_mut() }
260 }
261
262 #[inline(always)]
263 unsafe fn as_ptr(&self) -> impl Deref<Target = NonNull<Self::PointerType>> {
264 DerefWrapper(NonNull::from_ref(self))
265 }
266
267 #[inline(always)]
268 unsafe fn as_mut_ptr(&mut self) -> impl DerefMut<Target = NonNull<Self::PointerType>> {
269 DerefWrapper(NonNull::from_mut(self))
270 }
271}