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