ratify_protocol/
canonical.rs1use base64::{engine::general_purpose::STANDARD, Engine as _};
17use serde_json::Value;
18
19pub fn canonical_json(value: &Value) -> Vec<u8> {
21 let mut out = String::new();
22 encode_value(value, &mut out);
23 out.into_bytes()
24}
25
26fn encode_value(v: &Value, out: &mut String) {
27 match v {
28 Value::Null => out.push_str("null"),
29 Value::Bool(true) => out.push_str("true"),
30 Value::Bool(false) => out.push_str("false"),
31 Value::Number(n) => out.push_str(&encode_number(n)),
32 Value::String(s) => encode_string(s, out),
33 Value::Array(arr) => {
34 out.push('[');
35 for (i, item) in arr.iter().enumerate() {
36 if i > 0 {
37 out.push(',');
38 }
39 encode_value(item, out);
40 }
41 out.push(']');
42 }
43 Value::Object(obj) => {
44 let mut keys: Vec<&String> = obj.keys().collect();
46 keys.sort();
47 out.push('{');
48 let mut first = true;
49 for k in keys {
50 let val = &obj[k];
51 if val.is_null() {
53 continue;
54 }
55 if !first {
56 out.push(',');
57 }
58 encode_string(k, out);
59 out.push(':');
60 encode_value(val, out);
61 first = false;
62 }
63 out.push('}');
64 }
65 }
66}
67
68fn encode_number(n: &serde_json::Number) -> String {
74 if let Some(i) = n.as_i64() {
75 return i.to_string();
76 }
77 if let Some(u) = n.as_u64() {
78 return u.to_string();
79 }
80 if let Some(f) = n.as_f64() {
81 if f.is_finite() && f.fract() == 0.0 && f.abs() < 1e15 {
82 return (f as i64).to_string();
84 }
85 return f.to_string();
86 }
87 n.to_string()
88}
89
90fn encode_string(s: &str, out: &mut String) {
91 out.push('"');
92 for c in s.chars() {
93 match c {
94 '"' => out.push_str("\\\""),
95 '\\' => out.push_str("\\\\"),
96 '\u{0008}' => out.push_str("\\b"),
97 '\u{0009}' => out.push_str("\\t"),
98 '\u{000A}' => out.push_str("\\n"),
99 '\u{000C}' => out.push_str("\\f"),
100 '\u{000D}' => out.push_str("\\r"),
101 '\u{2028}' => out.push_str("\\u2028"),
102 '\u{2029}' => out.push_str("\\u2029"),
103 c if (c as u32) < 0x20 => {
104 out.push_str(&format!("\\u{:04x}", c as u32));
105 }
106 c => out.push(c),
108 }
109 }
110 out.push('"');
111}
112
113pub fn base64_std_encode(data: &[u8]) -> String {
115 STANDARD.encode(data)
116}
117
118pub fn base64_std_decode(s: &str) -> Result<Vec<u8>, base64::DecodeError> {
120 STANDARD.decode(s)
121}
122
123pub fn hex_encode(data: &[u8]) -> String {
125 hex::encode(data)
126}
127
128pub fn hex_decode(s: &str) -> Result<Vec<u8>, hex::FromHexError> {
130 hex::decode(s)
131}
132
133pub mod base64_bytes {
135 use super::{base64_std_decode, base64_std_encode};
136 use serde::{de::Error, Deserialize, Deserializer, Serializer};
137
138 pub fn serialize<S>(bytes: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: Serializer,
141 {
142 serializer.serialize_str(&base64_std_encode(bytes))
143 }
144
145 pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 let s = String::deserialize(deserializer)?;
150 base64_std_decode(&s).map_err(|e| D::Error::custom(format!("base64 decode: {e}")))
151 }
152}