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