1use std::fmt::{self, Display};
2
3#[derive(Debug, Clone)]
4pub enum Type {
5 Address,
6 FixedBytes(usize),
7 Bytes,
8 Int(usize),
9 Uint(usize),
10 Bool,
11 String,
12 FixedArray(Box<Type>, usize),
13 Array(Box<Type>),
14 Tuple(Vec<Type>),
15}
16
17pub type SchemaPart = Vec<(String, Type)>;
18
19pub struct Schema {
20 parts: SchemaPart,
21}
22
23pub struct SchemaBuilder {
24 parts: SchemaPart,
25}
26
27impl Default for SchemaBuilder {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl SchemaBuilder {
34 pub fn new() -> Self {
35 SchemaBuilder { parts: vec![] }
36 }
37
38 pub fn add(mut self, name: &str, token_type: Type) -> Self {
39 self.parts.push((name.to_owned(), token_type));
40 self
41 }
42
43 pub fn build(self) -> Schema {
44 Schema { parts: self.parts }
45 }
46}
47
48fn token_type_to_abi_type(token_type: &Type) -> String {
49 match token_type {
50 Type::Address => "address".into(),
51 Type::FixedBytes(size) => format!("bytes{}", size),
52 Type::Bytes => "bytes".into(),
53 Type::Int(size) => format!("int{}", size),
54 Type::Uint(size) => format!("uint{}", size),
55 Type::Bool => "bool".into(),
56 Type::String => "string".into(),
57 Type::FixedArray(token_type, size) => {
58 format!("{}[{}]", token_type_to_abi_type(token_type), size)
59 }
60 Type::Array(token_type) => {
61 format!("{}[]", token_type_to_abi_type(token_type))
62 }
63 Type::Tuple(types) => {
64 let inner_types = types
65 .iter()
66 .map(token_type_to_abi_type)
67 .collect::<Vec<String>>()
68 .join(",");
69 format!("({})", inner_types)
70 }
71 }
72}
73
74impl Display for Schema {
75 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76 let parts = self
77 .parts
78 .iter()
79 .map(|(name, token_type)| format!("{} {}", token_type_to_abi_type(token_type), name))
80 .collect::<Vec<String>>()
81 .join(", ");
82 write!(f, "{}", parts)
83 }
84}
85
86impl From<Schema> for String {
87 fn from(schema: Schema) -> Self {
88 schema.to_string()
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use crate::schema::{SchemaBuilder, Type};
95
96 #[test]
97 fn schema_test() {
98 let schema = SchemaBuilder::new()
99 .add("name", Type::String)
100 .add("age", Type::Uint(8))
101 .add("address", Type::Address)
102 .add("data", Type::FixedArray(Box::new(Type::Uint(8)), 3))
103 .add("data2", Type::Array(Box::new(Type::Uint(8))))
104 .add("data3", Type::Tuple(vec![Type::Uint(8), Type::Uint(8)]))
105 .build();
106 assert_eq!(schema.to_string(), "string name, uint8 age, address address, uint8[3] data, uint8[] data2, (uint8,uint8) data3");
107 }
108}