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