1use std::fmt::{self, Display};
10
11use core::Blot;
12use multihash::{Harvest, Multihash};
13use seal::Seal;
14use std::collections::HashMap;
15use tag::Tag;
16
17#[cfg(feature = "blot_json")]
18pub mod de;
19
20#[derive(Clone, Debug, PartialEq)]
21pub enum Value<T: Multihash> {
22 Null,
24 Bool(bool),
26 Integer(i64),
28 Float(f64),
30 String(String),
32 Timestamp(String),
34 Redacted(Seal<T>),
36 Raw(Vec<u8>),
38 List(Vec<Value<T>>),
40 Set(Vec<Value<T>>),
42 Dict(HashMap<String, Value<T>>),
44}
45
46impl<T: Multihash> Value<T> {
47 pub fn sequences_as_sets(self) -> Self {
48 match self {
49 Value::List(list) => Value::Set(list),
50 Value::Dict(dict) => Value::Dict(
51 dict.into_iter()
52 .map(|(k, v)| (k, v.sequences_as_sets()))
53 .collect(),
54 ),
55 value => value,
56 }
57 }
58}
59
60#[derive(Debug)]
61pub enum ValueError {
62 Unknown,
63}
64
65impl Display for ValueError {
66 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
67 write!(formatter, "{:?}", self)
68 }
69}
70
71impl<T: Multihash> Blot for Value<T> {
72 fn blot<D: Multihash>(&self, digester: &D) -> Harvest {
73 match self {
74 Value::Null => None::<u8>.blot(digester),
75 Value::Bool(raw) => raw.blot(digester),
76 Value::Integer(raw) => raw.blot(digester),
77 Value::Float(raw) => raw.blot(digester),
78 Value::String(raw) => raw.blot(digester),
79 Value::Timestamp(raw) => digester
80 .clone()
81 .digest_primitive(Tag::Timestamp, raw.as_bytes()),
82 Value::Redacted(raw) => raw.blot(digester),
83 Value::Raw(raw) => raw.as_slice().blot(digester),
84 Value::List(raw) => raw.blot(digester),
85 Value::Set(raw) => {
86 println!("in set");
87 let mut list: Vec<Vec<u8>> = raw
88 .iter()
89 .map(|item| {
90 item.blot(digester)
91 .as_slice()
92 .iter()
93 .map(|x| *x)
94 .collect::<Vec<u8>>()
95 }).collect();
96
97 list.sort_unstable();
98 list.dedup();
99
100 digester.clone().digest_collection(Tag::Set, list)
101 }
102 Value::Dict(raw) => raw.blot(digester),
103 }
104 }
105}
106
107#[macro_export]
108macro_rules! set {
109 ( $( $x:expr ),* ) => {
110 {
111 let mut temp_vec = Vec::new();
112 $(
113 temp_vec.push($x.into());
114 )*
115 Value::Set(temp_vec)
116 }
117 };
118}
119
120#[macro_export]
121macro_rules! raw {
122 ($input:expr) => {{
123 Vec::from_hex($input).map(|hash| Value::Raw(hash))
124 }};
125}
126
127#[macro_export]
128macro_rules! list {
129 ( $( $x:expr ),* ) => {
130 {
131 let mut temp_vec = Vec::new();
132 $(
133 temp_vec.push($x.into());
134 )*
135 Value::List(temp_vec)
136 }
137 };
138}
139
140#[macro_export]
141macro_rules! seal {
142 ($input:expr) => {{
143 Seal::from_str($input).map(Value::Redacted)
144 }};
145}
146
147impl<'a, T: Multihash> From<&'a str> for Value<T> {
148 fn from(raw: &str) -> Value<T> {
149 Value::String(raw.into())
150 }
151}
152
153impl<'a, T: Multihash> From<String> for Value<T> {
154 fn from(raw: String) -> Value<T> {
155 Value::String(raw)
156 }
157}
158
159impl<T: Multihash> From<i64> for Value<T> {
160 fn from(raw: i64) -> Value<T> {
161 Value::Integer(raw)
162 }
163}
164
165impl<T: Multihash> From<f64> for Value<T> {
166 fn from(raw: f64) -> Value<T> {
167 Value::Float(raw)
168 }
169}
170
171impl<T: Multihash> From<Vec<Value<T>>> for Value<T> {
172 fn from(raw: Vec<Value<T>>) -> Value<T> {
173 Value::List(raw)
174 }
175}
176
177impl<T: Multihash> From<Seal<T>> for Value<T> {
178 fn from(raw: Seal<T>) -> Value<T> {
179 Value::Redacted(raw)
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::*;
186 use multihash::Sha2256;
187
188 #[test]
189 fn common() {
190 let expected = "122032ae896c413cfdc79eec68be9139c86ded8b279238467c216cf2bec4d5f1e4a2";
191 let value: Value<Sha2256> = vec!["foo".into(), "bar".into()].into();
192 let actual = format!("{}", &value.digest(Sha2256));
193
194 assert_eq!(actual, expected);
195 }
196
197 #[test]
198 fn int_list() {
199 let pairs: [(Value<Sha2256>, &str); 4] = [
200 (
201 list![123],
202 "12201b93f704451e1a7a1b8c03626ffcd6dec0bc7ace947ff60d52e1b69b4658ccaa",
203 ),
204 (
205 list![1, 2, 3],
206 "1220157bf16c70bd4c9673ffb5030552df0ee2c40282042ccdf6167850edc9044ab7",
207 ),
208 (
209 list![123456789012345],
210 "12203488b9bc37cce8223a032760a9d4ef488cdfebddd9e1af0b31fcd1d7006369a4",
211 ),
212 (
213 list![123456789012345, 678901234567890],
214 "1220031ef1aaeccea3bced3a1c6237a4fc00ed4d629c9511922c5a3f4e5c128b0ae4",
215 ),
216 ];
217
218 for (value, expected) in pairs.iter() {
219 let actual = format!("{}", &value.digest(Sha2256));
220
221 assert_eq!(&actual, expected);
222 }
223 }
224
225 #[test]
226 fn floats() {
227 let mut map: HashMap<String, Value<Sha2256>> = HashMap::new();
228 map.insert(
229 "bar".into(),
230 list![
231 "baz",
232 Value::Null,
233 1.0,
234 1.5,
235 0.0001,
236 1000.0,
237 2.0,
238 -23.1234,
239 2.0
240 ],
241 );
242 let value = list!["foo", Value::Dict(map)];
243 let expected = "1220783a423b094307bcb28d005bc2f026ff44204442ef3513585e7e73b66e3c2213";
244 let actual = format!("{}", &value.digest(Sha2256));
245
246 assert_eq!(&actual, expected);
247 }
248
249 #[test]
250 fn int_floats() {
251 let mut map: HashMap<String, Value<Sha2256>> = HashMap::new();
252 map.insert(
253 "bar".into(),
254 vec![
255 "baz".into(),
256 Value::Null,
257 1.into(),
258 1.5.into(),
259 0.0001.into(),
260 1000.into(),
261 2.into(),
262 (-23.1234).into(),
263 2.into(),
264 ].into(),
265 );
266 let value = Value::List(vec!["foo".into(), Value::Dict(map)]);
267 let expected = "1220726e7ae9e3fadf8a2228bf33e505a63df8db1638fa4f21429673d387dbd1c52a";
268 let actual = format!("{}", &value.digest(Sha2256));
269
270 assert_eq!(&actual, expected);
271 }
272
273 #[test]
274 fn set() {
275 let mut map: HashMap<String, Value<Sha2256>> = HashMap::new();
276 let mut map2: HashMap<String, Value<Sha2256>> = HashMap::new();
277 map2.insert(
278 "thing2".into(),
279 Value::Set(vec![1.into(), 2.into(), "s".into()]),
280 );
281 map.insert("thing1".into(), Value::Dict(map2));
282 map.insert("thing3".into(), 1234.567.into());
283 let value = Value::Dict(map);
284
285 let expected = "1220618cf0582d2e716a70e99c2f3079d74892fec335e3982eb926835967cb0c246c";
286 let actual = format!("{}", &value.digest(Sha2256));
287
288 assert_eq!(&actual, expected);
289 }
290
291 #[test]
292 fn complex_set() {
293 let value: Value<Sha2256> = set!{"foo", 23.6, set!{set!{}}, set!{set!{1}}};
294
295 let expected = "12203773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398";
296 let actual = format!("{}", &value.digest(Sha2256));
297
298 assert_eq!(&actual, expected);
299 }
300
301 #[test]
302 fn complex_set_repeated() {
303 let value: Value<Sha2256> = set!{
304 "foo",
305 23.6,
306 set!{set!{}},
307 set!{set!{1}},
308 set!{set!{}}
309 };
310
311 let expected = "12203773b0a5283f91243a304d2bb0adb653564573bc5301aa8bb63156266ea5d398";
312 let actual = format!("{}", &value.digest(Sha2256));
313
314 assert_eq!(&actual, expected);
315 }
316
317 #[test]
318 fn raw() {
319 let pairs: [(Value<Sha2256>, &str); 3] = [
320 (
321 Value::Raw(vec![]),
322 "1220454349e422f05297191ead13e21d3db520e5abef52055e4964b82fb213f593a1",
323 ),
324 (
325 Value::Raw(vec![255, 255]),
326 "122043ad246c14bf0bc0b2ac9cab9fae202a181ab4c6abb07fb40cad8c67a4cab8ee",
327 ),
328 (
329 Value::Raw(vec![0, 0, 0]),
330 "1220d877bf4e5023a6df5262218800a7162e240c84e44696bb2c3ad1c5e756f3dac1",
331 ),
332 ];
333
334 for (value, expected) in pairs.iter() {
335 let actual = format!("{}", &value.digest(Sha2256));
336
337 assert_eq!(&actual, expected);
338 }
339 }
340
341 #[test]
342 fn redacted() {
343 let expected = "1220454349e422f05297191ead13e21d3db520e5abef52055e4964b82fb213f593a1";
344 let seal: Seal<Sha2256> = Seal::from_str(
345 "**REDACTED**1220454349e422f05297191ead13e21d3db520e5abef52055e4964b82fb213f593a1",
346 ).unwrap();
347 let value = Value::Redacted(seal);
348 let actual = format!("{}", &value.digest(Sha2256));
349 assert_eq!(&actual, expected);
350 }
351
352 #[test]
353 fn redacted_mix() {
354 let expected_value: Value<Sha2256> = list!["foo", "bar"];
355 let expected = expected_value.digest(Sha2256);
356 let foo: Seal<Sha2256> = Seal::from_str(
357 "**REDACTED**1220a6a6e5e783c363cd95693ec189c2682315d956869397738679b56305f2095038",
358 ).unwrap();
359 let actual = list![foo, "bar"].digest(Sha2256);
360 assert_eq!(actual.to_string(), expected.to_string());
361 }
362
363}