casper_contract_schema/
ty.rs

1use core::fmt;
2
3use schemars::JsonSchema;
4use serde::{
5    de::{self, MapAccess, Visitor},
6    ser::{Serialize, SerializeStructVariant, Serializer},
7    Deserialize, Deserializer,
8};
9
10/// CLType representation. It is slight extension of the original CLType enum.
11/// Instead of `Any` variant, it uses `Custom` variant to represent custom
12/// types, that can have name.
13#[derive(PartialEq, PartialOrd, Ord, Eq, Clone, JsonSchema, Debug, Hash)]
14pub enum NamedCLType {
15    Bool,
16    I32,
17    I64,
18    U8,
19    U32,
20    U64,
21    U128,
22    U256,
23    U512,
24    Unit,
25    String,
26    Key,
27    URef,
28    PublicKey,
29    Option(Box<NamedCLType>),
30    List(Box<NamedCLType>),
31    ByteArray(u32),
32    Result {
33        ok: Box<NamedCLType>,
34        err: Box<NamedCLType>,
35    },
36    Map {
37        key: Box<NamedCLType>,
38        value: Box<NamedCLType>,
39    },
40    Tuple1([Box<NamedCLType>; 1]),
41    Tuple2([Box<NamedCLType>; 2]),
42    Tuple3([Box<NamedCLType>; 3]),
43    Custom(String),
44}
45
46impl Serialize for NamedCLType {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: Serializer,
50    {
51        match self {
52            NamedCLType::Bool => serializer.serialize_unit_variant("NamedCLType", 0, "Bool"),
53            NamedCLType::I32 => serializer.serialize_unit_variant("NamedCLType", 1, "I32"),
54            NamedCLType::I64 => serializer.serialize_unit_variant("NamedCLType", 2, "I64"),
55            NamedCLType::U8 => serializer.serialize_unit_variant("NamedCLType", 3, "U8"),
56            NamedCLType::U32 => serializer.serialize_unit_variant("NamedCLType", 4, "U32"),
57            NamedCLType::U64 => serializer.serialize_unit_variant("NamedCLType", 5, "U64"),
58            NamedCLType::U128 => serializer.serialize_unit_variant("NamedCLType", 6, "U128"),
59            NamedCLType::U256 => serializer.serialize_unit_variant("NamedCLType", 7, "U256"),
60            NamedCLType::U512 => serializer.serialize_unit_variant("NamedCLType", 8, "U512"),
61            NamedCLType::Unit => serializer.serialize_unit_variant("NamedCLType", 9, "Unit"),
62            NamedCLType::String => serializer.serialize_unit_variant("NamedCLType", 10, "String"),
63            NamedCLType::Key => serializer.serialize_unit_variant("NamedCLType", 11, "Key"),
64            NamedCLType::URef => serializer.serialize_unit_variant("NamedCLType", 12, "URef"),
65            NamedCLType::PublicKey => {
66                serializer.serialize_unit_variant("NamedCLType", 13, "PublicKey")
67            }
68            NamedCLType::Option(f) => {
69                serializer.serialize_newtype_variant("NamedCLType", 14, "Option", f)
70            }
71            NamedCLType::List(f) => {
72                serializer.serialize_newtype_variant("NamedCLType", 15, "List", f)
73            }
74            NamedCLType::ByteArray(f) => {
75                serializer.serialize_newtype_variant("NamedCLType", 16, "ByteArray", f)
76            }
77            NamedCLType::Result { ok, err } => {
78                let mut s =
79                    serializer.serialize_struct_variant("NamedCLType", 17, "Result", 0 + 1 + 1)?;
80                s.serialize_field("ok", ok)?;
81                s.serialize_field("err", err)?;
82                s.end()
83            }
84            NamedCLType::Map { key, value } => {
85                let mut s =
86                    serializer.serialize_struct_variant("NamedCLType", 18, "Map", 0 + 1 + 1)?;
87                s.serialize_field("key", key)?;
88                s.serialize_field("value", value)?;
89                s.end()
90            }
91            NamedCLType::Tuple1(f) => {
92                serializer.serialize_newtype_variant("NamedCLType", 19, "Tuple1", f)
93            }
94            NamedCLType::Tuple2(f) => {
95                serializer.serialize_newtype_variant("NamedCLType", 20, "Tuple2", f)
96            }
97            NamedCLType::Tuple3(f) => {
98                serializer.serialize_newtype_variant("NamedCLType", 21, "Tuple3", f)
99            }
100            NamedCLType::Custom(name) => serializer.serialize_str(name),
101        }
102    }
103}
104
105impl<'de> Deserialize<'de> for NamedCLType {
106    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
107    where
108        D: Deserializer<'de>,
109    {
110        struct NamedCLTypeVisitor;
111
112        impl<'de> Visitor<'de> for NamedCLTypeVisitor {
113            type Value = NamedCLType;
114
115            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
116                formatter.write_str("a NamedCLType enum as string or map")
117            }
118
119            fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
120            where
121                E: de::Error,
122            {
123                Ok(match value {
124                    "Bool" => NamedCLType::Bool,
125                    "I32" => NamedCLType::I32,
126                    "I64" => NamedCLType::I64,
127                    "U8" => NamedCLType::U8,
128                    "U32" => NamedCLType::U32,
129                    "U64" => NamedCLType::U64,
130                    "U128" => NamedCLType::U128,
131                    "U256" => NamedCLType::U256,
132                    "U512" => NamedCLType::U512,
133                    "Unit" => NamedCLType::Unit,
134                    "String" => NamedCLType::String,
135                    "Key" => NamedCLType::Key,
136                    "URef" => NamedCLType::URef,
137                    "PublicKey" => NamedCLType::PublicKey,
138                    other => NamedCLType::Custom(other.to_string()),
139                })
140            }
141
142            fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
143            where
144                M: MapAccess<'de>,
145            {
146                // Expect a single key => value pair
147                if let Some((key, value)) = access.next_entry::<String, serde_json::Value>()? {
148                    match key.as_str() {
149                        "Option" => {
150                            let inner: NamedCLType =
151                                serde_json::from_value(value).map_err(de::Error::custom)?;
152                            Ok(NamedCLType::Option(Box::new(inner)))
153                        }
154                        "List" => {
155                            let inner: NamedCLType =
156                                serde_json::from_value(value).map_err(de::Error::custom)?;
157                            Ok(NamedCLType::List(Box::new(inner)))
158                        }
159                        "ByteArray" => {
160                            let len: u32 =
161                                serde_json::from_value(value).map_err(de::Error::custom)?;
162                            Ok(NamedCLType::ByteArray(len))
163                        }
164                        "Result" => {
165                            let obj: serde_json::Value = value;
166                            let ok: NamedCLType = serde_json::from_value(
167                                obj.get("ok")
168                                    .cloned()
169                                    .ok_or_else(|| de::Error::missing_field("ok"))?,
170                            )
171                            .map_err(de::Error::custom)?;
172                            let err: NamedCLType = serde_json::from_value(
173                                obj.get("err")
174                                    .cloned()
175                                    .ok_or_else(|| de::Error::missing_field("err"))?,
176                            )
177                            .map_err(de::Error::custom)?;
178                            Ok(NamedCLType::Result {
179                                ok: Box::new(ok),
180                                err: Box::new(err),
181                            })
182                        }
183                        "Map" => {
184                            let obj: serde_json::Value = value;
185                            let key_ty: NamedCLType = serde_json::from_value(
186                                obj.get("key")
187                                    .cloned()
188                                    .ok_or_else(|| de::Error::missing_field("key"))?,
189                            )
190                            .map_err(de::Error::custom)?;
191                            let value_ty: NamedCLType = serde_json::from_value(
192                                obj.get("value")
193                                    .cloned()
194                                    .ok_or_else(|| de::Error::missing_field("value"))?,
195                            )
196                            .map_err(de::Error::custom)?;
197                            Ok(NamedCLType::Map {
198                                key: Box::new(key_ty),
199                                value: Box::new(value_ty),
200                            })
201                        }
202                        "Tuple1" => {
203                            let arr: [NamedCLType; 1] =
204                                serde_json::from_value(value).map_err(de::Error::custom)?;
205                            Ok(NamedCLType::Tuple1([Box::new(arr[0].clone())]))
206                        }
207                        "Tuple2" => {
208                            let arr: [NamedCLType; 2] =
209                                serde_json::from_value(value).map_err(de::Error::custom)?;
210                            Ok(NamedCLType::Tuple2([
211                                Box::new(arr[0].clone()),
212                                Box::new(arr[1].clone()),
213                            ]))
214                        }
215                        "Tuple3" => {
216                            let arr: [NamedCLType; 3] =
217                                serde_json::from_value(value).map_err(de::Error::custom)?;
218                            Ok(NamedCLType::Tuple3([
219                                Box::new(arr[0].clone()),
220                                Box::new(arr[1].clone()),
221                                Box::new(arr[2].clone()),
222                            ]))
223                        }
224                        "Custom" => {
225                            let s: String =
226                                serde_json::from_value(value).map_err(de::Error::custom)?;
227                            Ok(NamedCLType::Custom(s))
228                        }
229                        other => Err(de::Error::unknown_variant(
230                            other,
231                            &[
232                                "Bool",
233                                "String",
234                                "U8",
235                                "U32",
236                                "Option",
237                                "List",
238                                "ByteArray",
239                                "Result",
240                                "Map",
241                                "Tuple1",
242                                "Tuple2",
243                                "Tuple3",
244                                "Custom",
245                            ],
246                        )),
247                    }
248                } else {
249                    Err(de::Error::custom("expected a map with one key"))
250                }
251            }
252        }
253
254        deserializer.deserialize_any(NamedCLTypeVisitor)
255    }
256}