1use crate::{
10 memory::{Budgeted, BudgetedSmallVec, MemoryBudget, MemoryError, ProductionControl},
11 CancellationToken, QueryCancelled,
12};
13
14mod lexical;
15mod string;
16
17pub use string::{decode_json_string, decode_json_string_with_control};
18
19#[derive(Debug, thiserror::Error)]
20pub enum JsonReadError {
21 #[error("invalid JSON text")]
22 InvalidJson,
23 #[error(transparent)]
24 Memory(#[from] MemoryError),
25 #[error(transparent)]
26 Cancelled(#[from] QueryCancelled),
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30pub enum JsonToken<'a> {
31 Null,
32 Bool(bool),
33 Number(&'a str),
34 String(&'a [u8]),
36 Key(&'a [u8]),
37 StartArray,
38 EndArray,
39 StartObject,
40 EndObject,
41}
42
43#[derive(Debug, PartialEq, Eq)]
44pub struct JsonEvent<'a> {
45 pub token: JsonToken<'a>,
46 pub range: std::ops::Range<usize>,
48}
49
50#[derive(Clone, Copy)]
51enum Frame {
52 ArrayFirst,
53 ArrayValue,
54 ArrayAfter,
55 ObjectFirst,
56 ObjectKey,
57 ObjectValue,
58 ObjectAfter,
59}
60
61enum Stack {
63 Unbounded(Vec<Frame>),
64 Bounded(BudgetedSmallVec<[Frame; 16]>),
65}
66
67impl Stack {
68 fn frames(&mut self) -> &mut [Frame] {
69 match self {
70 Self::Unbounded(values) => values,
71 Self::Bounded(values) => values,
72 }
73 }
74
75 fn push(&mut self, frame: Frame) -> Result<(), JsonReadError> {
76 match self {
77 Self::Unbounded(values) => values.push(frame),
78 Self::Bounded(values) => values.push(frame)?,
79 }
80 Ok(())
81 }
82
83 fn pop(&mut self) {
84 match self {
85 Self::Unbounded(values) => {
86 values.pop();
87 }
88 Self::Bounded(values) => {
89 values.pop();
90 }
91 }
92 }
93}
94
95pub struct JsonReader<'a, 'c> {
97 input: &'a [u8],
98 position: usize,
99 stack: Stack,
100 cancellation: Option<&'c CancellationToken>,
101 production: Option<ProductionControl<'c>>,
102 root_started: bool,
103 depth_limit: Option<usize>,
104 ignored_string_escapes: bool,
105 validated_utf8: bool,
107}
108
109impl<'a, 'c> JsonReader<'a, 'c> {
110 pub fn new(input: &'a str, memory: &MemoryBudget, cancellation: &'c CancellationToken) -> Self {
111 Self {
112 validated_utf8: true,
113 ..Self::from_slice(input.as_bytes(), memory, cancellation)
114 }
115 }
116
117 pub fn from_slice(
118 input: &'a [u8],
119 memory: &MemoryBudget,
120 cancellation: &'c CancellationToken,
121 ) -> Self {
122 Self {
123 input,
124 position: 0,
125 stack: Stack::Bounded(BudgetedSmallVec::new(memory)),
126 cancellation: Some(cancellation),
127 production: None,
128 root_started: false,
129 depth_limit: None,
130 ignored_string_escapes: false,
131 validated_utf8: false,
132 }
133 }
134
135 pub(crate) fn unbounded(input: &'a str) -> Self {
136 Self {
137 input: input.as_bytes(),
138 position: 0,
139 stack: Stack::Unbounded(Vec::new()),
140 cancellation: None,
141 production: None,
142 root_started: false,
143 depth_limit: None,
144 ignored_string_escapes: false,
145 validated_utf8: true,
146 }
147 }
148
149 pub fn with_control(input: &'a str, control: &ProductionControl<'c>) -> Self {
151 Self {
152 input: input.as_bytes(),
153 position: 0,
154 stack: control.budget().map_or_else(
155 || Stack::Unbounded(Vec::new()),
156 |budget| Stack::Bounded(BudgetedSmallVec::new(budget)),
157 ),
158 cancellation: None,
159 production: Some(*control),
160 root_started: false,
161 depth_limit: None,
162 ignored_string_escapes: false,
163 validated_utf8: true,
164 }
165 }
166
167 #[must_use]
169 pub fn with_depth_limit(mut self, limit: usize) -> Self {
170 self.depth_limit = Some(limit);
171 self
172 }
173
174 #[must_use]
176 pub fn with_ignored_string_escapes(mut self) -> Self {
177 self.ignored_string_escapes = true;
178 self
179 }
180
181 pub fn next_event(&mut self) -> Result<Option<JsonEvent<'a>>, JsonReadError> {
182 self.check()?;
183 self.skip_whitespace()?;
184 let frame = self.stack.frames().last().copied();
185 match frame {
186 None if self.root_started => {
187 return if self.position == self.input.len() {
188 Ok(None)
189 } else {
190 Err(JsonReadError::InvalidJson)
191 };
192 }
193 None => self.root_started = true,
194 Some(Frame::ArrayFirst) if self.peek() == Some(b']') => {
195 return self.close(JsonToken::EndArray)
196 }
197 Some(Frame::ObjectFirst) if self.peek() == Some(b'}') => {
198 return self.close(JsonToken::EndObject)
199 }
200 Some(Frame::ArrayAfter) => match self.peek() {
201 Some(b']') => return self.close(JsonToken::EndArray),
202 Some(b',') => {
203 self.advance()?;
204 self.skip_whitespace()?;
205 self.replace(Frame::ArrayValue);
206 }
207 _ => return Err(JsonReadError::InvalidJson),
208 },
209 Some(Frame::ObjectAfter) => match self.peek() {
210 Some(b'}') => return self.close(JsonToken::EndObject),
211 Some(b',') => {
212 self.advance()?;
213 self.skip_whitespace()?;
214 self.replace(Frame::ObjectKey);
215 }
216 _ => return Err(JsonReadError::InvalidJson),
217 },
218 _ => {}
219 }
220 match self.stack.frames().last().copied() {
221 Some(Frame::ObjectFirst | Frame::ObjectKey) => {
222 let start = self.position;
223 let key = self.string()?;
224 self.replace(Frame::ObjectValue);
225 return Ok(Some(self.event(start, JsonToken::Key(key))));
226 }
227 Some(Frame::ObjectValue) => {
228 self.consume(b':')?;
229 self.skip_whitespace()?;
230 self.replace(Frame::ObjectAfter);
231 }
232 Some(Frame::ArrayFirst | Frame::ArrayValue) => self.replace(Frame::ArrayAfter),
233 _ => {}
234 }
235 self.value().map(Some)
236 }
237
238 fn value(&mut self) -> Result<JsonEvent<'a>, JsonReadError> {
239 let start = self.position;
240 let token = match self.peek().ok_or(JsonReadError::InvalidJson)? {
241 b'n' => {
242 self.keyword(b"null")?;
243 JsonToken::Null
244 }
245 b't' => {
246 self.keyword(b"true")?;
247 JsonToken::Bool(true)
248 }
249 b'f' => {
250 self.keyword(b"false")?;
251 JsonToken::Bool(false)
252 }
253 b'"' => JsonToken::String(self.string()?),
254 b'-' | b'0'..=b'9' => JsonToken::Number(self.number()?),
255 b'[' | b'{' => {
256 if self
257 .depth_limit
258 .is_some_and(|limit| self.stack.frames().len() >= limit)
259 {
260 return Err(JsonReadError::InvalidJson);
261 }
262 let array = self.peek() == Some(b'[');
263 self.stack.push(if array {
264 Frame::ArrayFirst
265 } else {
266 Frame::ObjectFirst
267 })?;
268 self.advance()?;
269 if array {
270 JsonToken::StartArray
271 } else {
272 JsonToken::StartObject
273 }
274 }
275 _ => return Err(JsonReadError::InvalidJson),
276 };
277 self.check()?;
278 Ok(self.event(start, token))
279 }
280
281 fn replace(&mut self, frame: Frame) {
282 *self.stack.frames().last_mut().expect("open JSON container") = frame;
283 }
284
285 fn close(&mut self, token: JsonToken<'a>) -> Result<Option<JsonEvent<'a>>, JsonReadError> {
286 let start = self.position;
287 self.advance()?;
288 self.stack.pop();
289 Ok(Some(self.event(start, token)))
290 }
291
292 fn event(&self, start: usize, token: JsonToken<'a>) -> JsonEvent<'a> {
293 JsonEvent {
294 token,
295 range: start..self.position,
296 }
297 }
298
299 fn check(&self) -> Result<(), JsonReadError> {
300 if let Some(cancellation) = self.cancellation {
301 cancellation.check()?;
302 }
303 if let Some(production) = self.production {
304 production.check_cancellation()?;
305 }
306 Ok(())
307 }
308}
309
310#[cfg(test)]
311mod tests;