1use core::Blot;
25use multihash::{Harvest, Multihash};
26use serde_json::{Map, Number, Value};
27use tag::Tag;
28
29impl Blot for Map<String, Value> {
30 fn blot<D: Multihash>(&self, digester: &D) -> Harvest {
31 let mut list: Vec<Vec<u8>> = self
32 .iter()
33 .map(|(k, v)| {
34 let mut res: Vec<u8> = Vec::with_capacity(64);
35 res.extend_from_slice(k.blot(digester).as_slice());
36 res.extend_from_slice(v.blot(digester).as_slice());
37
38 res
39 }).collect();
40
41 list.sort_unstable();
42
43 digester.digest_collection(Tag::Dict, list)
44 }
45}
46
47#[cfg(feature = "common_json")]
48impl Blot for Number {
49 fn blot<D: Multihash>(&self, digester: &D) -> Harvest {
50 self.as_f64()
51 .expect("Casting JSON Number as f64 failed")
52 .blot(digester)
53 }
54}
55
56#[cfg(not(feature = "common_json"))]
57impl Blot for Number {
58 fn blot<D: Multihash>(&self, digester: &D) -> Harvest {
59 if self.is_f64() {
60 self.as_f64()
61 .expect("Casting JSON Number as f64 failed")
62 .blot(digester)
63 } else if self.is_u64() {
64 self.as_u64()
65 .expect("Casting JSON Number as u64 failed")
66 .blot(digester)
67 } else {
68 self.as_i64()
69 .expect("Casting JSON Number as i64 failed")
70 .blot(digester)
71 }
72 }
73}
74
75impl Blot for Value {
76 fn blot<D: Multihash>(&self, digester: &D) -> Harvest {
77 use hex::FromHex;
78 match self {
79 Value::Null => None::<u8>.blot(digester),
80 Value::Bool(raw) => raw.blot(digester),
81 Value::Number(raw) => raw.blot(digester),
82 Value::String(raw) => {
83 if raw.starts_with("**REDACTED**") {
85 let slice =
86 Vec::from_hex(raw.get(12..).expect("REDACTED")).expect("Hexadecimal");
87
88 slice.into_boxed_slice().into()
89 } else {
90 raw.blot(digester)
91 }
92 }
93 Value::Array(raw) => raw.blot(digester),
94 Value::Object(raw) => raw.blot(digester),
95 }
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102 use multihash::Sha2256;
103 use serde_json::{self, Value};
104
105 #[test]
106 fn common() {
107 let expected = "122032ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2";
108 let value: Value = serde_json::from_str(r#"["foo", "bar"]"#).unwrap();
109 let actual = format!("{}", &value.digest(Sha2256));
110
111 assert_eq!(actual, expected);
112 }
113
114 #[test]
115 fn common_redacted() {
116 let expected = "122032ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2";
117 let value: Value = serde_json::from_str(r#"["**REDACTED**a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038", "bar"]"#).unwrap();
118 let actual = format!("{}", &value.digest(Sha2256));
119
120 assert_eq!(actual, expected);
121 }
122
123 #[cfg(not(feature = "common_json"))]
124 mod default {
125 use super::*;
126 use multihash::Sha2256;
127 use serde_json::{self, Value};
128
129 #[test]
130 fn int_list() {
131 let pairs = [
132 (
133 r#"[123]"#,
134 "12201b93f704451e1a7a1b8c03626ffcd6dec0bc7ace947ff60d52e1b69b4658ccaa",
135 ),
136 (
137 r#"[1, 2, 3]"#,
138 "1220157bf16c70bd4c9673ffb5030552df0ee2c40282042ccdf6167850edc9044ab7",
139 ),
140 (
141 r#"[123456789012345]"#,
142 "12203488b9bc37cce8223a032760a9d4ef488cdfebddd9e1af0b31fcd1d7006369a4",
143 ),
144 (
145 r#"[123456789012345, 678901234567890]"#,
146 "1220031ef1aaeccea3bced3a1c6237a4fc00ed4d629c9511922c5a3f4e5c128b0ae4",
147 ),
148 ];
149 for (raw, expected) in pairs.iter() {
150 let value: Value = serde_json::from_str(raw).unwrap();
151 let actual = format!("{}", &value.digest(Sha2256));
152
153 assert_eq!(&actual, expected);
154 }
155 }
156
157 #[test]
158 fn int_float_mix() {
159 let pairs = [
160 (
161 r#"["foo", {"bar":["baz", null, 1.0, 1.5, 0.0001, 1000.0, 2.0, -23.1234, 2.0]}]"#,
162 "1220783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213"
163 ),
164 (
165 r#"["foo", {"bar":["baz", null, 1, 1.5, 0.0001, 1000, 2, -23.1234, 2]}]"#,
166 "1220726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a"
167 )
168 ];
169 for (raw, expected) in pairs.iter() {
170 let value: Value = serde_json::from_str(raw).unwrap();
171 let actual = format!("{}", &value.digest(Sha2256));
172
173 assert_eq!(&actual, expected);
174 }
175 }
176
177 #[test]
178 fn list() {
179 let expected = "1220acac86c0e609ca906f632b0e2dacccb2b77d22b0621f20ebece1a4835b93f6f0";
180 let value: Value = serde_json::from_str(r#"[]"#).unwrap();
181 let actual = format!("{}", &value.digest(Sha2256));
182
183 assert_eq!(&actual, expected);
184 }
185 }
186
187 #[cfg(feature = "common_json")]
188 mod common_json {
189 use super::*;
190 use multihash::Sha2256;
191 use serde_json::{self, Value};
192
193 #[test]
194 fn int_list() {
195 let pairs = [
196 (
197 r#"[123]"#,
198 "12202e72db006266ed9cdaa353aa22b9213e8a3c69c838349437c06896b1b34cee36",
199 ),
200 (
201 r#"[1, 2, 3]"#,
202 "1220925d474ac71f6e8cb35dd951d123944f7cabc5cda9a043cf38cd638cc0158db0",
203 ),
204 (
205 r#"[123456789012345]"#,
206 "1220f446de5475e2f24c0a2b0cd87350927f0a2870d1bb9cbaa794e789806e4c0836",
207 ),
208 (
209 r#"[123456789012345, 678901234567890]"#,
210 "1220d4cca471f1c68f62fbc815b88effa7e52e79d110419a7c64c1ebb107b07f7f56",
211 ),
212 ];
213 for (raw, expected) in pairs.iter() {
214 let value: Value = serde_json::from_str(raw).unwrap();
215 let actual = format!("{}", &value.digest(Sha2256));
216
217 assert_eq!(&actual, expected);
218 }
219 }
220 }
221}