Skip to main content

sciforge_parser/json/
writer.rs

1pub enum JsonVal<'a> {
2    Str(&'a str),
3    Num(f64),
4    Int(i64),
5    Bool(bool),
6    Null,
7    Raw(&'a str),
8}
9
10pub fn write_json_object(fields: &[(&str, JsonVal<'_>)]) -> String {
11    let mut out = String::with_capacity(512);
12    out.push_str("{\n");
13    for (i, (key, val)) in fields.iter().enumerate() {
14        out.push_str("  \"");
15        push_json_escaped(&mut out, key);
16        out.push_str("\": ");
17        push_json_val(&mut out, val);
18        if i + 1 < fields.len() {
19            out.push(',');
20        }
21        out.push('\n');
22    }
23    out.push('}');
24    out
25}
26
27pub fn write_json_array(items: &[String]) -> String {
28    let mut out = String::with_capacity(items.iter().map(|s| s.len() + 2).sum::<usize>() + 4);
29    out.push_str("[\n");
30    for (i, item) in items.iter().enumerate() {
31        out.push_str(item);
32        if i + 1 < items.len() {
33            out.push_str(",\n");
34        }
35        out.push('\n');
36    }
37    out.push(']');
38    out
39}
40
41pub fn push_json_escaped(out: &mut String, s: &str) {
42    for c in s.chars() {
43        match c {
44            '"' => out.push_str("\\\""),
45            '\\' => out.push_str("\\\\"),
46            '\n' => out.push_str("\\n"),
47            '\r' => out.push_str("\\r"),
48            '\t' => out.push_str("\\t"),
49            c if (c as u32) < 0x20 => {
50                out.push_str(&format!("\\u{:04x}", c as u32));
51            }
52            _ => out.push(c),
53        }
54    }
55}
56
57fn push_json_val(out: &mut String, val: &JsonVal<'_>) {
58    match val {
59        JsonVal::Str(s) => {
60            out.push('"');
61            push_json_escaped(out, s);
62            out.push('"');
63        }
64        JsonVal::Num(n) => {
65            if n.fract() == 0.0 && n.abs() < 1e15 {
66                out.push_str(&format!("{}", *n as i64));
67            } else {
68                out.push_str(&format!("{n}"));
69            }
70        }
71        JsonVal::Int(n) => out.push_str(&format!("{n}")),
72        JsonVal::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
73        JsonVal::Null => out.push_str("null"),
74        JsonVal::Raw(s) => out.push_str(s),
75    }
76}