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 #[cfg_attr(feature = "serde", serde(default))]
235 pub type_name: Option<String>,
236 pub template: Option<String>,
237 pub peekable: bool,
238 pub fields: Vec<UnnamedField<L>>,
239}
240
241#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
242#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
243pub struct NamedField<L: LinkingScheme> {
244 pub display_name: String,
245 pub silent: bool,
246 pub value: L::TypeLink,
247 pub doc: String,
248}
249
250#[derive(Clone, Debug, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
251#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
252pub struct UnnamedField<L: LinkingScheme> {
253 pub value: L::TypeLink,
254 pub silent: bool,
255 pub doc: String,
256}
257
258#[derive(Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
259#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
260#[allow(non_camel_case_types)]
261pub enum IntegerType {
262 i8,
263 i16,
264 i32,
265 i64,
266 i128,
267 u8,
268 u16,
269 u32,
270 u64,
271 u128,
272}
273
274impl IntegerType {
275 pub fn size(&self) -> usize {
276 match self {
277 IntegerType::i8 => core::mem::size_of::<i8>(),
278 IntegerType::i16 => core::mem::size_of::<i16>(),
279 IntegerType::i32 => core::mem::size_of::<i32>(),
280 IntegerType::i64 => core::mem::size_of::<i64>(),
281 IntegerType::i128 => core::mem::size_of::<i128>(),
282 IntegerType::u8 => core::mem::size_of::<u8>(),
283 IntegerType::u16 => core::mem::size_of::<u16>(),
284 IntegerType::u32 => core::mem::size_of::<u32>(),
285 IntegerType::u64 => core::mem::size_of::<u64>(),
286 IntegerType::u128 => core::mem::size_of::<u128>(),
287 }
288 }
289}
290
291#[derive(Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
292#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
293pub enum FixedPointDisplay {
294 Decimals(u8),
295 FromSiblingField {
296 field_index: usize,
297 byte_offset: usize,
298 },
299 FromSiblingFieldWithOverride {
304 field_index: usize,
305 byte_offset: usize,
306 override_match: [u8; 32],
307 override_decimals: u8,
308 },
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
312#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
313pub enum IntegerDisplay {
314 Hex,
315 #[default]
316 Decimal,
317 FixedPoint(FixedPointDisplay),
318}
319
320pub trait IntegerDisplayable {
321 fn integer_type() -> IntegerType;
322
323 fn with_display(display: IntegerDisplay) -> Link {
324 Link::Immediate(Primitive::Integer(Self::integer_type(), display))
325 }
326}
327
328macro_rules! integer_displayable {
329 ($t:ident) => {
330 impl IntegerDisplayable for $t {
331 fn integer_type() -> IntegerType {
332 IntegerType::$t
333 }
334 }
335 };
336}
337macro_for_ints!(integer_displayable);
338
339pub trait ByteDisplayable {
340 fn with_display(display: ByteDisplay) -> Link {
341 Link::Immediate(Primitive::ByteVec { display })
342 }
343}
344
345impl<T: OverrideSchema> ByteDisplayable for T
347where
348 T::Output: ByteDisplayable,
349{
350 fn with_display(display: ByteDisplay) -> Link {
351 T::Output::with_display(display)
352 }
353}
354
355impl ByteDisplayable for Vec<u8> {
356 fn with_display(display: ByteDisplay) -> Link {
357 Link::Immediate(Primitive::ByteVec { display })
358 }
359}
360
361impl<const N: usize> ByteDisplayable for [u8; N] {
362 fn with_display(display: ByteDisplay) -> Link {
363 Link::Immediate(Primitive::ByteArray { len: N, display })
364 }
365}
366
367#[derive(Debug, Clone, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
368#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
369pub struct ContainerSerdeMetadata {
370 pub name: String,
371 pub fields_or_variants: Vec<FieldOrVariantSerdeMetadata>,
372}
373
374#[derive(Debug, Clone, PartialEq, Eq, Default, BorshSerialize, BorshDeserialize)]
375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
376pub struct FieldOrVariantSerdeMetadata {
377 pub name: String,
378}