evobench_tools/serde_util/
mod.rs1pub mod json5_from_str;
4
5use std::{cell::RefCell, fmt::Display, path::Path};
6
7use anyhow::Result;
8use serde::de::DeserializeOwned;
9use serde_json::Value;
10
11use crate::ctx;
12
13pub fn serde_read_json<T: DeserializeOwned>(path: &Path) -> Result<T> {
17 (|| -> Result<_> {
18 let s = std::fs::read_to_string(path)?;
19 Ok(serde_json::from_str(&s)?)
20 })()
21 .map_err(ctx!("reading file {path:?}"))
22}
23
24pub struct CanonicalJson<'t>(pub &'t Value);
25
26fn display_canonical_json(json: &Value, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
27 match json {
28 Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) | Value::Array(_) => {
29 write!(f, "{}", json)
30 }
31 Value::Object(map) => {
32 let display_keyval =
33 |(key, val, _): &(&String, &Value, _), f: &mut std::fmt::Formatter<'_>| {
34 write!(f, "{}:", Value::String((*key).to_owned()))?;
37 display_canonical_json(val, f)
38 };
39
40 f.write_str("{")?;
41 let mut keyvals: Vec<(&String, &Value, RefCell<Option<String>>)> = map
42 .iter()
43 .map(|(key, val)| (key, val, RefCell::new(None)))
44 .collect();
45 if !keyvals.is_empty() {
46 keyvals.sort_by(|a, b| {
47 a.0.cmp(b.0).then_with(|| {
48 let mut ar = a.2.borrow_mut();
49 if ar.is_none() {
50 *ar = Some(CanonicalJson(&a.1).to_string());
51 }
52 let mut br = b.2.borrow_mut();
53 if br.is_none() {
54 *br = Some(CanonicalJson(&b.1).to_string());
55 }
56 ar.as_ref()
57 .expect("just set")
58 .cmp(br.as_ref().expect("just_set"))
59 })
60 });
61 for keyval in &keyvals[0..keyvals.len() - 1] {
62 display_keyval(keyval, f)?;
63 f.write_str(",")?;
64 }
65 display_keyval(keyvals.last().expect("checked non-empty"), f)?;
66 }
67 f.write_str("}")
68 }
69 }
70}
71
72impl<'t> Display for CanonicalJson<'t> {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 display_canonical_json(&self.0, f)
75 }
76}