json-rs 0.1.1

Lightweight JSON reader and writer, written in pure rust.
Documentation
mod lexer;
mod parser;
pub mod json;

#[cfg(test)]
mod tests {
    use std::{collections::HashMap, time};

    use crate::json::{JSONValue, self, Cast};

    use super::lexer::Lexer;

    #[test]
    fn lexer_test() {
        let new_buf = 
        "
{
    \"foo\": \"bar\",
    \"baz\": 134.0e-3,
    \"beanz\": $ [false, true]
}";
        let mut lexer: Lexer = Lexer::new(new_buf.as_bytes().to_vec());

        lexer.tokenify().expect_err("this should error");
    }

    #[test]
    fn parser_test() -> json::Result<()> {
        let buffer = std::fs::read("tests/array.json").unwrap();
        assert_eq!(JSONValue::Array(vec![
            JSONValue::Number(1.0),
            JSONValue::Number(2.0),
            JSONValue::Number(3.0),
            JSONValue::Bool(true),
            JSONValue::Null,
        ]), JSONValue::try_from(buffer)?);

        let buffer = std::fs::read("tests/string.json").unwrap();
        let str: String = JSONValue::try_from(buffer)?.cast()?;
        assert_eq!("asdfa sdfas\\df / wallalla tryn 165-08 {}{}___--=+123,./<>?".to_owned(), str);

        Ok(())
    }

    macro_rules! int_test {
        ($var:expr, $($type_name:ty)+) => {
            $(let _var: $type_name = $var.cast()?;)+
        };
    }

    #[test]
    fn json_test() -> json::Result<()> {
        let value = JSONValue::try_from(std::fs::read("tests/test.json").unwrap())?;
        
        let a: String = value.get("foo")?.cast()?;
        assert_eq!("bar", a);
        let b: String = value["foo"].cast()?;
        assert_eq!(a, b);

        let bool: bool = value["baz"][0].cast()?;
        assert_eq!(bool, true);
        let bool_2: bool = value.get("baz")?.try_index(0)?.cast()?;
        assert_eq!(bool, bool_2);

        int_test!(value["obj"]["b"], i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32);
        let the_answer: u8 = value["qux"]["qux_obj"]["nest_arr"][3]["the_answer"].cast()?;
        assert_eq!(42, the_answer);

        Ok(())
    }

    #[test]
    fn serialize_test() -> json::Result<()> {
        let mut values: JSONValue = JSONValue::Object(HashMap::new());
        values.obj_insert("foo", JSONValue::from(vec![
            JSONValue::from(23.4),
            JSONValue::from("asdfasdf".to_owned()),
            JSONValue::from(true),
        ]))?;
        values["foo"].arr_push(JSONValue::from(()))?;

        let string = values.to_string();

        assert_eq!("{
    \"foo\": [
        23.4,
        \"asdfasdf\",
        true,
        null
    ]
}", format!("{string}"));

        Ok(())
    }

    #[test]
    fn big_parse_test() -> json::Result<()> {
        let mut s: String = String::from("{");

        for i in 0..2<<16 {
            s.push_str(&format!("\"name_{0}\":{0},", i));
        }

        s.push_str(&format!("\"name_{0}\":{0}", 2<<16));
        s.push('}');

        let t0 = time::Instant::now();
        let value = JSONValue::try_from(s.as_bytes().to_vec())?;
        let t1 = time::Instant::now();

        for i in 0..=2<<16 {
            let v: i32 = value[format!("name_{}", i)].cast()?;
            assert_eq!(i, v);
        }
        let t2 = time::Instant::now();
        println!("time to complete parse: {}", (t1-t0).as_secs_f64());
        println!("time to complete iteration: {}", (t2-t1).as_secs_f64());
        println!("total time: {}", (t2-t0).as_secs_f64());

        Ok(())
    }
}