casper_contract_sdk/
abi.rs

1use core::mem;
2
3use crate::prelude::{
4    collections,
5    collections::{BTreeMap, BTreeSet, HashMap, LinkedList},
6    str::FromStr,
7};
8use impl_trait_for_tuples::impl_for_tuples;
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
12pub struct EnumVariant {
13    pub name: String,
14    pub discriminant: u64,
15    pub decl: Declaration,
16}
17
18#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
19pub struct StructField {
20    pub name: String,
21    pub decl: Declaration,
22}
23
24#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
25pub enum Primitive {
26    Char,
27    U8,
28    I8,
29    U16,
30    I16,
31    U32,
32    I32,
33    U64,
34    I64,
35    U128,
36    I128,
37    F32,
38    F64,
39    Bool,
40}
41
42impl FromStr for Primitive {
43    type Err = &'static str;
44
45    fn from_str(s: &str) -> Result<Self, Self::Err> {
46        use Primitive::*;
47        match s {
48            "Char" => Ok(Char),
49            "U8" => Ok(U8),
50            "I8" => Ok(I8),
51            "U16" => Ok(U16),
52            "I16" => Ok(I16),
53            "U32" => Ok(U32),
54            "I32" => Ok(I32),
55            "U64" => Ok(U64),
56            "I64" => Ok(I64),
57            "U128" => Ok(U128),
58            "I128" => Ok(I128),
59            "F32" => Ok(F32),
60            "F64" => Ok(F64),
61            "Bool" => Ok(Bool),
62            _ => Err("Unknown primitive type"),
63        }
64    }
65}
66
67pub trait Keyable {
68    const PRIMITIVE: Primitive;
69}
70
71#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
72#[serde(tag = "type")]
73pub enum Definition {
74    /// Primitive type.
75    ///
76    /// Examples: u64, i32, f32, bool, etc
77    Primitive(Primitive),
78    /// A mapping.
79    ///
80    /// Example Rust types: BTreeMap<K, V>.
81    Mapping {
82        key: Declaration,
83        value: Declaration,
84    },
85    /// Arbitrary sequence of values.
86    ///
87    /// Example Rust types: `Vec<T>`, `&[T]`, `[T; N]`, `Box<[T]>`
88    Sequence {
89        /// If length is known, then it specifies that this definition should be be represented as
90        /// an array of a fixed size.
91        decl: Declaration,
92    },
93    FixedSequence {
94        /// If length is known, then it specifies that this definition should be be represented as
95        /// an array of a fixed size.
96        length: u32, // None -> Vec<T> Some(N) [T; N]
97        decl: Declaration,
98    },
99    /// A tuple of multiple values of various types.
100    ///
101    /// Can be also used to represent a heterogeneous list.
102    Tuple {
103        items: Vec<Declaration>,
104    },
105    Enum {
106        items: Vec<EnumVariant>,
107    },
108    Struct {
109        items: Vec<StructField>,
110    },
111}
112
113impl Definition {
114    pub fn unit() -> Self {
115        // Empty struct should be equivalent to `()` in Rust in other languages.
116        Definition::Tuple { items: Vec::new() }
117    }
118
119    pub fn as_struct(&self) -> Option<&[StructField]> {
120        if let Self::Struct { items } = self {
121            Some(items.as_slice())
122        } else {
123            None
124        }
125    }
126
127    pub fn as_enum(&self) -> Option<&[EnumVariant]> {
128        if let Self::Enum { items } = self {
129            Some(items.as_slice())
130        } else {
131            None
132        }
133    }
134
135    pub fn as_tuple(&self) -> Option<&[Declaration]> {
136        if let Self::Tuple { items } = self {
137            Some(items.as_slice())
138        } else {
139            None
140        }
141    }
142}
143
144#[derive(Default, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
145pub struct Definitions(BTreeMap<Declaration, Definition>);
146
147impl Definitions {
148    pub fn populate_one<T: CasperABI>(&mut self) {
149        T::populate_definitions(self);
150
151        let decl = T::declaration();
152        let def = T::definition();
153
154        self.populate_custom(decl, def);
155    }
156
157    pub fn populate_custom(&mut self, decl: Declaration, def: Definition) {
158        let previous = self.0.insert(decl.clone(), def.clone());
159        if previous.is_some() && previous != Some(def.clone()) {
160            panic!("Type {decl} has multiple definitions ({previous:?} != {def:?}).");
161        }
162    }
163
164    pub fn iter(&self) -> impl Iterator<Item = (&Declaration, &Definition)> {
165        self.0.iter()
166    }
167
168    pub fn get(&self, decl: &str) -> Option<&Definition> {
169        self.0.get(decl)
170    }
171
172    pub fn first(&self) -> Option<(&Declaration, &Definition)> {
173        self.0.iter().next()
174    }
175
176    /// Returns true if the given declaration has a definition in this set.
177    pub fn has_definition(&self, decl: &Declaration) -> bool {
178        self.0.contains_key(decl)
179    }
180}
181
182impl IntoIterator for Definitions {
183    type Item = (Declaration, Definition);
184    type IntoIter = collections::btree_map::IntoIter<Declaration, Definition>;
185
186    fn into_iter(self) -> Self::IntoIter {
187        self.0.into_iter()
188    }
189}
190
191pub type Declaration = String;
192
193pub trait CasperABI {
194    fn populate_definitions(definitions: &mut Definitions);
195    fn declaration() -> Declaration; // "String"
196    fn definition() -> Definition; // Sequence { Char }
197}
198
199impl<T> CasperABI for &T
200where
201    T: CasperABI,
202{
203    fn populate_definitions(definitions: &mut Definitions) {
204        T::populate_definitions(definitions);
205    }
206
207    fn declaration() -> Declaration {
208        T::declaration()
209    }
210
211    fn definition() -> Definition {
212        T::definition()
213    }
214}
215
216impl<T> CasperABI for Box<T>
217where
218    T: CasperABI,
219{
220    fn populate_definitions(definitions: &mut Definitions) {
221        T::populate_definitions(definitions);
222    }
223
224    fn declaration() -> Declaration {
225        T::declaration()
226    }
227
228    fn definition() -> Definition {
229        T::definition()
230    }
231}
232
233macro_rules! impl_abi_for_types {
234    // Accepts following syntax: impl_abi_for_types(u8, u16, u32, u64, String => "string", f32, f64)
235    ($($ty:ty $(=> $name:expr)?,)* ) => {
236        $(
237            impl_abi_for_types!(@impl $ty $(=> $name)?);
238        )*
239    };
240
241    (@impl $ty:ty ) => {
242       impl_abi_for_types!(@impl $ty => stringify!($ty));
243    };
244
245    (@impl $ty:ty => $def:expr ) => {
246        impl CasperABI for $ty {
247            fn populate_definitions(_definitions: &mut Definitions) {
248            }
249
250            fn declaration() -> Declaration {
251                stringify!($def).into()
252            }
253
254            fn definition() -> Definition {
255                use Primitive::*;
256                const PRIMITIVE: Primitive = $def;
257                Definition::Primitive(PRIMITIVE)
258            }
259        }
260
261        impl Keyable for $ty {
262            const PRIMITIVE: Primitive = {
263                use Primitive::*;
264                $def
265            };
266        }
267    };
268}
269
270impl CasperABI for () {
271    fn populate_definitions(_definitions: &mut Definitions) {}
272
273    fn declaration() -> Declaration {
274        "()".into()
275    }
276
277    fn definition() -> Definition {
278        Definition::unit()
279    }
280}
281
282impl_abi_for_types!(
283    char => Char,
284    bool => Bool,
285    u8 => U8,
286    u16 => U16,
287    u32 => U32,
288    u64 => U64,
289    u128 => U128,
290    i8 => I8,
291    i16 => I16,
292    i32 => I32,
293    i64 => I64,
294    f32 => F32,
295    f64 => F64,
296    i128 => I128,
297);
298
299#[impl_for_tuples(1, 12)]
300impl CasperABI for Tuple {
301    fn populate_definitions(_definitions: &mut Definitions) {
302        for_tuples!( #( _definitions.populate_one::<Tuple>(); )* )
303    }
304
305    fn declaration() -> Declaration {
306        let items = <[_]>::into_vec(Box::new([for_tuples!( #( Tuple::declaration() ),* )]));
307        format!("({})", items.join(", "))
308    }
309
310    fn definition() -> Definition {
311        let items = <[_]>::into_vec(Box::new([for_tuples!( #( Tuple::declaration() ),* )]));
312        Definition::Tuple { items }
313    }
314}
315
316impl<T: CasperABI, E: CasperABI> CasperABI for Result<T, E> {
317    fn populate_definitions(definitions: &mut Definitions) {
318        definitions.populate_one::<T>();
319        definitions.populate_one::<E>();
320    }
321
322    fn declaration() -> Declaration {
323        let t_decl = T::declaration();
324        let e_decl = E::declaration();
325        format!("Result<{t_decl}, {e_decl}>")
326    }
327
328    fn definition() -> Definition {
329        Definition::Enum {
330            items: vec![
331                EnumVariant {
332                    name: "Ok".into(),
333                    discriminant: 0,
334                    decl: T::declaration(),
335                },
336                EnumVariant {
337                    name: "Err".into(),
338                    discriminant: 1,
339                    decl: E::declaration(),
340                },
341            ],
342        }
343    }
344}
345
346impl<T: CasperABI> CasperABI for Option<T> {
347    fn declaration() -> Declaration {
348        format!("Option<{}>", T::declaration())
349    }
350    fn definition() -> Definition {
351        Definition::Enum {
352            items: vec![
353                EnumVariant {
354                    name: "None".into(),
355                    discriminant: 0,
356                    decl: <()>::declaration(),
357                },
358                EnumVariant {
359                    name: "Some".into(),
360                    discriminant: 1,
361                    decl: T::declaration(),
362                },
363            ],
364        }
365    }
366
367    fn populate_definitions(definitions: &mut Definitions) {
368        definitions.populate_one::<()>();
369        definitions.populate_one::<T>();
370    }
371}
372
373impl<T: CasperABI> CasperABI for Vec<T> {
374    fn populate_definitions(definitions: &mut Definitions) {
375        definitions.populate_one::<T>();
376    }
377
378    fn declaration() -> Declaration {
379        format!("Vec<{}>", T::declaration())
380    }
381    fn definition() -> Definition {
382        Definition::Sequence {
383            decl: T::declaration(),
384        }
385    }
386}
387
388impl<T: CasperABI, const N: usize> CasperABI for [T; N] {
389    fn populate_definitions(definitions: &mut Definitions) {
390        definitions.populate_one::<T>();
391    }
392
393    fn declaration() -> Declaration {
394        format!("[{}; {N}]", T::declaration())
395    }
396    fn definition() -> Definition {
397        Definition::FixedSequence {
398            length: N.try_into().expect("N is too big"),
399            decl: T::declaration(),
400        }
401    }
402}
403
404impl<K: CasperABI, V: CasperABI> CasperABI for BTreeMap<K, V> {
405    fn populate_definitions(definitions: &mut Definitions) {
406        definitions.populate_one::<K>();
407        definitions.populate_one::<V>();
408    }
409
410    fn declaration() -> Declaration {
411        format!("BTreeMap<{}, {}>", K::declaration(), V::declaration())
412    }
413
414    fn definition() -> Definition {
415        Definition::Mapping {
416            key: K::declaration(),
417            value: V::declaration(),
418        }
419    }
420}
421
422impl<K: CasperABI, V: CasperABI> CasperABI for HashMap<K, V> {
423    fn populate_definitions(definitions: &mut Definitions) {
424        definitions.populate_one::<K>();
425        definitions.populate_one::<V>();
426    }
427
428    fn declaration() -> Declaration {
429        format!("HashMap<{}, {}>", K::declaration(), V::declaration())
430    }
431
432    fn definition() -> Definition {
433        Definition::Mapping {
434            key: K::declaration(),
435            value: V::declaration(),
436        }
437    }
438}
439
440impl CasperABI for String {
441    fn populate_definitions(_definitions: &mut Definitions) {}
442
443    fn declaration() -> Declaration {
444        "String".into()
445    }
446    fn definition() -> Definition {
447        Definition::Sequence {
448            decl: char::declaration(),
449        }
450    }
451}
452
453impl CasperABI for str {
454    fn populate_definitions(_definitions: &mut Definitions) {}
455
456    fn declaration() -> Declaration {
457        "String".into()
458    }
459    fn definition() -> Definition {
460        Definition::Sequence {
461            decl: char::declaration(),
462        }
463    }
464}
465
466impl CasperABI for &str {
467    fn populate_definitions(_definitions: &mut Definitions) {}
468
469    fn declaration() -> Declaration {
470        "String".into()
471    }
472
473    fn definition() -> Definition {
474        Definition::Sequence {
475            decl: char::declaration(),
476        }
477    }
478}
479
480impl<T: CasperABI> CasperABI for LinkedList<T> {
481    fn populate_definitions(definitions: &mut Definitions) {
482        definitions.populate_one::<T>();
483    }
484
485    fn declaration() -> Declaration {
486        format!("LinkedList<{}>", T::declaration())
487    }
488    fn definition() -> Definition {
489        Definition::Sequence {
490            decl: T::declaration(),
491        }
492    }
493}
494
495impl<T: CasperABI> CasperABI for BTreeSet<T> {
496    fn populate_definitions(definitions: &mut Definitions) {
497        definitions.populate_one::<T>();
498    }
499
500    fn declaration() -> Declaration {
501        format!("BTreeSet<{}>", T::declaration())
502    }
503    fn definition() -> Definition {
504        Definition::Sequence {
505            decl: T::declaration(),
506        }
507    }
508}
509
510impl<const N: usize> CasperABI for bnum::BUint<N> {
511    fn populate_definitions(definitions: &mut Definitions) {
512        definitions.populate_one::<u64>();
513    }
514
515    fn declaration() -> Declaration {
516        let width_bytes: usize = mem::size_of::<bnum::BUint<N>>();
517        let width_bits: usize = width_bytes * 8;
518        format!("U{width_bits}")
519    }
520
521    fn definition() -> Definition {
522        let length: u32 = N.try_into().expect("N is too big");
523        Definition::FixedSequence {
524            length,
525            decl: u64::declaration(),
526        }
527    }
528}
529
530#[cfg(test)]
531mod tests {
532    use crate::{
533        abi::{CasperABI, Definition},
534        types::U256,
535    };
536
537    #[test]
538    fn u256_schema() {
539        assert_eq!(U256::declaration(), "U256");
540        assert_eq!(
541            U256::definition(),
542            Definition::FixedSequence {
543                length: 4,
544                decl: u64::declaration()
545            }
546        );
547
548        let mut value = U256::from(u128::MAX);
549        value += U256::from(1u64);
550        let bytes = borsh::to_vec(&value).unwrap();
551        // Ensure bnum's borsh serialize/deserialize is what we consider "FixedSequence"
552        let bytes_back: [u64; 4] = borsh::from_slice(&bytes).unwrap();
553        let value_back = U256::from_digits(bytes_back);
554        assert_eq!(value, value_back);
555    }
556}