Skip to main content

deser_json/
stream.rs

1// @generated from deser-template-json/src/stream.rs by
2// deser-template-json/generate.py.  Do not edit.
3//! Reading JSON streams.
4#[cfg(feature = "io")]
5use std::io::Read;
6
7#[cfg(feature = "io")]
8use deser_core::de::DeserializeOwned;
9use deser_core::de::{self, DeserializeDriver, Frame, Progress};
10use deser_core::{Error, ErrorKind, State};
11
12use crate::Trailing;
13use crate::de::{Deserializer, DeserializerConfig};
14use crate::parser::{Copying, Discard, Options, Parser, Progress as ParseProgress};
15use crate::scan::skip_to_escape;
16
17fn is_whitespace(byte: u8) -> bool {
18    matches!(byte, b' ' | b'\n' | b'\t' | b'\r')
19}
20
21/// Returns where the next token starts and if it's there.
22///
23/// At the end of the input there is no token.
24fn skip_whitespace(input: &[u8], pos: usize, _eof: bool) -> (usize, bool) {
25    match input[pos..].iter().position(|&b| !is_whitespace(b)) {
26        Some(index) => (pos + index, true),
27        None => (input.len(), false),
28    }
29}
30
31/// The state of a JSON stream that is read.
32#[derive(Debug, Default)]
33struct StreamState {
34    // `Trailing::Strict`: the value was read
35    done: bool,
36    // parses values while their input arrives (see `drive_partial`)
37    parser: Parser,
38    // the rest of a value that failed in a sink is skipped from the
39    // position in the input
40    skipping: Option<usize>,
41    // parsing failed, the stream cannot be continued
42    failed: bool,
43    // the stream ended within a value
44    ended: bool,
45    // the position up to which the input was scanned
46    pos: usize,
47    // `Trailing::Stop`: the value being scanned
48    value: Option<Value>,
49}
50
51/// The state of the scan of a value.
52#[derive(Debug)]
53struct Value {
54    start: usize,
55    kind: ValueKind,
56    depth: usize,
57    in_string: bool,
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61enum ValueKind {
62    /// A number or literal.
63    Scalar,
64    /// A string, map or sequence.
65    Structure,
66}
67
68fn frame_all(state: &mut StreamState, input: &[u8], eof: bool) -> Result<Frame, Error> {
69    if state.done {
70        // only whitespace may follow the value
71        return trailing_whitespace(input, 0, eof).map(|progress| match progress {
72            Progress::End => Frame::End,
73            Progress::NeedMore { consumed } => Frame::Incomplete { consumed },
74            Progress::Done { .. } => unreachable!(),
75        });
76    }
77    if !eof {
78        return Ok(Frame::Incomplete { consumed: 0 });
79    }
80    let (start, _) = skip_whitespace(input, 0, eof);
81    Ok(if start < input.len() {
82        state.done = true;
83        Frame::Value {
84            start,
85            end: input.len(),
86            consumed: input.len(),
87        }
88    } else {
89        Frame::End
90    })
91}
92
93/// Checks that only whitespace follows a value.
94///
95/// `offset` is the offset of the input in the stream for errors.
96fn trailing_whitespace(input: &[u8], offset: usize, eof: bool) -> Result<Progress, Error> {
97    match skip_whitespace(input, 0, eof) {
98        (pos, _) if pos == input.len() && eof => Ok(Progress::End),
99        (pos, false) if !eof => Ok(Progress::NeedMore { consumed: pos }),
100        (pos, _) => Err(Error::with_offset(
101            ErrorKind::Syntax,
102            "garbage after input",
103            offset + pos,
104        )),
105    }
106}
107
108fn frame_line(state: &mut StreamState, input: &[u8], eof: bool) -> Frame {
109    let end = input[state.pos..]
110        .iter()
111        .position(|&b| b == b'\n')
112        .map(|index| state.pos + index);
113    let end = match end {
114        Some(end) => end,
115        None if eof => input.len(),
116        None => {
117            state.pos = input.len();
118            return Frame::Incomplete { consumed: 0 };
119        }
120    };
121    state.pos = 0;
122    let consumed = (end + 1).min(input.len());
123    match skip_whitespace(&input[..end], 0, true) {
124        (start, _) if start < end => Frame::Value {
125            start,
126            end,
127            consumed,
128        },
129        _ if consumed == 0 => Frame::End,
130        // blank lines are skipped
131        _ => Frame::Incomplete { consumed },
132    }
133}
134
135fn frame_value(state: &mut StreamState, input: &[u8], eof: bool) -> Frame {
136    let value = match state.value {
137        Some(ref mut value) => value,
138        None => {
139            let start = match skip_whitespace(input, 0, eof) {
140                (start, true) => start,
141                (_, false) if input.is_empty() && eof => return Frame::End,
142                (consumed, false) => return Frame::Incomplete { consumed },
143            };
144            let (kind, depth, in_string) = match input[start] {
145                b'"' => (ValueKind::Structure, 0, true),
146                b'{' | b'[' => (ValueKind::Structure, 1, false),
147                // a value cannot start with these, the parser reports the
148                // error
149                b'}' | b']' | b',' | b':' => {
150                    return Frame::Value {
151                        start,
152                        end: start + 1,
153                        consumed: start + 1,
154                    };
155                }
156                _ => (ValueKind::Scalar, 0, false),
157            };
158            state.pos = start + 1;
159            state.value.insert(Value {
160                start,
161                kind,
162                depth,
163                in_string,
164            })
165        }
166    };
167
168    let end = match value.kind {
169        ValueKind::Scalar => {
170            let end = input[state.pos..].iter().position(|&b| match b {
171                b'{' | b'}' | b'[' | b']' | b',' | b':' | b'"' => true,
172                _ => is_whitespace(b),
173            });
174            match end {
175                Some(index) => Some(state.pos + index),
176                None => {
177                    state.pos = input.len();
178                    None
179                }
180            }
181        }
182        ValueKind::Structure => scan_structure(input, &mut state.pos, value),
183    };
184
185    let start = value.start;
186    match end {
187        Some(end) => {
188            state.value = None;
189            state.pos = 0;
190            Frame::Value {
191                start,
192                end,
193                consumed: end,
194            }
195        }
196        // the value is incomplete, the parser reports the error
197        None if eof => {
198            state.value = None;
199            state.pos = 0;
200            Frame::Value {
201                start,
202                end: input.len(),
203                consumed: input.len(),
204            }
205        }
206        None => {
207            // discard the whitespace before the value
208            value.start = 0;
209            state.pos -= start;
210            Frame::Incomplete { consumed: start }
211        }
212    }
213}
214
215/// Scans a string, map or sequence from `pos`.
216///
217/// Returns the end of the value if it's complete.
218fn scan_structure(input: &[u8], pos: &mut usize, value: &mut Value) -> Option<usize> {
219    let mut index = *pos;
220    while index < input.len() {
221        if value.in_string {
222            index = skip_to_escape(input, index);
223            let byte = input.get(index).copied();
224            match byte {
225                Some(b'"') => {
226                    value.in_string = false;
227                    index += 1;
228                    if value.depth == 0 {
229                        return Some(index);
230                    }
231                }
232                Some(b'\\') => {
233                    // the escaped byte is scanned again with more input
234                    if index + 1 >= input.len() {
235                        break;
236                    }
237                    index += 2;
238                }
239                // control characters are reported by the parser
240                Some(_) => index += 1,
241                None => break,
242            }
243        } else {
244            match input[index] {
245                b'"' => {
246                    value.in_string = true;
247                }
248                b'{' | b'[' => value.depth += 1,
249                b'}' | b']' => {
250                    value.depth -= 1;
251                    if value.depth == 0 {
252                        return Some(index + 1);
253                    }
254                }
255                _ => {}
256            }
257            index += 1;
258        }
259    }
260    *pos = index;
261    None
262}
263
264/// Reads a stream of JSON values (see [`deser::stream`](deser_core::stream)).
265///
266/// How the stream is split depends on [`DeserializerConfig::set_trailing`]:
267///
268/// * [`Trailing::Strict`]: the stream holds a single value which is parsed
269///   once the whole stream was read.
270/// * [`Trailing::Newline`]: every line holds a value ([JSON
271///   Lines](https://jsonlines.org/)).  Blank lines are skipped and errors
272///   only discard their line, reading continues with the next one.
273/// * [`Trailing::Stop`]: values follow each other (optionally separated by
274///   whitespace) and are split where they end.  Numbers at the end of the
275///   stream are only complete at the end of the stream, other values are
276///   complete once their last byte was read.  Reading continues after
277///   values that fail to deserialize, values that are not valid JSON end
278///   the stream (unless they are read from their frames).
279///
280/// Except for JSON Lines, values which do not borrow are deserialized while
281/// their input arrives (see
282/// [`StreamDeserializer::drive_partial`](de::StreamDeserializer::drive_partial))
283/// so only incomplete tokens are buffered.
284///
285/// ```
286/// # #[cfg(feature = "io")] {
287/// use deser_json::{DeserializerConfig, Trailing};
288///
289/// const LINES: DeserializerConfig =
290///     DeserializerConfig::builder().trailing(Trailing::Newline).build();
291/// let mut reader = LINES.reader(&b"[1, 2]\n[3]\n"[..]);
292/// assert_eq!(reader.read::<Vec<u32>>().unwrap(), Some(vec![1, 2]));
293/// assert_eq!(reader.read::<Vec<u32>>().unwrap(), Some(vec![3]));
294/// assert_eq!(reader.read::<Vec<u32>>().unwrap(), None);
295/// # }
296/// ```
297///
298/// Values which are read from their frames are parsed like with a
299/// [`Deserializer`], so they can borrow from the stream's buffer (see
300/// [`InputBuffer::deserialize`](deser_core::stream::InputBuffer::deserialize)).  The input ranges (and thus
301/// locations) of these values refer to the start of their line (or value),
302/// those of values that are deserialized while their input arrives to the
303/// stream.
304#[derive(Debug)]
305pub struct StreamDeserializer {
306    config: DeserializerConfig,
307    state: StreamState,
308}
309
310impl Default for StreamDeserializer {
311    fn default() -> StreamDeserializer {
312        StreamDeserializer::new()
313    }
314}
315
316impl StreamDeserializer {
317    /// Creates a stream deserializer.
318    pub fn new() -> StreamDeserializer {
319        StreamDeserializer::with_config(DeserializerConfig::new())
320    }
321
322    /// Creates a stream deserializer with the given configuration.
323    pub fn with_config(config: DeserializerConfig) -> StreamDeserializer {
324        StreamDeserializer {
325            config,
326            state: StreamState::default(),
327        }
328    }
329
330    /// Returns the configuration.
331    pub fn config(&self) -> &DeserializerConfig {
332        &self.config
333    }
334
335    /// Skips what precedes the next value.
336    ///
337    /// This skips the rest of a value that failed in a sink and the
338    /// whitespace before the next value.  Returns where the value starts,
339    /// or the progress if there is no value (yet).
340    fn skip_to_value(
341        &mut self,
342        input: &[u8],
343        offset: usize,
344        eof: bool,
345    ) -> Result<Result<usize, Progress>, Error> {
346        let options = self.options();
347        let state = &mut self.state;
348        if state.ended {
349            return Ok(Err(Progress::End));
350        }
351        if state.failed {
352            return Err(Error::new(
353                ErrorKind::InvalidState,
354                "cannot continue after an error",
355            ));
356        }
357
358        // skip the rest of a value that failed in a sink
359        let mut pos = 0;
360        if let Some(skip) = state.skipping {
361            let mut discard = Discard(State::new());
362            match state
363                .parser
364                .parse(input, skip, eof, offset, options, &mut discard)
365            {
366                Ok(ParseProgress::Done(end)) => {
367                    state.skipping = None;
368                    state.done = self.config.trailing_mode() == Trailing::Strict;
369                    pos = end;
370                }
371                Ok(ParseProgress::NeedMore(consumed)) => {
372                    state.skipping = Some(0);
373                    return Ok(Err(Progress::NeedMore { consumed }));
374                }
375                Err(err) => {
376                    state.parser.reset();
377                    state.skipping = None;
378                    state.failed = true;
379                    return Err(err);
380                }
381            }
382        }
383
384        if !state.parser.is_idle() {
385            return Ok(Ok(pos));
386        }
387        if state.done {
388            return match trailing_whitespace(&input[pos..], offset + pos, eof)? {
389                Progress::NeedMore { consumed } => Ok(Err(Progress::NeedMore {
390                    consumed: pos + consumed,
391                })),
392                progress => Ok(Err(progress)),
393            };
394        }
395        // a new value, skip the whitespace before it
396        let token;
397        (pos, token) = skip_whitespace(input, pos, eof);
398        if !token && (pos == input.len() || !eof) {
399            return Ok(Err(if eof {
400                Progress::End
401            } else {
402                Progress::NeedMore { consumed: pos }
403            }));
404        }
405        Ok(Ok(pos))
406    }
407
408    /// Returns the options of the parser.
409    fn options(&self) -> Options {
410        Options {
411            validate_utf8: true,
412            exact_numbers: self.config.exact_numbers_enabled(),
413        }
414    }
415}
416
417impl de::StreamDeserializer for StreamDeserializer {
418    fn context(&self) -> deser_core::Context {
419        self.config.context().clone()
420    }
421
422    fn frame(&mut self, input: &[u8], eof: bool) -> Result<Frame, Error> {
423        let state = &mut self.state;
424        match self.config.trailing_mode() {
425            Trailing::Strict => frame_all(state, input, eof),
426            Trailing::Newline => Ok(frame_line(state, input, eof)),
427            Trailing::Stop => Ok(frame_value(state, input, eof)),
428        }
429    }
430
431    fn drive_frame<'de>(
432        &mut self,
433        frame: &'de [u8],
434        driver: &mut DeserializeDriver<'_, 'de>,
435    ) -> Result<(), Error> {
436        Deserializer::from_frame(frame, &self.config).drive(driver)
437    }
438
439    fn is_text(&self) -> bool {
440        true
441    }
442
443    /// JSON Lines are read line by line, the other values while their
444    /// input arrives.
445    fn supports_partial(&self) -> bool {
446        self.config.trailing_mode() != Trailing::Newline
447    }
448
449    fn drive_partial(
450        &mut self,
451        input: &[u8],
452        offset: usize,
453        eof: bool,
454        driver: &mut DeserializeDriver<'_, '_>,
455    ) -> Result<Progress, Error> {
456        let pos = match self.skip_to_value(input, offset, eof)? {
457            Ok(pos) => pos,
458            Err(progress) => return Ok(progress),
459        };
460        let options = self.options();
461        let state = &mut self.state;
462        match state
463            .parser
464            .parse(input, pos, eof, offset, options, &mut Copying(driver))
465        {
466            Ok(ParseProgress::Done(end)) => {
467                state.done = self.config.trailing_mode() == Trailing::Strict;
468                Ok(Progress::Done { consumed: end })
469            }
470            Ok(ParseProgress::NeedMore(consumed)) => Ok(Progress::NeedMore { consumed }),
471            Err(err) => {
472                if let Some(resume) = state.parser.recoverable() {
473                    // a sink failed, the next call continues after the
474                    // value.  The input is not consumed on errors.
475                    state.skipping = Some(resume);
476                } else {
477                    state.parser.reset();
478                    // after an incomplete value at the end there are no
479                    // more values
480                    state.ended = eof && err.kind() == ErrorKind::EndOfFile;
481                    state.failed = true;
482                }
483                Err(err)
484            }
485        }
486    }
487
488    fn peek(&mut self, input: &[u8], eof: bool) -> Result<Option<Progress>, Error> {
489        if !de::StreamDeserializer::supports_partial(self) {
490            return Ok(None);
491        }
492        Ok(Some(match self.skip_to_value(input, 0, eof)? {
493            Ok(pos) => Progress::Done { consumed: pos },
494            Err(progress) => progress,
495        }))
496    }
497}
498
499#[cfg(feature = "io")]
500impl DeserializerConfig {
501    /// Creates a reader of a stream of values (see
502    /// [`deser::io::Reader`](deser_core::io::Reader)).
503    ///
504    /// See [`StreamDeserializer`] for how the stream is split into values.
505    pub fn reader<R: Read>(&self, reader: R) -> deser_core::io::Reader<R, StreamDeserializer> {
506        deser_core::io::Reader::new(reader, StreamDeserializer::with_config(self.clone()))
507    }
508
509    /// Deserializes a value from a reader.
510    ///
511    /// See [`from_reader`].
512    pub fn from_reader<T: DeserializeOwned, R: Read>(&self, reader: R) -> Result<T, Error> {
513        deser_core::io::from_reader(reader, StreamDeserializer::with_config(self.clone()))
514    }
515}
516
517/// Deserializes a value from a reader.
518///
519/// The reader is read to the end.  Only whitespace may follow the value.
520/// The reader does not need to be buffered.  To read more than one value
521/// (for instance JSON Lines) use [`DeserializerConfig::reader`].
522///
523/// ```
524/// let value: Vec<u32> =
525///     deser_json::from_reader(&b"[1, 2, 3]"[..]).unwrap();
526/// assert_eq!(value, [1, 2, 3]);
527/// ```
528#[cfg(feature = "io")]
529pub fn from_reader<T: DeserializeOwned, R: Read>(reader: R) -> Result<T, Error> {
530    DeserializerConfig::new().from_reader(reader)
531}