1pub mod byte_display;
2pub mod visitor;
3use core::panic;
4use std::fmt::Debug;
5
6use borsh::{BorshDeserialize, BorshSerialize};
7pub use byte_display::ByteDisplay;
8#[cfg(feature = "serde")]
9use serde::{de::DeserializeOwned, Deserialize, Serialize};
10
11use crate::schema::{IndexLinking, Link, OverrideSchema, Primitive};
12
13macro_rules! macro_for_ints {
14 ($macro:ident) => {
15 $macro!(u8);
16 $macro!(u16);
17 $macro!(u32);
18 $macro!(u64);
19 $macro!(u128);
20 $macro!(i8);
21 $macro!(i16);
22 $macro!(i32);
23 $macro!(i64);
24 $macro!(i128);
25 };
26}
27pub(crate) use macro_for_ints;
28
29pub trait LinkingScheme: Clone + Debug {
30 #[cfg(not(feature = "serde"))]
33 type TypeLink: Clone + Debug + PartialEq + Eq + BorshSerialize + BorshDeserialize;
34 #[cfg(feature = "serde")]
35 type TypeLink: Clone
36 + Debug
37 + PartialEq
38 + Eq
39 + BorshSerialize
40 + BorshDeserialize
41 + Serialize
42 + DeserializeOwned;
43}
44
45#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47pub enum Ty<L: LinkingScheme> {
48 Enum(Enum<L>),
49 Struct(Struct<L>),
50 Tuple(Tuple<L>),
51 Option {
52 value: L::TypeLink,
53 },
54 Integer(IntegerType, IntegerDisplay),
55 ByteArray {
56 len: usize,
57 display: ByteDisplay,
58 },
59 Float32,
60 Float64,
61 String,
62 Boolean,
63 Skip {
64 len: usize,
65 },
66 ByteVec {
67 display: ByteDisplay,
68 },
69 Array {
70 len: usize,
71 value: L::TypeLink,
72 },
73 Vec {
74 value: L::TypeLink,
75 },
76 Map {
77 key: L::TypeLink,
78 value: L::TypeLink,
79 },
80}
81
82impl<L: LinkingScheme> Ty<L> {
83 pub fn is_skip(&self) -> bool {
85 matches!(self, Ty::Skip { .. })
86 }
87}
88
89impl Ty<IndexLinking> {
90 pub fn fill_next_placholder(&mut self, child: Link) {
92 let err_msg =
93 format!("Called `fill_next_placholder` on a type with no placeholders: {self:?}");
94 match self {
95 Ty::Enum(e) => {
96 e.variants
97 .iter_mut()
98 .find(|v| v.value == Some(Link::Placeholder))
99 .expect(&err_msg).value = Some(child);
100 }
101 Ty::Struct(s) => {
102 s.fields
103 .iter_mut()
104 .find(|field| field.value == Link::Placeholder)
105 .expect(&err_msg)
106 .value = child;
107 }
108 Ty::Tuple(t) => {
109 t.fields
110 .iter_mut()
111 .find(|field| field.value == Link::Placeholder)
112 .expect(&err_msg)
113 .value = child;
114 }
115 Ty::Option { value } => if *value == Link::Placeholder {
116 *value = child;
117 } else {
118 panic!("{}", err_msg);
119 }
120 Ty::Array { value, .. } => {
121 if *value == Link::Placeholder {
122 *value = child;
123 } else {
124 panic!("{}", err_msg);
125 }
126 }
127 Ty::Vec { value } => if *value == Link::Placeholder {
128 *value = child;
129 } else {
130 panic!("{}", err_msg);
131 }
132 Ty::Map { key, value } => if *key == Link::Placeholder {
133 *key = child;
134 } else if *value == Link::Placeholder {
135 *value = child;
136 } else {
137 panic!("{}", err_msg);
138 }
139 _ => panic!(
140 "Tried to fill a placholder on a type with no children. Only Vec, Tuple, Option, Array, Struct and Map types have children. Self: {:?}",
141 self
142 ),
143 }
144 }
145}
146
147impl<L: LinkingScheme> Ty<L> {
148 pub fn is_primitive(&self) -> bool {
149 match self {
151 Ty::Enum(_)
152 | Ty::Struct(_)
153 | Ty::Tuple(_)
154 | Ty::Option { .. }
155 | Ty::Array { .. }
156 | Ty::Vec { .. }
157 | Ty::Map { .. } => false,
158 Ty::Integer(_, _)
159 | Ty::ByteArray { .. }
160 | Ty::ByteVec { .. }
161 | Ty::String
162 | Ty::Float32
163 | Ty::Float64
164 | Ty::Boolean
165 | Ty::Skip { .. } => true,
166 }
167 }
168
169 pub fn parent_byte_references(&self) -> Vec<(usize, usize)> {
170 match self {
171 Ty::Integer(
172 _,
173 IntegerDisplay::FixedPoint(FixedPointDisplay::FromSiblingField {
174 field_index,
175 byte_offset,
176 }),
177 ) => vec![(*field_index, *byte_offset)],
178 Ty::Integer(
179 _,
180 IntegerDisplay::FixedPoint(FixedPointDisplay::FromSiblingFieldWithOverride {
181 field_index,
182 ..
183 }),
184 ) => {
185 (0..32).map(|i| (*field_index, i)).collect()
189 }
190 _ => Vec::new(),
191 }
192 }
193}
194
195#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
199#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
200pub struct EnumVariant<L: LinkingScheme> {
201 pub name: String,
202 pub discriminant: u8,
203 pub template: Option<String>,
204 pub value: Option<L::TypeLink>,
205}
206
207#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
209pub struct Enum<L: LinkingScheme> {
210 pub type_name: String,
211 pub variants: Vec<EnumVariant<L>>,
212 pub hide_tag: bool,
214}
215
216#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
218pub struct Struct<L: LinkingScheme> {
219 pub type_name: String,
220 pub template: Option<String>,
221 pub peekable: bool,
222 pub fields: Vec<NamedField<L>>,
223}
224
225#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
226#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
227pub struct Tuple<L: LinkingScheme> {
228 pub template: Option<String>,
229 pub peekable: bool,
230 pub fields: Vec<UnnamedField<L>>,
231}
232
233#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
234#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
235pub struct NamedField<L: LinkingScheme> {
236 pub display_name: String,
237 pub silent: bool,
238 pub value: L::TypeLink,
239 pub doc: String,
240}
241
242#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
244pub struct UnnamedField<L: LinkingScheme> {
245 pub value: L::TypeLink,
246 pub silent: bool,
247 pub doc: String,
248}
249
250#[derive(Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
252#[allow(non_camel_case_types)]
253pub enum IntegerType {
254 i8,
255 i16,
256 i32,
257 i64,
258 i128,
259 u8,
260 u16,
261 u32,
262 u64,
263 u128,
264}
265
266impl IntegerType {
267 pub fn size(&self) -> usize {
268 match self {
269 IntegerType::i8 => core::mem::size_of::<i8>(),
270 IntegerType::i16 => core::mem::size_of::<i16>(),
271 IntegerType::i32 => core::mem::size_of::<i32>(),
272 IntegerType::i64 => core::mem::size_of::<i64>(),
273 IntegerType::i128 => core::mem::size_of::<i128>(),
274 IntegerType::u8 => core::mem::size_of::<u8>(),
275 IntegerType::u16 => core::mem::size_of::<u16>(),
276 IntegerType::u32 => core::mem::size_of::<u32>(),
277 IntegerType::u64 => core::mem::size_of::<u64>(),
278 IntegerType::u128 => core::mem::size_of::<u128>(),
279 }
280 }
281}
282
283#[derive(Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
285pub enum FixedPointDisplay {
286 Decimals(u8),
287 FromSiblingField {
288 field_index: usize,
289 byte_offset: usize,
290 },
291 FromSiblingFieldWithOverride {
296 field_index: usize,
297 byte_offset: usize,
298 override_match: [u8; 32],
299 override_decimals: u8,
300 },
301}
302
303#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
304#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
305pub enum IntegerDisplay {
306 Hex,
307 #[default]
308 Decimal,
309 FixedPoint(FixedPointDisplay),
310}
311
312pub trait IntegerDisplayable {
313 fn integer_type() -> IntegerType;
314
315 fn with_display(display: IntegerDisplay) -> Link {
316 Link::Immediate(Primitive::Integer(Self::integer_type(), display))
317 }
318}
319
320macro_rules! integer_displayable {
321 ($t:ident) => {
322 impl IntegerDisplayable for $t {
323 fn integer_type() -> IntegerType {
324 IntegerType::$t
325 }
326 }
327 };
328}
329macro_for_ints!(integer_displayable);
330
331pub trait ByteDisplayable {
332 fn with_display(display: ByteDisplay) -> Link {
333 Link::Immediate(Primitive::ByteVec { display })
334 }
335}
336
337impl<T: OverrideSchema> ByteDisplayable for T
339where
340 T::Output: ByteDisplayable,
341{
342 fn with_display(display: ByteDisplay) -> Link {
343 T::Output::with_display(display)
344 }
345}
346
347impl ByteDisplayable for Vec<u8> {
348 fn with_display(display: ByteDisplay) -> Link {
349 Link::Immediate(Primitive::ByteVec { display })
350 }
351}
352
353impl<const N: usize> ByteDisplayable for [u8; N] {
354 fn with_display(display: ByteDisplay) -> Link {
355 Link::Immediate(Primitive::ByteArray { len: N, display })
356 }
357}
358
359#[derive(Debug, Clone, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
360#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
361pub struct ContainerSerdeMetadata {
362 pub name: String,
363 pub fields_or_variants: Vec<FieldOrVariantSerdeMetadata>,
364}
365
366#[derive(Debug, Clone, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
367#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
368pub struct FieldOrVariantSerdeMetadata {
369 pub name: String,
370}