Skip to main content

sark_json/
scan.rs

1use crate::Result;
2use crate::error::Fail;
3
4pub struct Scan;
5
6impl Scan {
7    pub fn ws(input: &[u8], idx: &mut usize) {
8        while *idx < input.len() && input[*idx].is_ascii_whitespace() {
9            *idx += 1;
10        }
11    }
12
13    pub fn eat_byte(input: &[u8], idx: &mut usize, want: u8) -> bool {
14        if *idx < input.len() && input[*idx] == want {
15            *idx += 1;
16            true
17        } else {
18            false
19        }
20    }
21
22    pub fn expect_byte(input: &[u8], idx: &mut usize, want: u8) -> Result<()> {
23        if Self::eat_byte(input, idx, want) {
24            return Ok(());
25        }
26        Err(Fail::bad())
27    }
28
29    pub fn expect_prop(input: &[u8], idx: &mut usize, first: bool, want: &[u8]) -> Result<()> {
30        Self::ws(input, idx);
31        if !first {
32            Self::expect_byte(input, idx, b',')?;
33            Self::ws(input, idx);
34        }
35        Self::expect_byte(input, idx, b'"')?;
36        let end = idx.saturating_add(want.len());
37        if input.get(*idx..end) != Some(want) {
38            return Err(Fail::bad());
39        }
40        *idx = end;
41        Self::expect_byte(input, idx, b'"')?;
42        Self::ws(input, idx);
43        Self::expect_byte(input, idx, b':')?;
44        Self::ws(input, idx);
45        Ok(())
46    }
47
48    pub fn seek_name(input: &[u8], idx: &mut usize, want: &[u8]) -> Result<()> {
49        let need = want.len() + 3;
50        while idx.saturating_add(need) <= input.len() {
51            if input[*idx] == b'"' {
52                let key_start = idx.saturating_add(1);
53                let key_end = key_start.saturating_add(want.len());
54                if input.get(key_start..key_end) == Some(want)
55                    && input.get(key_end) == Some(&b'"')
56                    && input.get(key_end + 1) == Some(&b':')
57                {
58                    *idx = key_end + 2;
59                    return Ok(());
60                }
61            }
62            *idx += 1;
63        }
64        Err(Fail::bad())
65    }
66
67    pub fn eat_null(input: &[u8], idx: &mut usize) -> bool {
68        if input.get(*idx..(*idx + 4)) == Some(b"null") {
69            *idx += 4;
70            true
71        } else {
72            false
73        }
74    }
75
76    pub fn skip_plain_string(input: &[u8], idx: &mut usize) -> Result<()> {
77        Self::expect_byte(input, idx, b'"')?;
78        while *idx < input.len() {
79            match input[*idx] {
80                b'"' => {
81                    *idx += 1;
82                    return Ok(());
83                }
84                b'\\' => return Err(Fail::bad()),
85                _ => *idx += 1,
86            }
87        }
88        Err(Fail::bad())
89    }
90
91    pub fn skip_value(input: &[u8], idx: &mut usize) -> Result<()> {
92        Self::ws(input, idx);
93        if *idx >= input.len() {
94            return Err(Fail::bad());
95        }
96        match input[*idx] {
97            b'"' => {
98                let _ = Self::str_slice(input, idx)?;
99                Ok(())
100            }
101            b'{' => Self::skip_group(input, idx, b'{', b'}'),
102            b'[' => Self::skip_group(input, idx, b'[', b']'),
103            b't' => {
104                let _ = crate::parse::Parse::bool(input, idx)?;
105                Ok(())
106            }
107            b'f' => {
108                let _ = crate::parse::Parse::bool(input, idx)?;
109                Ok(())
110            }
111            b'n' => {
112                if input.get(*idx..(*idx + 4)) == Some(b"null") {
113                    *idx += 4;
114                    Ok(())
115                } else {
116                    Err(Fail::bad())
117                }
118            }
119            b'-' | b'0'..=b'9' => Self::skip_number(input, idx),
120            _ => Err(Fail::bad()),
121        }
122    }
123
124    fn skip_number(input: &[u8], idx: &mut usize) -> Result<()> {
125        let start = *idx;
126        let _ = Self::eat_byte(input, idx, b'-');
127        if !Self::skip_digits(input, idx) {
128            return Err(Fail::bad());
129        }
130        if Self::eat_byte(input, idx, b'.') && !Self::skip_digits(input, idx) {
131            return Err(Fail::bad());
132        }
133        if *idx < input.len() && (input[*idx] == b'e' || input[*idx] == b'E') {
134            *idx += 1;
135            if *idx < input.len() && (input[*idx] == b'+' || input[*idx] == b'-') {
136                *idx += 1;
137            }
138            if !Self::skip_digits(input, idx) {
139                return Err(Fail::bad());
140            }
141        }
142        if *idx == start {
143            return Err(Fail::bad());
144        }
145        Ok(())
146    }
147
148    fn skip_digits(input: &[u8], idx: &mut usize) -> bool {
149        let start = *idx;
150        while *idx < input.len() && input[*idx].is_ascii_digit() {
151            *idx += 1;
152        }
153        *idx != start
154    }
155
156    pub fn str_slice<'a>(input: &'a [u8], idx: &mut usize) -> Result<&'a [u8]> {
157        Self::expect_byte(input, idx, b'"')?;
158        let start = *idx;
159        while *idx < input.len() {
160            match input[*idx] {
161                b'\\' => {
162                    *idx += 2;
163                }
164                b'"' => {
165                    let end = *idx;
166                    *idx += 1;
167                    return Ok(&input[start..end]);
168                }
169                _ => {
170                    *idx += 1;
171                }
172            }
173        }
174        Err(Fail::bad())
175    }
176
177    pub(super) fn decode_str(input: &[u8]) -> Result<Vec<u8>> {
178        let mut out = Vec::with_capacity(input.len());
179        let mut idx = 0usize;
180        while idx < input.len() {
181            match input[idx] {
182                b'\\' => {
183                    idx += 1;
184                    if idx >= input.len() {
185                        return Err(Fail::bad());
186                    }
187                    match input[idx] {
188                        b'"' => out.push(b'"'),
189                        b'\\' => out.push(b'\\'),
190                        b'/' => out.push(b'/'),
191                        b'b' => out.push(0x08),
192                        b'f' => out.push(0x0c),
193                        b'n' => out.push(b'\n'),
194                        b'r' => out.push(b'\r'),
195                        b't' => out.push(b'\t'),
196                        _ => return Err(Fail::bad()),
197                    }
198                }
199                b => out.push(b),
200            }
201            idx += 1;
202        }
203        Ok(out)
204    }
205
206    fn skip_group(input: &[u8], idx: &mut usize, open: u8, close: u8) -> Result<()> {
207        Self::expect_byte(input, idx, open)?;
208        let mut depth = 1usize;
209        while *idx < input.len() {
210            match input[*idx] {
211                b'"' => {
212                    let _ = Self::str_slice(input, idx)?;
213                }
214                b if b == open => {
215                    depth += 1;
216                    *idx += 1;
217                }
218                b if b == close => {
219                    depth -= 1;
220                    *idx += 1;
221                    if depth == 0 {
222                        return Ok(());
223                    }
224                }
225                _ => {
226                    *idx += 1;
227                }
228            }
229        }
230        Err(Fail::bad())
231    }
232}