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