openzeppelin_monitor/utils/macros/
deserialization.rs1#[macro_export]
15macro_rules! impl_case_insensitive_enum {
16 ($enum_name:ident, { $($variant_str:expr => $variant:ident),* $(,)? }) => {
17 impl<'de> ::serde::Deserialize<'de> for $enum_name {
18 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
19 where
20 D: ::serde::Deserializer<'de>,
21 {
22 use ::serde::de::{self, MapAccess, Visitor};
23 use std::fmt;
24
25 struct EnumVisitor;
26
27 impl<'de> Visitor<'de> for EnumVisitor {
28 type Value = $enum_name;
29
30 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
31 formatter.write_str(concat!("a struct with a `type` field for ", stringify!($enum_name)))
32 }
33
34 fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
35 where
36 M: MapAccess<'de>,
37 {
38 let mut type_: Option<String> = None;
39 let mut value: Option<::serde_json::Value> = None;
40
41 while let Some(key) = map.next_key::<String>()? {
42 if key == "type" {
43 type_ = Some(map.next_value()?);
44 } else if key == "value" {
45 value = Some(map.next_value()?);
46 } else {
47 let _: ::serde_json::Value = map.next_value()?;
48 }
49 }
50
51 let type_ = type_.ok_or_else(|| de::Error::missing_field("type"))?;
52 let value = value.ok_or_else(|| de::Error::missing_field("value"))?;
53 let type_lowercase = type_.to_lowercase();
54
55 match type_lowercase.as_str() {
56 $(
57 $variant_str => {
58 let content = ::serde_json::from_value::<String>(value)
59 .map_err(|e| de::Error::custom(format!(
60 concat!("invalid ", $variant_str, " value: {}"), e
61 )))?;
62 Ok($enum_name::$variant(content.into()))
63 },
64 )*
65 _ => Err(de::Error::unknown_variant(
66 &type_,
67 &[$($variant_str),*],
68 )),
69 }
70 }
71 }
72
73 deserializer.deserialize_map(EnumVisitor)
74 }
75 }
76 };
77}
78
79#[macro_export]
84macro_rules! impl_case_insensitive_enum_struct {
85 ($enum_name:ident, { $($variant_str:expr => $variant:ident),* $(,)? }) => {
86 impl<'de> ::serde::Deserialize<'de> for $enum_name {
87 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88 where
89 D: ::serde::Deserializer<'de>,
90 {
91 use ::serde::de::{self, MapAccess, Visitor};
92 use std::fmt;
93
94 #[derive(::serde::Deserialize)]
95 struct TypeField {
96 #[serde(rename = "type")]
97 type_: String,
98 #[serde(flatten)]
99 rest: ::serde_json::Value,
100 }
101
102 struct EnumVisitor;
103
104 impl<'de> Visitor<'de> for EnumVisitor {
105 type Value = $enum_name;
106
107 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
108 formatter.write_str(concat!("a struct with a `type` field for ", stringify!($enum_name)))
109 }
110
111 fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
112 where
113 M: MapAccess<'de>,
114 {
115 let TypeField { type_, rest } = ::serde::Deserialize::deserialize(
117 ::serde::de::value::MapAccessDeserializer::new(map)
118 )?;
119
120 let type_lowercase = type_.to_lowercase();
121
122 match type_lowercase.as_str() {
124 $(
125 $variant_str => {
126 let mut json_value = rest;
128 if let ::serde_json::Value::Object(ref mut map) = json_value {
129 map.insert("type".to_string(), ::serde_json::Value::String(stringify!($variant).to_string()));
130 }
131
132 ::serde_json::from_value(json_value)
134 .map_err(de::Error::custom)
135 }
136 )*
137 _ => Err(de::Error::unknown_variant(
138 &type_,
139 &[$($variant_str),*],
140 )),
141 }
142 }
143 }
144
145 deserializer.deserialize_map(EnumVisitor)
146 }
147 }
148 };
149}
150
151#[cfg(test)]
152mod tests {
153 use serde::Serialize;
154
155 #[test]
156 fn test_impl_case_insensitive_enum() {
157 #[derive(Debug, Clone, Serialize, PartialEq)]
158 #[serde(tag = "type", content = "value")]
159 enum MyEnum {
160 Variant1(String),
161 Variant2(String),
162 }
163
164 impl_case_insensitive_enum!(MyEnum, {
165 "variant1" => Variant1,
166 "variant2" => Variant2,
167 });
168
169 let json = r#"{"type": "variant1", "value": "test"}"#;
170 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
171 assert_eq!(deserialized, MyEnum::Variant1("test".to_string()));
172
173 let json = r#"{"type": "VARIANT1", "value": "test"}"#;
174 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
175 assert_eq!(deserialized, MyEnum::Variant1("test".to_string()));
176
177 let json = r#"{"type": "Variant1", "value": "test"}"#;
178 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
179 assert_eq!(deserialized, MyEnum::Variant1("test".to_string()));
180
181 let json = r#"{"type": "variant2", "value": "test"}"#;
182 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
183 assert_eq!(deserialized, MyEnum::Variant2("test".to_string()));
184
185 let json = r#"{"type": "VARIANT2", "value": "test"}"#;
186 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
187 assert_eq!(deserialized, MyEnum::Variant2("test".to_string()));
188
189 let json = r#"{"type": "Variant2", "value": "test"}"#;
190 let deserialized: MyEnum = serde_json::from_str(json).unwrap();
191 assert_eq!(deserialized, MyEnum::Variant2("test".to_string()));
192
193 let json = r#"{"type": "variant3", "value": "test"}"#;
194 let deserialized: Result<MyEnum, serde_json::Error> = serde_json::from_str(json);
195 assert!(deserialized.is_err());
196
197 let json = r#"{"type": "VARIANT3", "value": "test"}"#;
198 let deserialized: Result<MyEnum, serde_json::Error> = serde_json::from_str(json);
199 assert!(deserialized.is_err());
200
201 let json = r#"{"type": "Variant3", "value": "test"}"#;
202 let deserialized: Result<MyEnum, serde_json::Error> = serde_json::from_str(json);
203 assert!(deserialized.is_err());
204 }
205}