Download orchestrator/gitbucket/external/src/canonical.rs from Snapkitty/sov-kernel-monster: direct link, hf CLI and curl.
- Browser
- Download file 2.85 kB
-
https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/orchestrator/gitbucket/external/src/canonical.rs
- Command line
-
hf download hf://Snapkitty/sov-kernel-monster/orchestrator/gitbucket/external/src/canonical.rs
-
curl -L -o canonical.rs https://huggingface.co/Snapkitty/sov-kernel-monster/resolve/main/orchestrator/gitbucket/external/src/canonical.rs
2.85 kB
| //! Canonical JSON Serialization | |
| //! Deterministic byte representation with key ordering invariance | |
| use serde_json::Value; | |
| use std::collections::BTreeMap; | |
| /// Canonicalize a JSON value to deterministic bytes | |
| /// Keys are sorted lexicographically to ensure same logical value → same bytes | |
| pub fn canonical_bytes(value: &Value) -> Vec<u8> { | |
| canonicalize_value(value).into_bytes() | |
| } | |
| /// Recursively canonicalize a JSON value | |
| fn canonicalize_value(value: &Value) -> String { | |
| match value { | |
| Value::Null => "null".to_string(), | |
| Value::Bool(b) => if *b { "true" } else { "false" }.to_string(), | |
| Value::Number(n) => n.to_string(), | |
| Value::String(s) => canonicalize_string(s), | |
| Value::Array(arr) => { | |
| let inner: Vec<String> = arr.iter().map(canonicalize_value).collect(); | |
| format!("[{}]", inner.join(",")) | |
| } | |
| Value::Object(obj) => { | |
| // KEY INSIGHT: Sort by key name (BTreeMap ensures lexicographic order) | |
| let sorted: BTreeMap<&String, &Value> = obj.iter().collect(); | |
| let inner: Vec<String> = sorted | |
| .iter() | |
| .map(|(k, v)| format!("\"{}\":{}", k, canonicalize_value(v))) | |
| .collect(); | |
| format!("{{{}}}", inner.join(",")) | |
| } | |
| } | |
| } | |
| /// Canonicalize a string (minimal: return as-is) | |
| /// Production: use unicode-normalization for NFC form | |
| fn canonicalize_string(s: &str) -> String { | |
| // Escape special characters for JSON | |
| let escaped = s | |
| .replace('\\', "\\\\") | |
| .replace('"', "\\\"") | |
| .replace('\n', "\\n") | |
| .replace('\r', "\\r") | |
| .replace('\t', "\\t"); | |
| format!("\"{}\"", escaped) | |
| } | |
| mod tests { | |
| use super::*; | |
| use serde_json::json; | |
| fn test_key_ordering_invariance() { | |
| let v1 = json!({"b": 2, "a": 1}); | |
| let v2 = json!({"a": 1, "b": 2}); | |
| assert_eq!(canonical_bytes(&v1), canonical_bytes(&v2)); | |
| } | |
| fn test_nested_objects() { | |
| let v1 = json!({"z": {"b": 2, "a": 1}, "y": 3}); | |
| let v2 = json!({"y": 3, "z": {"a": 1, "b": 2}}); | |
| assert_eq!(canonical_bytes(&v1), canonical_bytes(&v2)); | |
| } | |
| fn test_arrays_preserve_order() { | |
| let v1 = json!([1, 2, 3]); | |
| let v2 = json!([1, 2, 3]); | |
| assert_eq!(canonical_bytes(&v1), canonical_bytes(&v2)); | |
| } | |
| fn test_primitives() { | |
| assert_eq!(canonicalize_value(&json!(null)), "null"); | |
| assert_eq!(canonicalize_value(&json!(true)), "true"); | |
| assert_eq!(canonicalize_value(&json!(false)), "false"); | |
| assert_eq!(canonicalize_value(&json!(42)), "42"); | |
| assert_eq!(canonicalize_value(&json!("hello")), "\"hello\""); | |
| } | |
| } | |