1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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(())
    }
}