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