Skip to main content

json_bourne/
parser.rs

1use crate::error::{Error, ErrorKind};
2use crate::event::{Event, JsonStr};
3use crate::lexer::{DEFAULT_MAX_DEPTH, Frame, Lexer};
4
5#[derive(Copy, Clone, Debug, PartialEq, Eq)]
6enum State {
7    /// Document start — expecting a value, no events emitted yet.
8    Start,
9    /// Just emitted a value at the document root — only whitespace + EOF allowed.
10    DocumentEnd,
11    /// Inside an array, expecting either a value or `]`.
12    ArrayValueOrEnd,
13    /// Inside an array, just emitted a value, expecting `,` or `]`.
14    ArrayCommaOrEnd,
15    /// Inside an object, expecting either a key or `}`.
16    ObjectKeyOrEnd,
17    /// Inside an object, just emitted a key, expecting `:`. The streaming
18    /// fast-path fuses `:` consumption with the value parse so this state
19    /// rarely surfaces in `next_event`.
20    ObjectColon,
21    /// Inside an object, after `:`, expecting a value. Used by the
22    /// fast-path object API as a handoff point when the caller falls back
23    /// to `next_event` for a single value.
24    ObjectValue,
25    /// Inside an object, just emitted a value, expecting `,` or `}`.
26    ObjectCommaOrEnd,
27}
28
29/// Streaming JSON parser over a borrowed byte slice.
30///
31/// Pull-based: each call to [`Parser::next_event`] advances the input and
32/// returns one [`Event`]. Returns `Ok(None)` once the document has been fully
33/// consumed (and any trailing whitespace has been validated).
34///
35/// `Parser` is the streaming API. It owns a [`Lexer`] (the byte walker) plus
36/// a small grammar state machine that enforces JSON's "value, then comma,
37/// then value" structure when emitting events serially. Typed consumers
38/// (`json_bourne::FromJson`) drive the lexer directly and bypass this state
39/// machine — for them, the type's recursive structure already enforces the
40/// grammar, and the dispatch through `match self.state` is pure overhead.
41///
42/// `MAX_DEPTH` is the maximum nesting depth of containers the parser will
43/// accept. It is also the size of the inline nesting stack, so picking a
44/// small value reduces the parser's stack footprint as well as bounding
45/// untrusted input. The default is [`DEFAULT_MAX_DEPTH`].
46#[derive(Debug)]
47pub struct Parser<'input, const MAX_DEPTH: usize = DEFAULT_MAX_DEPTH> {
48    lex: Lexer<'input, MAX_DEPTH>,
49    state: State,
50}
51
52impl<'input, const MAX_DEPTH: usize> Parser<'input, MAX_DEPTH> {
53    /// Construct a parser over `input`.
54    ///
55    /// # Panics
56    ///
57    /// Panics if `input.len()` exceeds `MAX_INPUT_LEN`. See
58    /// [`Lexer::new`].
59    #[must_use]
60    pub const fn new(input: &'input [u8]) -> Self {
61        Self {
62            lex: Lexer::new(input),
63            state: State::Start,
64        }
65    }
66
67    /// Borrow the underlying lexer mutably. Typed consumers use this to
68    /// drive parsing directly without going through the `next_event`
69    /// state machine.
70    pub const fn lexer(&mut self) -> &mut Lexer<'input, MAX_DEPTH> {
71        &mut self.lex
72    }
73
74    #[must_use]
75    pub const fn position(&self) -> crate::error::Position {
76        self.lex.position()
77    }
78
79    /// The input slice the parser was constructed with.
80    #[must_use]
81    pub const fn input(&self) -> &'input [u8] {
82        self.lex.input()
83    }
84
85    pub fn next_event(&mut self) -> Result<Option<Event>, Error> {
86        self.lex.skip_whitespace();
87        match self.state {
88            State::Start => self.ev_start(),
89            State::DocumentEnd => self.ev_document_end(),
90            State::ArrayValueOrEnd => self.ev_array_value_or_end(),
91            State::ArrayCommaOrEnd => self.ev_array_comma_or_end(),
92            State::ObjectKeyOrEnd => self.ev_object_key_or_end(),
93            State::ObjectColon => self.ev_object_colon(),
94            State::ObjectValue => self.ev_object_value(),
95            State::ObjectCommaOrEnd => self.ev_object_comma_or_end(),
96        }
97    }
98
99    fn ev_start(&mut self) -> Result<Option<Event>, Error> {
100        match self.lex.peek() {
101            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
102            Some(_) => {
103                let ev = self.lex.read_value()?;
104                self.state = state_after_value(&ev, State::DocumentEnd);
105                Ok(Some(ev))
106            }
107        }
108    }
109
110    fn ev_document_end(&self) -> Result<Option<Event>, Error> {
111        if self.lex.peek().is_some() {
112            Err(self.lex.err(ErrorKind::TrailingData))
113        } else {
114            Ok(None)
115        }
116    }
117
118    fn ev_array_value_or_end(&mut self) -> Result<Option<Event>, Error> {
119        match self.lex.peek() {
120            Some(b']') => {
121                self.lex.bump();
122                Ok(Some(self.close_container(Frame::Array)?))
123            }
124            Some(_) => {
125                let ev = self.lex.read_value()?;
126                self.state = state_after_value(&ev, State::ArrayCommaOrEnd);
127                Ok(Some(ev))
128            }
129            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
130        }
131    }
132
133    fn ev_array_comma_or_end(&mut self) -> Result<Option<Event>, Error> {
134        match self.lex.peek() {
135            Some(b',') => {
136                self.lex.bump();
137                self.lex.skip_whitespace();
138                if self.lex.peek() == Some(b']') {
139                    return Err(self.lex.err(ErrorKind::UnexpectedByte(b']')));
140                }
141                let ev = self.lex.read_value()?;
142                self.state = state_after_value(&ev, State::ArrayCommaOrEnd);
143                Ok(Some(ev))
144            }
145            Some(b']') => {
146                self.lex.bump();
147                Ok(Some(self.close_container(Frame::Array)?))
148            }
149            Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
150            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
151        }
152    }
153
154    fn ev_object_key_or_end(&mut self) -> Result<Option<Event>, Error> {
155        match self.lex.peek() {
156            Some(b'}') => {
157                self.lex.bump();
158                Ok(Some(self.close_container(Frame::Object)?))
159            }
160            Some(b'"') => {
161                let s = self.lex.read_string()?;
162                self.state = State::ObjectColon;
163                Ok(Some(Event::Key(s)))
164            }
165            Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
166            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
167        }
168    }
169
170    fn ev_object_colon(&mut self) -> Result<Option<Event>, Error> {
171        match self.lex.peek() {
172            Some(b':') => {
173                self.lex.bump();
174                self.lex.skip_whitespace();
175                let ev = self.lex.read_value()?;
176                self.state = state_after_value(&ev, State::ObjectCommaOrEnd);
177                Ok(Some(ev))
178            }
179            Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
180            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
181        }
182    }
183
184    fn ev_object_value(&mut self) -> Result<Option<Event>, Error> {
185        let ev = self.lex.read_value()?;
186        self.state = state_after_value(&ev, State::ObjectCommaOrEnd);
187        Ok(Some(ev))
188    }
189
190    fn ev_object_comma_or_end(&mut self) -> Result<Option<Event>, Error> {
191        match self.lex.peek() {
192            Some(b',') => {
193                self.lex.bump();
194                self.lex.skip_whitespace();
195                if self.lex.peek() == Some(b'}') {
196                    return Err(self.lex.err(ErrorKind::UnexpectedByte(b'}')));
197                }
198                self.ev_object_key_or_end()
199            }
200            Some(b'}') => {
201                self.lex.bump();
202                self.close_container(Frame::Object).map(Some)
203            }
204            Some(b) => Err(self.lex.err(ErrorKind::UnexpectedByte(b))),
205            None => Err(self.lex.err(ErrorKind::UnexpectedEof)),
206        }
207    }
208
209    fn close_container(&mut self, expected: Frame) -> Result<Event, Error> {
210        self.lex.pop_frame(expected)?;
211        self.state = match self.lex.stack.top() {
212            None => State::DocumentEnd,
213            Some(Frame::Array) => State::ArrayCommaOrEnd,
214            Some(Frame::Object) => State::ObjectCommaOrEnd,
215        };
216        Ok(match expected {
217            Frame::Array => Event::EndArray,
218            Frame::Object => Event::EndObject,
219        })
220    }
221
222    // -----------------------------------------------------------------
223    // Fast-path methods for typed consumers.
224    //
225    // These mirror the methods on `Lexer` but additionally synchronize
226    // `self.state` so a subsequent `next_event` call resumes correctly.
227    // Typed consumers that drive the lexer directly via `Parser::lexer()`
228    // skip these and avoid the state writes entirely.
229    // -----------------------------------------------------------------
230
231    pub fn parse_i64_value(&mut self) -> Result<i64, Error> {
232        self.lex.parse_i64_value()
233    }
234
235    pub fn parse_str_value(&mut self) -> Result<&'input str, Error> {
236        self.lex.parse_str_value()
237    }
238
239    /// On `[` push a frame and, for empty arrays, pop and synchronize state.
240    pub fn array_start(&mut self) -> Result<bool, Error> {
241        let empty = self.lex.array_start()?;
242        if empty {
243            self.state = match self.lex.stack.top() {
244                None => State::DocumentEnd,
245                Some(Frame::Array) => State::ArrayCommaOrEnd,
246                Some(Frame::Object) => State::ObjectCommaOrEnd,
247            };
248        } else {
249            self.state = State::ArrayValueOrEnd;
250        }
251        Ok(empty)
252    }
253
254    pub fn array_continue(&mut self, end_byte: u8) -> Result<bool, Error> {
255        let closed = self.lex.array_continue(end_byte)?;
256        if closed {
257            self.state = match self.lex.stack.top() {
258                None => State::DocumentEnd,
259                Some(Frame::Array) => State::ArrayCommaOrEnd,
260                Some(Frame::Object) => State::ObjectCommaOrEnd,
261            };
262        }
263        Ok(closed)
264    }
265
266    pub fn object_first_key(&mut self) -> Result<Option<&'input str>, Error> {
267        let key = self.lex.object_first_key()?;
268        self.state = match key {
269            None => match self.lex.stack.top() {
270                None => State::DocumentEnd,
271                Some(Frame::Array) => State::ArrayCommaOrEnd,
272                Some(Frame::Object) => State::ObjectCommaOrEnd,
273            },
274            Some(_) => State::ObjectValue,
275        };
276        Ok(key)
277    }
278
279    pub fn object_next_key(&mut self) -> Result<Option<&'input str>, Error> {
280        let key = self.lex.object_next_key()?;
281        self.state = match key {
282            None => match self.lex.stack.top() {
283                None => State::DocumentEnd,
284                Some(Frame::Array) => State::ArrayCommaOrEnd,
285                Some(Frame::Object) => State::ObjectCommaOrEnd,
286            },
287            Some(_) => State::ObjectValue,
288        };
289        Ok(key)
290    }
291
292    /// Like [`object_first_key`], but returns the key as a [`JsonStr`]
293    /// span so the caller can decode escapes when present. The fast
294    /// `&str`-returning variant rejects any backslash; this one carries
295    /// escape-bearing keys through.
296    ///
297    /// [`object_first_key`]: Self::object_first_key
298    pub fn object_first_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
299        let key = self.lex.object_first_key_lex()?;
300        self.state = match key {
301            None => match self.lex.stack.top() {
302                None => State::DocumentEnd,
303                Some(Frame::Array) => State::ArrayCommaOrEnd,
304                Some(Frame::Object) => State::ObjectCommaOrEnd,
305            },
306            Some(_) => State::ObjectValue,
307        };
308        Ok(key)
309    }
310
311    /// Like [`object_next_key`], but returns the key as a [`JsonStr`]
312    /// span. See [`object_first_key_lex`].
313    ///
314    /// [`object_next_key`]: Self::object_next_key
315    /// [`object_first_key_lex`]: Self::object_first_key_lex
316    pub fn object_next_key_lex(&mut self) -> Result<Option<JsonStr>, Error> {
317        let key = self.lex.object_next_key_lex()?;
318        self.state = match key {
319            None => match self.lex.stack.top() {
320                None => State::DocumentEnd,
321                Some(Frame::Array) => State::ArrayCommaOrEnd,
322                Some(Frame::Object) => State::ObjectCommaOrEnd,
323            },
324            Some(_) => State::ObjectValue,
325        };
326        Ok(key)
327    }
328}
329
330#[inline]
331const fn state_after_value(ev: &Event, scalar_next: State) -> State {
332    match ev {
333        Event::StartObject => State::ObjectKeyOrEnd,
334        Event::StartArray => State::ArrayValueOrEnd,
335        _ => scalar_next,
336    }
337}