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(Primitive),
78 Mapping {
82 key: Declaration,
83 value: Declaration,
84 },
85 Sequence {
89 decl: Declaration,
92 },
93 FixedSequence {
94 length: u32, decl: Declaration,
98 },
99 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 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 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; fn definition() -> Definition; }
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 ($($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 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}