Skip to main content

deser_json/
de.rs

1// @generated from deser-template-json/src/de.rs by
2// deser-template-json/generate.py.  Do not edit.
3use alloc::string::String;
4use alloc::sync::Arc;
5use core::marker::PhantomData;
6use core::str;
7
8use deser_core::__format::{MakeSink, deserialize_value, drive_value};
9use deser_core::de::{self, Deserialize, DeserializeDriver};
10use deser_core::{BytesFormat, Error, ErrorKind, Source};
11
12use crate::Trailing;
13use crate::parser::{Borrowing, Cursor, Options, Parser, Progress};
14
15/// Configures how JSON is deserialized.
16///
17/// The configuration is independent of the input so it can be created once
18/// (even as a constant) and used for many inputs.  The methods
19/// [`from_str`](Self::from_str) and [`from_slice`](Self::from_slice) work
20/// like the functions of the same name.  To create a [`Deserializer`] with
21/// the configuration use [`Deserializer::from_str_with_config`] or
22/// [`Deserializer::from_slice_with_config`].
23///
24/// ```
25/// use deser_json::DeserializerConfig;
26///
27/// const CONFIG: DeserializerConfig =
28///     DeserializerConfig::new().exact_numbers(false);
29/// let value: Vec<f64> = CONFIG.from_str("[0.10, 1e5]").unwrap();
30/// assert_eq!(value, [0.1, 1e5]);
31/// ```
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct DeserializerConfig {
34    track_locations: bool,
35    exact_numbers: bool,
36    trailing: Trailing,
37    bytes: BytesFormat,
38}
39
40impl Default for DeserializerConfig {
41    fn default() -> DeserializerConfig {
42        DeserializerConfig::new()
43    }
44}
45
46impl DeserializerConfig {
47    /// Creates the default configuration.
48    pub const fn new() -> DeserializerConfig {
49        DeserializerConfig {
50            track_locations: false,
51            exact_numbers: true,
52            trailing: Trailing::Strict,
53            bytes: BytesFormat::BASE64,
54        }
55    }
56
57    /// Sets how strings are decoded into bytes.
58    ///
59    /// JSON has no bytes, types that expect bytes (like `Vec<u8>`) accept
60    /// strings and sequences of integers instead.  By default strings are
61    /// decoded as base64, both with the standard and the URL-safe alphabet
62    /// and with or without padding.  This changes how strings are decoded,
63    /// for [`BytesFormat::SEQ`] they are still decoded as base64.
64    ///
65    /// ```
66    /// let value: Vec<u8> =
67    ///     deser_json::from_str(r#""Af8=""#).unwrap();
68    /// assert_eq!(value, [1, 255]);
69    /// let value: Vec<u8> =
70    ///     deser_json::from_str(r#""Af8""#).unwrap();
71    /// assert_eq!(value, [1, 255]);
72    /// let value: Vec<u8> =
73    ///     deser_json::from_str("[1, 255]").unwrap();
74    /// assert_eq!(value, [1, 255]);
75    /// ```
76    ///
77    /// Strings in other encodings than base64 need this, for instance hex
78    /// (`BytesFormat::encoded::<deser_encoding::Hex>()` with
79    /// [`deser-encoding`](https://docs.rs/deser-encoding)).
80    ///
81    /// The format is placed into the state (see [bytes](deser_core::adapters#bytes)).  Values
82    /// that use an adapter for bytes are not affected.
83    pub const fn bytes(mut self, format: BytesFormat) -> DeserializerConfig {
84        self.bytes = format;
85        self
86    }
87
88    /// Controls what may follow a value.
89    ///
90    /// By default ([`Trailing::Strict`]) only whitespace may follow the
91    /// value.  [`Trailing::Newline`] reads [JSON
92    /// Lines](https://jsonlines.org/) and [`Trailing::Stop`] stops after
93    /// the value without looking at what follows:
94    ///
95    /// ```
96    /// use deser_json::{DeserializerConfig, Trailing};
97    ///
98    /// assert!(
99    ///     deser_json::from_str::<Vec<u32>>("[1] trash")
100    ///         .is_err()
101    /// );
102    /// const STOP: DeserializerConfig =
103    ///     DeserializerConfig::new().trailing(Trailing::Stop);
104    /// assert_eq!(STOP.from_str::<Vec<u32>>("[1] trash").unwrap(), [1]);
105    /// ```
106    ///
107    /// With [`Trailing::Newline`] a [`Deserializer`] reads the lines one by
108    /// one.  Errors only discard their line:
109    ///
110    /// ```
111    /// use deser_json::{
112    ///     Deserializer, DeserializerConfig, Trailing,
113    /// };
114    ///
115    /// const LINES: DeserializerConfig =
116    ///     DeserializerConfig::new().trailing(Trailing::Newline);
117    /// let mut de =
118    ///     Deserializer::from_str_with_config("1\n\nnope\n3\n", &LINES);
119    /// let mut values = Vec::new();
120    /// while !de.is_end() {
121    ///     match de.deserialize::<u32>() {
122    ///         Ok(value) => values.push(value),
123    ///         Err(err) => assert_eq!(err.line(), Some(3)),
124    ///     }
125    /// }
126    /// assert_eq!(values, [1, 3]);
127    /// ```
128    pub const fn trailing(mut self, trailing: Trailing) -> DeserializerConfig {
129        self.trailing = trailing;
130        self
131    }
132
133    /// Returns what may follow a value.
134    pub(crate) fn trailing_mode(&self) -> Trailing {
135        self.trailing
136    }
137
138    /// Returns how strings are decoded into bytes.
139    pub(crate) fn bytes_format(&self) -> BytesFormat {
140        self.bytes
141    }
142
143    /// Returns `true` if exact numbers are enabled.
144    pub(crate) fn exact_numbers_enabled(&self) -> bool {
145        self.exact_numbers
146    }
147
148    /// Enables or disables location tracking.
149    ///
150    /// The byte range of every event is always published into the state
151    /// (see [`State::input_range`](deser_core::State::input_range)).  When
152    /// enabled additionally the input is set as source (see
153    /// [`Source`](deser_core::Source)) which allows resolving the
154    /// ranges into lines and columns, for instance with the `Spanned` type
155    /// of [`deser-location`](https://docs.rs/deser-location).  This copies
156    /// the input.
157    pub const fn track_locations(mut self, yes: bool) -> DeserializerConfig {
158        self.track_locations = yes;
159        self
160    }
161
162    /// Enables or disables exact numbers.
163    ///
164    /// When enabled (which is the default) floats which lose precision as
165    /// `f64` and integers that do not fit into 128 bits are emitted as
166    /// [`Number`](deser_core::ext::Number) extension values.  These carry the
167    /// text of the number together with its value as `f64`, which is what
168    /// types that do not know about exact numbers receive.  Types like
169    /// [`Decimal`](deser_core::ext::Decimal) (and the types of `rust_decimal` or
170    /// `bigdecimal`) use the text to deserialize the number exactly:
171    ///
172    /// ```
173    /// use deser::ext::Decimal;
174    ///
175    /// let value: Decimal =
176    ///     deser_json::from_str("0.10000000000000000001")
177    ///         .unwrap();
178    /// assert_eq!(value.as_str(), "0.10000000000000000001");
179    /// let value: f64 =
180    ///     deser_json::from_str("0.10000000000000000001")
181    ///         .unwrap();
182    /// assert_eq!(value, 0.1);
183    /// ```
184    ///
185    /// Floats whose text is the shortest representation of their value (as
186    /// formatted by `Debug`, for instance `0.5` or `3.14`) are emitted as
187    /// plain floats as the text can be recovered from the value.  This keeps
188    /// the common case fast.  When disabled, all floats are emitted as plain
189    /// floats.
190    pub const fn exact_numbers(mut self, yes: bool) -> DeserializerConfig {
191        self.exact_numbers = yes;
192        self
193    }
194
195    /// Deserializes JSON from the given string.
196    ///
197    /// What may follow the value depends on [`trailing`](Self::trailing).
198    /// With [`Trailing::Newline`] this reads the first line.
199    pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> {
200        deserialize_value(|make_sink| self.drive_str(s, make_sink))
201    }
202
203    /// The part of [`from_str`](Self::from_str) that does not depend on the type
204    /// of the value, it exists once.
205    fn drive_str<'de>(
206        &self,
207        s: &'de str,
208        make_sink: &mut MakeSink<'_, '_, 'de>,
209    ) -> Result<(), Error> {
210        drive_value(&mut Deserializer::from_str_with_config(s, self), make_sink)
211    }
212
213    /// Deserializes JSON from the given bytes.
214    ///
215    /// The input must be UTF-8.  Rather than validating the input upfront,
216    /// the strings are validated while parsing (see
217    /// [`Deserializer::from_slice`]).
218    pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> {
219        deserialize_value(|make_sink| self.drive_slice(bytes, make_sink))
220    }
221
222    /// The part of [`from_slice`](Self::from_slice) that does not depend on the type
223    /// of the value, it exists once.
224    fn drive_slice<'de>(
225        &self,
226        bytes: &'de [u8],
227        make_sink: &mut MakeSink<'_, '_, 'de>,
228    ) -> Result<(), Error> {
229        drive_value(
230            &mut Deserializer::from_slice_with_config(bytes, self),
231            make_sink,
232        )
233    }
234}
235
236/// Deserializes a serializable from JSON.
237///
238/// Every call to [`deserialize`](Self::deserialize) reads the next value.
239/// What may follow a value is controlled by
240/// [`DeserializerConfig::trailing`].  By default only whitespace may follow
241/// so there is only a single value.  With [`Trailing::Newline`] the
242/// deserializer reads [JSON Lines](https://jsonlines.org/):
243///
244/// ```
245/// use deser_json::{
246///     Deserializer, DeserializerConfig, Trailing,
247/// };
248///
249/// let config = DeserializerConfig::new().trailing(Trailing::Newline);
250/// let mut de =
251///     Deserializer::from_str_with_config("[1, 2]\n[3]\n", &config);
252/// assert_eq!(de.deserialize::<Vec<u32>>().unwrap(), [1, 2]);
253/// assert_eq!(de.deserialize::<Vec<u32>>().unwrap(), [3]);
254/// assert!(de.is_end());
255/// ```
256///
257/// To deserialize a single value, use [`from_str`](crate::from_str) and
258/// [`from_slice`](crate::from_slice) (or the methods of the same name on
259/// [`DeserializerConfig`]).  The deserializer is also useful to
260/// [`drive`](Self::drive) a custom sink.
261pub struct Deserializer<'a> {
262    input: &'a [u8],
263    pos: usize,
264    parser: Parser,
265    // `true` if the input is a byte slice which needs to be validated
266    validate_utf8: bool,
267    // `true` if a value failed and the stream cannot be continued
268    failed: bool,
269    // the input as source for location tracking, shared by all values
270    source: Option<Arc<str>>,
271    config: DeserializerConfig,
272}
273
274impl<'a> Deserializer<'a> {
275    /// Creates a new deserializer for a string.
276    #[allow(clippy::should_implement_trait)]
277    pub fn from_str(input: &'a str) -> Deserializer<'a> {
278        Deserializer::from_str_with_config(input, &DeserializerConfig::new())
279    }
280
281    /// Creates a new deserializer for a string with the given configuration.
282    pub fn from_str_with_config(input: &'a str, config: &DeserializerConfig) -> Deserializer<'a> {
283        Deserializer {
284            // the parser works on bytes but relies on the input being valid
285            // UTF-8 when it hands out string slices.
286            input: input.as_bytes(),
287            validate_utf8: false,
288            pos: 0,
289            parser: Parser::default(),
290            failed: false,
291            source: None,
292            config: config.clone(),
293        }
294    }
295
296    /// Creates a new deserializer for a byte slice.
297    ///
298    /// The input is not validated upfront.  Instead strings are validated as
299    /// UTF-8 when they are parsed (bytes outside of strings are only ever
300    /// accepted if they are ASCII).  Invalid UTF-8 is an error.
301    pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
302        Deserializer::from_slice_with_config(input, &DeserializerConfig::new())
303    }
304
305    /// Creates a new deserializer for a byte slice with the given
306    /// configuration.
307    ///
308    /// See [`from_slice`](Self::from_slice).
309    pub fn from_slice_with_config(
310        input: &'a [u8],
311        config: &DeserializerConfig,
312    ) -> Deserializer<'a> {
313        Deserializer {
314            input,
315            validate_utf8: true,
316            pos: 0,
317            parser: Parser::default(),
318            failed: false,
319            source: None,
320            config: config.clone(),
321        }
322    }
323
324    /// Creates a deserializer for the frame of a value in a stream.
325    ///
326    /// Only whitespace may follow the value in the frame.
327    pub(crate) fn from_frame(input: &'a [u8], config: &DeserializerConfig) -> Deserializer<'a> {
328        let mut de = Deserializer::from_slice_with_config(input, config);
329        de.config.trailing = Trailing::Strict;
330        de
331    }
332
333    /// Returns the configuration.
334    pub fn config(&self) -> &DeserializerConfig {
335        &self.config
336    }
337
338    /// Returns the current offset in the input.
339    pub fn offset(&self) -> usize {
340        self.pos
341    }
342
343    /// Returns `true` if there are no more values.
344    ///
345    /// This is the case if only whitespace is left or if a value failed and
346    /// the stream cannot be continued (see [`deserialize`](Self::deserialize)).
347    pub fn is_end(&self) -> bool {
348        self.failed || self.next_token() == self.input.len()
349    }
350
351    /// Fails if there is more than whitespace left.
352    ///
353    /// This is useful with [`Trailing::Stop`] to check that the input was
354    /// consumed.
355    pub fn end(&self) -> Result<(), Error> {
356        if self.is_end() {
357            return Ok(());
358        }
359        Err(Error::new(ErrorKind::Unexpected, "garbage after input")
360            .with_offset(self.next_token())
361            .resolve_position(self.input))
362    }
363
364    /// Returns where the next token starts (or the end of the input).
365    fn next_token(&self) -> usize {
366        let mut cursor = Cursor::new(self.input, self.pos);
367        cursor.parse_whitespace();
368        cursor.pos
369    }
370
371    /// Returns the input as string for the source.
372    fn source(&self) -> alloc::borrow::Cow<'a, str> {
373        if self.validate_utf8 {
374            // invalid UTF-8 fails the parsing when reached, the offsets of
375            // the tokens before it are not affected by the replacements.
376            String::from_utf8_lossy(self.input)
377        } else {
378            // SAFETY: the input was created from a string
379            alloc::borrow::Cow::Borrowed(unsafe { str::from_utf8_unchecked(self.input) })
380        }
381    }
382
383    /// Deserializes the next value.
384    ///
385    /// What may follow the value depends on
386    /// [`DeserializerConfig::trailing`].  Fails with
387    /// [`ErrorKind::EndOfFile`] if there are no more values.
388    ///
389    /// If a value fails to deserialize (because it's malformed or does not
390    /// match the type), the stream ends: [`is_end`](Self::is_end) returns
391    /// `true` and further calls fail.  With [`Trailing::Newline`] only the
392    /// rest of the line is skipped and the next call continues with the
393    /// next line.
394    ///
395    /// To configure the deserialization (for instance to add layers) use
396    /// [`deserialize_with`](Self::deserialize_with).
397    pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
398        de::Deserializer::deserialize(self)
399    }
400
401    /// Deserializes the next value with a configured driver.
402    ///
403    /// The callback is invoked with the driver before the value is
404    /// deserialized, for instance to add [`Layer`](deser_core::de::Layer)s.
405    pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
406    where
407        T: Deserialize<'a>,
408        F: FnOnce(&mut DeserializeDriver<'_, 'a>),
409    {
410        de::Deserializer::deserialize_with(self, setup)
411    }
412
413    /// Returns an iterator over the remaining values.
414    ///
415    /// This is useful to read JSON Lines (see [`Trailing::Newline`]).  The
416    /// iterator stops after the first error.
417    ///
418    /// ```
419    /// use deser_json::{
420    ///     Deserializer, DeserializerConfig, Trailing,
421    /// };
422    ///
423    /// let config = DeserializerConfig::new().trailing(Trailing::Newline);
424    /// let mut de = Deserializer::from_str_with_config("1\n2\n3\n", &config);
425    /// let items = de.iter::<u32>().collect::<Result<Vec<_>, _>>().unwrap();
426    /// assert_eq!(items, [1, 2, 3]);
427    /// ```
428    pub fn iter<T: Deserialize<'a>>(&mut self) -> Iter<'_, 'a, T> {
429        Iter {
430            de: self,
431            failed: false,
432            _marker: PhantomData,
433        }
434    }
435
436    /// Parses the next value and feeds the events into the given driver.
437    ///
438    /// This is useful to deserialize into a custom [`Sink`](deser_core::de::Sink).
439    /// See also [`deserialize_with`](Self::deserialize_with).
440    ///
441    /// Strings without escape sequences are passed on borrowed from the
442    /// input (see [`emit_borrowed`](DeserializeDriver::emit_borrowed)).
443    /// Errors carry the location in the input (see [`Error::line`]).
444    pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
445        if self.failed {
446            return Err(Error::new(
447                ErrorKind::Unexpected,
448                "cannot continue after an error",
449            ));
450        }
451        if self.config.track_locations {
452            let source = match self.source {
453                Some(ref source) => source.clone(),
454                None => {
455                    let source: Arc<str> = self.source().into();
456                    self.source = Some(source.clone());
457                    source
458                }
459            };
460            Source::set(driver.state_mut(), source);
461        }
462        if self.config.bytes != BytesFormat::BASE64 {
463            self.config.bytes.set(driver.state_mut());
464        }
465
466        // for JSON Lines the input is cut off at the end of the line.  The
467        // parser then fails if the value does not end on the line.
468        let input = self.input;
469        let line_end = if self.config.trailing == Trailing::Newline {
470            self.skip_whitespace();
471            let end = input[self.pos..]
472                .iter()
473                .position(|&b| b == b'\n')
474                .map_or(input.len(), |idx| self.pos + idx);
475            self.input = &input[..end];
476            Some(end)
477        } else {
478            None
479        };
480
481        let rv = self.drive_impl(driver);
482        self.input = input;
483
484        let rv = rv.map_err(|err| self.locate_error(err));
485        match line_end {
486            // the rest of the line is skipped, even after errors
487            Some(end) => self.pos = end,
488            // after an error the position within the value is unknown
489            None => self.failed = rv.is_err() && !self.is_end(),
490        }
491        rv
492    }
493
494    /// Attaches the location to an error.
495    #[cold]
496    fn locate_error(&self, err: Error) -> Error {
497        // errors of the parser are located at the current position, errors
498        // of the sinks at the event that failed
499        let err = match err.offset() {
500            Some(_) => err,
501            None => err.with_offset(self.pos),
502        };
503        err.resolve_position(self.input)
504    }
505
506    fn drive_impl(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
507        let options = Options {
508            validate_utf8: self.validate_utf8,
509            exact_numbers: self.config.exact_numbers,
510        };
511        let mut out = Borrowing(driver);
512        match self
513            .parser
514            .parse(self.input, self.pos, true, 0, options, &mut out)
515        {
516            Ok(Progress::Done(pos)) => {
517                self.pos = pos;
518                self.finish_value()
519            }
520            Ok(Progress::NeedMore(_)) => unreachable!("the input is complete"),
521            Err(err) => {
522                self.parser.reset();
523                Err(err)
524            }
525        }
526    }
527
528    /// Skips whitespace.
529    fn skip_whitespace(&mut self) {
530        self.pos = self.next_token();
531    }
532
533    /// Checks what follows a complete value.
534    #[inline]
535    fn finish_value(&mut self) -> Result<(), Error> {
536        let msg = match self.config.trailing {
537            Trailing::Strict => "garbage after input",
538            // the input was cut off at the end of the line
539            Trailing::Newline => "expected end of line after value",
540            Trailing::Stop => return Ok(()),
541        };
542        self.skip_whitespace();
543        if self.pos < self.input.len() {
544            return Err(Error::new(ErrorKind::Unexpected, msg));
545        }
546        Ok(())
547    }
548}
549
550/// An iterator over the values of a JSON stream.
551///
552/// See [`Deserializer::iter`].
553pub struct Iter<'b, 'a, T> {
554    de: &'b mut Deserializer<'a>,
555    failed: bool,
556    _marker: PhantomData<fn() -> T>,
557}
558
559impl<'b, 'a, T: Deserialize<'a>> Iterator for Iter<'b, 'a, T> {
560    type Item = Result<T, Error>;
561
562    fn next(&mut self) -> Option<Self::Item> {
563        if self.failed || self.de.is_end() {
564            return None;
565        }
566        let rv = self.de.deserialize();
567        self.failed = rv.is_err();
568        Some(rv)
569    }
570}
571
572impl<'a> de::Deserializer<'a> for Deserializer<'a> {
573    fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
574        Deserializer::drive(self, driver)
575    }
576}
577
578/// Deserializes JSON from the given string.
579///
580/// The input must contain exactly one value, only whitespace may follow it.
581/// To read multiple values (for instance JSON Lines) use a [`Deserializer`]
582/// with [`Trailing::Newline`].  This uses the default
583/// [`DeserializerConfig`].
584pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
585    DeserializerConfig::new().from_str(s)
586}
587
588/// Deserializes JSON from the given bytes.
589///
590/// The input must be UTF-8.  Rather than validating the input upfront, the
591/// strings are validated while parsing (see [`Deserializer::from_slice`]).
592/// This uses the default [`DeserializerConfig`].
593pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Error> {
594    DeserializerConfig::new().from_slice(bytes)
595}