serde-beve 1.0.0

A BEVE data format for Serde
Documentation
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();

    // Sometimes you get very miniscule differences due to float imprecesion
    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);