use serde_json::{Number, Value};
fn json_eq(a: &Value, b: &Value) -> bool {
use Value::*;
match (a, b) {
(Null, Null) => true,
(Bool(x), Bool(y)) => x == y,
(String(x), String(y)) => x == y,
(Array(xs), Array(ys)) => {
xs.len() == ys.len() && xs.iter().zip(ys).all(|(x, y)| json_eq(x, y))
}
(Object(xm), Object(ym)) => {
xm.len() == ym.len()
&& xm.keys().all(|k| ym.contains_key(k))
&& xm.iter().all(|(k, v)| json_eq(v, &ym[k]))
}
(Number(x), Number(y)) => numbers_close(x, y),
_ => false,
}
}
fn numbers_close(x: &Number, y: &Number) -> bool {
if x == y {
return true;
};
let xf = x.as_f64();
let yf = y.as_f64();
const MAX_DIFF: f64 = 1e-7;
match (xf, yf) {
(Some(xf), Some(yf)) => (xf - yf).abs() < MAX_DIFF,
_ => false,
}
}
fn assert_json_eq(a: &Value, b: &Value) {
assert!(json_eq(a, b), "{a:#?}\n!=\n{b:#?}");
}
macro_rules! test {
( $( $name:ident )* ) => {
$(
#[test]
fn $name() {
const BYTES: &[u8] = include_bytes!(concat!(stringify!($name), ".beve"));
const JSON: &str = include_str!(concat!(stringify!($name), ".json"));
let beve: Value = serde_beve::from_bytes(BYTES).unwrap();
let json: Value = serde_json::from_str(JSON).unwrap();
assert_json_eq(&beve, &json);
}
)*
};
}
test!(complex_numbers float32_array float64_array general_object nested_object strings_array uint16_array);