Function simple_json_parser::parse

source ·
pub fn parse<'a>(
    on: &'a str,
    cb: impl for<'b> FnMut(&'b [JSONKey<'a>], RootJSONValue<'a>)
) -> Result<(), JSONParseError>
Expand description

If you want to return early (not parse the whole input) use parse_with_exit_signal

§Errors

Returns an error if it tries to parse invalid JSON input

Examples found in repository?
examples/to_object_unsafe.rs (lines 30-72)
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
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = std::env::args().nth(1).ok_or("Expected first argument")?;
    let content = std::fs::read_to_string(path)?;

    pub type Object = HashMap<String, Value>;

    #[derive(Debug)]
    pub enum Value {
        Object(Object),
        String(String),
        Number(String),
        Boolean(bool),
        Null,
    }

    impl Value {
        pub fn new_empty_object() -> Self {
            Self::Object(HashMap::new())
        }
    }

    let mut root = Object::new();

    let _res = parse(&content, |keys, value| {
        let [path @ .., end] = keys else {
            unreachable!("empty key change")
        };
        let pointer = &mut root;

        let mut to_add_to: *mut Object = pointer;

        for key in path {
            let name = match key {
                JSONKey::Slice(s) => (*s).to_string(),
                JSONKey::Index(i) => i.to_string(),
            };
            if let Some(Value::Object(ref mut obj)) =
                unsafe { (to_add_to.as_mut().unwrap()).get_mut(&name) }
            {
                to_add_to = obj;
            } else {
                let value = unsafe {
                    (to_add_to.as_mut().unwrap())
                        .entry(name)
                        .or_insert_with(Value::new_empty_object)
                };
                if let Value::Object(ref mut obj) = value {
                    to_add_to = obj;
                }
            }
        }
        let name = match end {
            JSONKey::Slice(s) => (*s).to_string(),
            JSONKey::Index(i) => i.to_string(),
        };
        let value = match value {
            RootJSONValue::String(s) => Value::String(s.to_string()),
            RootJSONValue::Number(n) => Value::Number(n.to_string()),
            RootJSONValue::True => Value::Boolean(true),
            RootJSONValue::False => Value::Boolean(false),
            RootJSONValue::Null => Value::Null,
        };
        unsafe {
            (to_add_to.as_mut().unwrap()).insert(name, value);
        }
    });

    eprintln!("Parsed: {root:#?}");
    Ok(())
}
More examples
Hide additional examples
examples/to_object.rs (line 60)
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
fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = std::env::args().nth(1).ok_or("Expected first argument")?;
    let content = std::fs::read_to_string(path)?;

    pub type Object = HashMap<String, Value>;

    #[derive(Debug)]
    pub enum Value {
        Object(Object),
        String(String),
        Number(String),
        Boolean(bool),
        Null,
    }

    impl Value {
        pub fn new_empty_object() -> Self {
            Self::Object(HashMap::new())
        }

        pub fn set<'a>(&'a mut self, keys: &'a [JSONKey<'a>], value: RootJSONValue<'a>) {
            if let Value::Object(ref mut obj) = self {
                if let [last] = keys {
                    let name = match last {
                        JSONKey::Slice(s) => (*s).to_string(),
                        JSONKey::Index(i) => i.to_string(),
                    };
                    let value = match value {
                        RootJSONValue::String(s) => Value::String(s.to_string()),
                        RootJSONValue::Number(n) => Value::Number(n.to_string()),
                        RootJSONValue::True => Value::Boolean(true),
                        RootJSONValue::False => Value::Boolean(false),
                        RootJSONValue::Null => Value::Null,
                    };
                    let existing = obj.insert(name, value);
                    debug_assert!(existing.is_none());
                } else if let [first, others @ ..] = keys {
                    let name = match first {
                        JSONKey::Slice(s) => (*s).to_string(),
                        JSONKey::Index(i) => i.to_string(),
                    };
                    obj.entry(name)
                        .or_insert_with(Value::new_empty_object)
                        .set(others, value);
                } else {
                    unreachable!("empty keys")
                }
            } else {
                unreachable!()
            }
        }
    }

    let mut root = Value::new_empty_object();

    parse(&content, |keys, value| root.set(keys, value))?;

    eprintln!("Parsed: {root:#?}");
    Ok(())
}
examples/scan.rs (line 90)
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
fn main() {
    let base = r#"{
        "name": "ezno",
        "version": "0.0.14",
        "description": "A JavaScript compiler and TypeScript checker written in Rust with a focus on static analysis and runtime performance",
        "license": "MIT",
        "repository": "https://github.com/kaleidawave/ezno",
        "main": "./dist/index.mjs",
        "module": "./dist/index.mjs",
        "type": "module",
        "exports": {
            ".": {
                "import": "./dist/index.mjs"
            },
            "./initialised": {
                "import": "./dist/initialised.mjs"
            }
        },
        "scripts": {
            "clean": "rmdir dist && rmdir build",
            "build": "cargo build --lib --target wasm32-unknown-unknown && npm run bind && npm run build-js",
            "build-release": "cargo build --lib --release --target wasm32-unknown-unknown && npm run bind-release && npm run build-js",
            "bind": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/debug/ezno_lib.wasm",
            "bind-release": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/release/ezno_lib.wasm",
            "build-js": "unbuild && cp ./build/ezno_lib_bg.wasm dist/shared && cp src/cli_node.cjs dist/cli.cjs",
            "test": "npm run build && npm run run-tests",
            "run-tests": "node test.mjs && deno run -A test.mjs"
        },
        "keywords": [
            "typescript",
            "checker",
            "type-checker",
            "compiler"
        ],
        "files": [
            "dist"
        ],
        "bin": {
            "ezno": "./dist/cli.mjs"
        },
        "author": {
            "name": "Ben",
            "email": "kaleidawave@gmail.com",
            "url": "https://kaleidawave.github.io/"
        },
        "funding": {
            "type": "individual",
            /*
                multiline comment
             */
            "url": "https://github.com/sponsors/kaleidawave"
        },
        "build": {
            "failOnWarn": false,
            "entries": [
                {
                    "builder": "rollup",
                    "input": "./src/index"
                },
                {
                    "builder": "rollup",
                    "input": "./src/initialised"
                },
                {
                    "builder": "rollup",
                    "input": "./src/cli"
                }
            ],
            // some comment
            "rollup": {
                "commonjs": true,
                "esbuild": {
                    "target": "esnext"
                }
            }
        },
        "devDependencies": {
            "unbuild": "^1.1.2"
        }
    }"#;

    let content = if let Some(path) = std::env::args().nth(1) {
        std::fs::read_to_string(path).unwrap()
    } else {
        base.to_owned()
    };

    let result = parse(&content, |keys, value| eprintln!("{keys:?} -> {value:?}"));

    if let Err(JSONParseError { at, reason }) = result {
        eprintln!("{reason:?} @ {at}");
    }
}