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#[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 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}