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