]>
Commit | Line | Data |
---|---|---|
9ff747ef WB |
1 | use anyhow::{bail, Error}; |
2 | use serde_json::Value; | |
3 | ||
4 | // Generate canonical json | |
5 | pub fn to_canonical_json(value: &Value) -> Result<Vec<u8>, Error> { | |
6 | let mut data = Vec::new(); | |
7 | write_canonical_json(value, &mut data)?; | |
8 | Ok(data) | |
9 | } | |
10 | ||
11 | pub fn write_canonical_json(value: &Value, output: &mut Vec<u8>) -> Result<(), Error> { | |
12 | match value { | |
13 | Value::Null => bail!("got unexpected null value"), | |
14 | Value::String(_) | Value::Number(_) | Value::Bool(_) => { | |
15 | serde_json::to_writer(output, &value)?; | |
16 | } | |
17 | Value::Array(list) => { | |
18 | output.push(b'['); | |
19 | let mut iter = list.iter(); | |
20 | if let Some(item) = iter.next() { | |
21 | write_canonical_json(item, output)?; | |
22 | for item in iter { | |
23 | output.push(b','); | |
24 | write_canonical_json(item, output)?; | |
25 | } | |
26 | } | |
27 | output.push(b']'); | |
28 | } | |
29 | Value::Object(map) => { | |
30 | output.push(b'{'); | |
31 | let mut keys: Vec<&str> = map.keys().map(String::as_str).collect(); | |
32 | keys.sort(); | |
33 | let mut iter = keys.into_iter(); | |
34 | if let Some(key) = iter.next() { | |
35 | serde_json::to_writer(&mut *output, &key)?; | |
36 | output.push(b':'); | |
37 | write_canonical_json(&map[key], output)?; | |
38 | for key in iter { | |
39 | output.push(b','); | |
40 | serde_json::to_writer(&mut *output, &key)?; | |
41 | output.push(b':'); | |
42 | write_canonical_json(&map[key], output)?; | |
43 | } | |
44 | } | |
45 | output.push(b'}'); | |
46 | } | |
47 | } | |
48 | Ok(()) | |
49 | } |