blot/value/
de.rs

1// Copyright 2018 Arnau Siches
2//
3// Licensed under the MIT license <LICENSE or http://opensource.org/licenses/MIT>.
4// This file may not be copied, modified, or distributed except
5// according to those terms.
6
7use 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        // TODO: A mismatch between seal and value hashing functions will result in a Raw hash, not
79        // in a failure.
80        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}