json_deserializer/
parser.rs

1use alloc::borrow::Cow;
2use alloc::string::String;
3use alloc::vec::Vec;
4
5use super::array::parse_array;
6use super::boolean::parse_false;
7use super::boolean::parse_true;
8use super::error::*;
9use super::null::parse_null;
10use super::number::parse_number;
11use super::object::parse_object;
12use super::string::parse_string;
13
14/// Typedef for the inside of an object.
15#[cfg(not(feature = "preserve_order"))]
16pub type Object<'a> = alloc::collections::BTreeMap<String, Value<'a>>;
17/// Typedef for the inside of an object.
18#[cfg(feature = "preserve_order")]
19pub type Object<'a> = indexmap::IndexMap<String, Value<'a>>;
20
21/// Reference to JSON data.
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum Number<'a> {
24    /// A float (contains exactly 1 period)
25    Float(&'a [u8], &'a [u8]),
26    /// An integer (contains exactly 0 periods)
27    Integer(&'a [u8], &'a [u8]),
28}
29
30/// Reference to JSON data.
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub enum Value<'a> {
33    /// A `null`
34    Null,
35    /// A string (i.e. something quoted; quotes are not part of this. Data has not been UTF-8 validated)
36    String(Cow<'a, str>),
37    /// A number (i.e. something starting with a number with an optional period)
38    Number(Number<'a>),
39    /// A bool (i.e. `false` or `true`)
40    Bool(bool),
41    /// An object (i.e. items inside curly brackets `{}` separated by colon `:` and comma `,`)
42    Object(Object<'a>),
43    /// An array (i.e. items inside squared brackets `[]` separated by comma `,`)
44    Array(Vec<Value<'a>>),
45}
46
47/// Parses JSON-compliant bytes into [`Value`]
48/// # Errors
49/// If and only if `json` is not valid JSON.
50/// # Panics
51/// If and only if there is not enough memory to allocate.
52pub fn parse(mut json: &[u8]) -> Result<Value, Error> {
53    parse_value(&mut json)
54}
55
56pub fn parse_value<'b, 'a>(values: &'b mut &'a [u8]) -> Result<Value<'a>, Error> {
57    skip_unused(values);
58    let token = current_token(values)?;
59    match token {
60        b'{' => parse_object(values).map(Value::Object),
61        b'[' => parse_array(values).map(Value::Array),
62        b'"' => parse_string(values).map(Value::String),
63        b'n' => parse_null(values).map(|_| Value::Null),
64        b't' => parse_true(values).map(|_| Value::Bool(true)),
65        b'f' => parse_false(values).map(|_| Value::Bool(false)),
66        b'0'..=b'9' | b'-' => parse_number(values).map(Value::Number),
67        other => Err(Error::InvalidToken(other)),
68    }
69}
70
71#[inline]
72pub fn skip_unused(values: &mut &[u8]) {
73    while let [first, rest @ ..] = values {
74        if !matches!(first, b'\n' | b' ' | b'\r' | b'\t') {
75            break;
76        }
77        *values = rest;
78    }
79}
80
81#[inline]
82pub fn current_token(values: &[u8]) -> Result<u8, Error> {
83    if let Some(t) = values.get(0) {
84        Ok(*t)
85    } else {
86        Err(Error::InvalidEOF)
87    }
88}