use std::fmt::Write;
use super::Val;
pub fn string(out: &mut String, s: &str) {
out.push('"');
for c in s.chars() {
match c {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
'\u{8}' => out.push_str("\\b"),
'\u{c}' => out.push_str("\\f"),
c if (c as u32) < 0x20 || c == '\u{2028}' || c == '\u{2029}' => {
let _ = write!(out, "\\u{:04x}", c as u32);
}
c => out.push(c),
}
}
out.push('"');
}
pub fn number(out: &mut String, v: f64) {
if !v.is_finite() {
out.push_str("null");
} else if v.fract() == 0.0 && v.abs() < 1e15 {
let _ = write!(out, "{}", v as i64);
} else {
let _ = write!(out, "{v}");
}
}
pub fn val(out: &mut String, v: &Val) {
match v {
Val::Str(s) => string(out, s),
Val::U(u) => {
let _ = write!(out, "{u}");
}
Val::I(i) => {
let _ = write!(out, "{i}");
}
Val::F(f) => number(out, *f),
Val::B(b) => out.push_str(if *b { "true" } else { "false" }),
}
}
pub fn object(out: &mut String, args: &[(&str, Val)]) {
out.push('{');
for (i, (k, v)) in args.iter().enumerate() {
if i > 0 {
out.push(',');
}
string(out, k);
out.push(':');
val(out, v);
}
out.push('}');
}
pub fn ms(out: &mut String, us: u64) {
number(out, us as f64 / 1000.0);
}