1use hex::FromHex;
8use multihash::Multihash;
9use regex::Regex;
10use seal::Seal;
11use serde::de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor};
12use std::collections::HashMap;
13use std::fmt;
14
15use super::Value;
16
17use std::marker::PhantomData;
18struct ValueVisitor<T: Multihash>(PhantomData<*const T>);
19
20impl<'de, T: Multihash> Visitor<'de> for ValueVisitor<T> {
21 type Value = Value<T>;
22
23 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
24 formatter.write_str("Expecting a valid JSON value.")
25 }
26
27 #[inline]
28 fn visit_bool<E>(self, value: bool) -> Result<Self::Value, E>
29 where
30 E: de::Error,
31 {
32 Ok(Value::Bool(value))
33 }
34
35 #[inline]
36 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
37 where
38 E: de::Error,
39 {
40 Ok(Value::Integer(value.into()))
41 }
42
43 #[inline]
44 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
45 where
46 E: de::Error,
47 {
48 use std::i64;
49
50 if value <= (i64::MAX as u64) {
51 Ok(Value::Integer(value as i64))
52 } else {
53 Err(E::custom(format!("i64 out of range: {}", value)))
54 }
55 }
56
57 #[inline]
58 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
59 where
60 E: de::Error,
61 {
62 Ok(Value::Float(value.into()))
63 }
64
65 #[inline]
66 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
67 where
68 E: de::Error,
69 {
70 self.visit_string(value.into())
71 }
72
73 #[inline]
74 fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
75 where
76 E: de::Error,
77 {
78 if let Ok(seal) = Seal::from_str(&value) {
81 return Ok(Value::Redacted(seal));
82 }
83
84 if let Ok(raw) = Vec::from_hex(&value) {
85 return Ok(Value::Raw(raw));
86 }
87
88 lazy_static! {
89 static ref RE: Regex = Regex::new(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z")
90 .expect("Regex to compile");
91 }
92
93 if RE.is_match(&value) {
94 return Ok(Value::Timestamp(value));
95 }
96
97 Ok(Value::String(value))
98 }
99
100 #[inline]
101 fn visit_none<E>(self) -> Result<Self::Value, E> {
102 Ok(Value::Null)
103 }
104
105 #[inline]
106 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
107 where
108 D: Deserializer<'de>,
109 {
110 Deserialize::deserialize(deserializer)
111 }
112
113 #[inline]
114 fn visit_unit<E>(self) -> Result<Self::Value, E> {
115 Ok(Value::Null)
116 }
117
118 #[inline]
119 fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
120 where
121 V: SeqAccess<'de>,
122 {
123 let mut vec = Vec::new();
124
125 while let Some(elem) = visitor.next_element()? {
126 vec.push(elem);
127 }
128
129 Ok(Value::List(vec))
130 }
131
132 fn visit_map<V>(self, mut access: V) -> Result<Self::Value, V::Error>
133 where
134 V: MapAccess<'de>,
135 {
136 let mut dict = HashMap::new();
137
138 while let Some((key, value)) = access.next_entry()? {
139 dict.insert(key, value);
140 }
141
142 Ok(Value::Dict(dict))
143 }
144}
145
146impl<'de, T: Multihash> Deserialize<'de> for Value<T> {
147 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148 where
149 D: Deserializer<'de>,
150 {
151 deserializer.deserialize_any(ValueVisitor(PhantomData))
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use multihash::{Sha2256, Sha3256};
159 use serde_json;
160
161 #[test]
162 fn basic_string_value() {
163 let input = r#""abc""#;
164 let expected = r#"Ok(String("abc"))"#.to_string();
165 let res = serde_json::from_str::<Value<Sha2256>>(input);
166
167 assert_eq!(format!("{:?}", res), expected);
168 }
169
170 #[test]
171 fn classic_redacted_value() {
172 let input =
173 r#""**REDACTED**1220a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038""#;
174 let expected = r#"Ok(Redacted(Seal { tag: Sha2256, digest: [166, 166, 229, 231, 131, 195, 99, 205, 149, 105, 62, 193, 137, 194, 104, 35, 21, 217, 86, 134, 147, 151, 115, 134, 121, 181, 99, 5, 242, 9, 80, 56] }))"#.to_string();
175 let res = serde_json::from_str::<Value<Sha2256>>(input);
176
177 assert_eq!(format!("{:?}", res), expected);
178 }
179
180 #[test]
181 fn redacted_value() {
182 let input = r#""771220a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038""#;
183 let expected = r#"Ok(Redacted(Seal { tag: Sha2256, digest: [166, 166, 229, 231, 131, 195, 99, 205, 149, 105, 62, 193, 137, 194, 104, 35, 21, 217, 86, 134, 147, 151, 115, 134, 121, 181, 99, 5, 242, 9, 80, 56] }))"#.to_string();
184 let res = serde_json::from_str::<Value<Sha2256>>(input);
185
186 assert_eq!(format!("{:?}", res), expected);
187 }
188
189 #[test]
190 fn raw_value() {
191 let input = r#""1220a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038""#;
192 let expected = r#"Ok(Raw([18, 32, 166, 166, 229, 231, 131, 195, 99, 205, 149, 105, 62, 193, 137, 194, 104, 35, 21, 217, 86, 134, 147, 151, 115, 134, 121, 181, 99, 5, 242, 9, 80, 56]))"#.to_string();
193 let res = serde_json::from_str::<Value<Sha2256>>(input);
194
195 assert_eq!(format!("{:?}", res), expected);
196 }
197
198 #[test]
199 fn redacted_value_wrong_algorithm() {
200 let input = r#""771220a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038""#;
201 let expected = r#"Ok(Raw([119, 18, 32, 166, 166, 229, 231, 131, 195, 99, 205, 149, 105, 62, 193, 137, 194, 104, 35, 21, 217, 86, 134, 147, 151, 115, 134, 121, 181, 99, 5, 242, 9, 80, 56]))"#;
202 let res = serde_json::from_str::<Value<Sha3256>>(input);
203
204 assert_eq!(format!("{:?}", res), expected);
205 }
206
207 #[test]
208 fn list_value() {
209 let input = r#"[1, 2]"#;
210 let expected = r#"Ok(List([Integer(1), Integer(2)]))"#;
211 let res = serde_json::from_str::<Value<Sha2256>>(input);
212
213 assert_eq!(format!("{:?}", res), expected);
214 }
215
216 #[test]
217 fn set_value() {
218 let input = r#"[1, 2]"#;
219 let expected = r#"Set([Integer(1), Integer(2)])"#;
220 let res = serde_json::from_str::<Value<Sha2256>>(input)
221 .unwrap()
222 .sequences_as_sets();
223
224 assert_eq!(format!("{:?}", res), expected);
225 }
226
227 #[test]
228 fn dict_set_value() {
229 let input = r#"{"foo": ["bar", "baz"]}"#;
230 let expected = r#"Dict({"foo": Set([String("bar"), String("baz")])})"#;
231 let res = serde_json::from_str::<Value<Sha2256>>(input)
232 .unwrap()
233 .sequences_as_sets();
234
235 assert_eq!(format!("{:?}", res), expected);
236 }
237
238 #[test]
239 fn timestamp_value() {
240 let input = r#""2018-10-13T15:50:00Z""#;
241 let expected = r#"Ok(Timestamp("2018-10-13T15:50:00Z"))"#;
242 let res = serde_json::from_str::<Value<Sha2256>>(input);
243
244 assert_eq!(format!("{:?}", res), expected);
245 }
246}