Skip to main content

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