deser_incomplete/
options_impl.rs

1use std::borrow::Cow;
2use std::marker::PhantomData;
3#[cfg(feature = "rand")]
4use std::sync::Arc;
5
6use serde::de::DeserializeSeed;
7#[cfg(doc)]
8use serde::de::{Deserializer, EnumAccess, MapAccess, Visitor};
9use serde::Deserialize;
10
11pub use crate::error::Error;
12use crate::error::InternalError;
13use crate::fallback::{DefaultFallbacks, Fallbacks};
14pub use crate::random_trailer::RandomTrailer;
15use crate::random_trailer::{InputPlusTrailer, NoopRandomTrailer, StringLike};
16use crate::state::AttemptState;
17use crate::unstable::{DefaultReporter, ExtraOptionsIsUnstable};
18use crate::Source;
19
20/// Number of times that we may backtrack.
21///
22/// For good results, you should allow at least one backtracking for when the input
23/// stops in the middle of a map/struct value or enum.
24///
25/// A higher limit on backtracks is useful when not all struct fields
26/// are declared `#[serde(default)]`. In this case, the algorithm will attempt to
27/// incrementally prune on higher levels, e.g. omitting the list item that contains
28/// the end-of-file, or omitting a field of an enclosing struct.
29const DEFAULT_MAX_BACKTRACKS: Option<usize> = Some(10);
30
31#[cfg(feature = "rand")]
32const RANDOM_TAG_LEN: usize = 8;
33
34/// Options for deserialization.
35///
36/// The most important methods are:
37///
38/// - [`Options::deserialize_from_json_str`] for JSON,
39/// - [`Options::deserialize_from_yaml_str`] for YAML,
40/// - [`Options::deserialize_source`] for a generic source.
41#[derive(Clone, Debug)]
42pub struct Options<Extra: ExtraOptions = DefaultExtraOptions> {
43    /// This is a random string that forms part of a suffix we add to
44    /// the input, for some data types.
45    ///
46    /// As of Dec 2024, we don't stabilize the specific string format.
47    #[cfg(feature = "rand")]
48    random_tag: Option<Arc<str>>,
49
50    pub(crate) max_n_backtracks: Option<usize>,
51
52    pub(crate) behavior: UnstableCustomBehavior,
53
54    pub(crate) extra: Extra,
55}
56
57impl Options {
58    /// Default config for JSON.
59    ///
60    /// This will currently generate a short extra trailer on inputs
61    /// for improved deserialization of incomplete JSON.
62    #[cfg(all(feature = "rand", feature = "serde_json"))]
63    pub fn new_json() -> Options<JsonExtraOptions> {
64        let base = Options {
65            ..Options::new_nonce()
66        };
67        base.set_random_trailer(crate::random_trailer::json::JsonRandomTrailer)
68    }
69
70    /// Default config for YAML.
71    ///
72    /// This will currently generate a short extra trailer on inputs
73    /// for improved deserialization of incomplete YAML.
74    ///
75    /// For YAML in particular, this suffix is important to get
76    /// good behavior.
77    #[cfg(all(feature = "rand", feature = "serde_yaml"))]
78    pub fn new_yaml() -> Options<YamlExtraOptions> {
79        let base = Options {
80            ..Options::new_nonce()
81        };
82        base.set_random_trailer(crate::random_trailer::yaml::YamlRandomTrailer)
83    }
84
85    /// Basic config, suitable for any data format.
86    ///
87    /// These options support adding a randomized trailer to the input.
88    /// However, you should probably call [`Options::set_random_trailer`]
89    /// to specify how this trailer should be removed from parsed strings.
90    #[cfg(feature = "rand")]
91    pub fn new_nonce() -> Options<DefaultExtraOptions> {
92        use rand::distributions::{Alphanumeric, DistString};
93        use rand::thread_rng;
94
95        // In the future, this may change to only generate a single random
96        // tag for the lifetime of the application.
97        let tag = Alphanumeric.sample_string(&mut thread_rng(), RANDOM_TAG_LEN);
98        Options {
99            random_tag: Some(tag.into()),
100            ..Options::new_no_nonce()
101        }
102    }
103
104    /// Basic config, suitable for any data format. However, this
105    /// config does not allow adding a randomized trailer to the input,
106    /// which tends to benefit many formats.
107    ///
108    /// - For `serde_json`, this means you won't get incomplete strings deserialized
109    ///
110    /// - For `serde_yaml`, this means that your output will flicker, as it seems to
111    ///   buffer lines somehow, and if a line has an unterminated string, then the
112    ///   whole line will be missing.
113    pub fn new_no_nonce() -> Options<DefaultExtraOptions> {
114        Options {
115            #[cfg(feature = "rand")]
116            random_tag: None,
117            max_n_backtracks: DEFAULT_MAX_BACKTRACKS,
118            behavior: UnstableCustomBehavior::default(),
119            extra: DefaultExtraOptions::default(),
120        }
121    }
122}
123
124impl<Extra: ExtraOptions> Options<Extra> {
125    pub fn with_max_n_backtracks(mut self, max_n_backtracks: Option<usize>) -> Self {
126        self.max_n_backtracks = max_n_backtracks;
127        self
128    }
129
130    /// Like [`crate::from_json_str`], but with options. This applies the random trailer.
131    #[cfg(all(feature = "rand", feature = "serde_json"))]
132    pub fn deserialize_from_json_str<T>(self, json: Cow<str>) -> Result<T, Error<serde_json::Error>>
133    where
134        T: for<'de> serde::de::Deserialize<'de>,
135    {
136        let prepared = self.prepare_str_for_borrowed_deserialization(json);
137        self.deserialize_from_json_str_borrowed(&prepared)
138    }
139
140    /// Like [`crate::from_json_slice`], but with options. This applies the random trailer.
141    #[cfg(all(feature = "rand", feature = "serde_json"))]
142    pub fn deserialize_from_json_slice<T>(
143        self,
144        json: Cow<[u8]>,
145    ) -> Result<T, Error<serde_json::Error>>
146    where
147        T: for<'de> serde::de::Deserialize<'de>,
148    {
149        let prepared = self.prepare_slice_for_borrowed_deserialization(json);
150        self.deserialize_from_json_slice_borrowed(&prepared)
151    }
152
153    /// Like [`crate::from_yaml_str`], but with options. This applies the random trailer.
154    #[cfg(all(feature = "rand", feature = "serde_yaml"))]
155    pub fn deserialize_from_yaml_str<T>(self, yaml: Cow<str>) -> Result<T, Error<serde_yaml::Error>>
156    where
157        T: for<'de> serde::de::Deserialize<'de>,
158    {
159        let prepared = self.prepare_str_for_borrowed_deserialization(yaml);
160        self.deserialize_from_yaml_str_borrowed(&prepared)
161    }
162
163    /// Like [`crate::from_yaml_slice`], but with options. This applies the random trailer.
164    #[cfg(all(feature = "rand", feature = "serde_yaml"))]
165    pub fn deserialize_from_yaml_slice<T>(
166        self,
167        yaml: Cow<[u8]>,
168    ) -> Result<T, Error<serde_yaml::Error>>
169    where
170        T: for<'de> serde::de::Deserialize<'de>,
171    {
172        let prepared = self.prepare_slice_for_borrowed_deserialization(yaml);
173        self.deserialize_from_yaml_slice_borrowed(&prepared)
174    }
175
176    /// Like [`Self::deserialize_from_json_slice`], but can deserialize borrowed strings and return them
177    /// directly.
178    ///
179    /// This comes at the cost that we cannot use the random trailer technique that gives
180    /// us access to the contents of incomplete strings.
181    ///
182    /// If you need incomplete strings as well, then use [`Self::deserialize_from_json_slice_borrowed`].
183    ///
184    /// ```
185    /// # use serde::Deserialize;
186    /// #[derive(Debug, Deserialize, PartialEq)]
187    /// struct TravelMode {
188    ///    #[serde(default)]
189    ///    mode: String,
190    ///    benefit: Option<String>
191    /// }
192    ///
193    /// let json = r#"[{"mode": "foot", "benefit": "healthy"}, {"mode": "incomplete"#;
194    /// let modes: Vec<TravelMode> = deser_incomplete::Options::new_json().deserialize_from_json_slice_plain_return_borrowed(&json).unwrap();
195    /// assert_eq!(modes, [
196    ///    TravelMode { mode: "foot".to_string(), benefit: Some("healthy".to_string()) },
197    ///    TravelMode { mode: "".to_string(), benefit: None },
198    ///    // Note: this function fails on incomplete strings, because
199    ///    // the randomized trailer is needed for those.
200    /// ]);
201    /// ```
202    #[cfg(feature = "serde_json")]
203    pub fn deserialize_from_json_slice_plain_return_borrowed<'de, T>(
204        self,
205        json: &'de impl AsRef<[u8]>,
206    ) -> Result<T, Error<serde_json::Error>>
207    where
208        T: serde::de::Deserialize<'de>,
209    {
210        self.deserialize_source(crate::source::JsonBytes(json.as_ref()))
211    }
212
213    /// Advanced API. Lets you deserialize into borrowed types like `&str`, while supporting
214    /// the random trailer that gives us access to the contents of incomplete strings.
215    ///
216    /// (The difference is that this only needs `T: serde::de::Deserialize<'de>`, which is weaker.)
217    ///
218    /// **Note: This API is relatively likely to change (more unstable) compared to [`Self::deserialize_from_json_str`].**
219    ///
220    /// ```
221    /// # use serde::Deserialize;
222    /// /// Note: `&'a str` instead of `String`.
223    /// ///
224    /// /// Like with serde_json, deserializing to &str can fail. Instead, you should probably
225    /// /// use `Cow<str>`, or just `String`.
226    /// #[derive(Debug, Deserialize, PartialEq)]
227    /// struct TravelMode<'a> {
228    ///    mode: &'a str,
229    ///    benefit: Option<&'a str>
230    /// }
231    ///
232    /// let json = r#"[{"mode": "foot", "benefit": "healthy"}, {"mode": "aeropl"#;
233    /// let options = deser_incomplete::Options::new_json();
234    /// let prepared = options.prepare_str_for_borrowed_deserialization(json.into());
235    /// let modes: Vec<TravelMode> = options.deserialize_from_json_str_borrowed(&prepared).unwrap();
236    /// assert_eq!(modes, [
237    ///    TravelMode { mode: "foot", benefit: Some("healthy") },
238    ///    TravelMode { mode: "aeropl", benefit: None }
239    /// ]);
240    /// ```
241    #[cfg(feature = "serde_json")]
242    pub fn deserialize_from_json_str_borrowed<'de, T>(
243        self,
244        InputPlusTrailer(prepared_json): &'de InputPlusTrailer<impl AsRef<str>>,
245    ) -> Result<T, Error<serde_json::Error>>
246    where
247        T: serde::de::Deserialize<'de>,
248    {
249        self.deserialize_source(crate::source::JsonStr(prepared_json.as_ref()))
250    }
251
252    /// Advanced API. See [`Self::deserialize_from_json_str_borrowed`], or
253    /// use [`Self::deserialize_from_json_slice`] for a simpler API.
254    ///
255    /// **Note: This API is relatively likely to change (more unstable) compared to [`Self::deserialize_from_json_slice`].**
256    #[cfg(feature = "serde_json")]
257    pub fn deserialize_from_json_slice_borrowed<'de, T>(
258        self,
259        InputPlusTrailer(prepared_json): &'de InputPlusTrailer<impl AsRef<[u8]>>,
260    ) -> Result<T, Error<serde_json::Error>>
261    where
262        T: serde::de::Deserialize<'de>,
263    {
264        self.deserialize_source(crate::source::JsonBytes(prepared_json.as_ref()))
265    }
266
267    /// Advanced API. See [`Self::deserialize_from_json_str_borrowed`], or
268    /// use [`Self::deserialize_from_yaml_str`] for a simpler API.
269    #[cfg(feature = "serde_yaml")]
270    pub fn deserialize_from_yaml_str_borrowed<'de, T>(
271        self,
272        InputPlusTrailer(prepared_yaml): &'de InputPlusTrailer<impl AsRef<str>>,
273    ) -> Result<T, Error<serde_yaml::Error>>
274    where
275        T: serde::de::Deserialize<'de>,
276    {
277        self.deserialize_source(crate::source::YamlStr(prepared_yaml.as_ref()))
278    }
279
280    /// Advanced API. See [`Self::deserialize_from_json_str_borrowed`], or
281    /// use [`Self::deserialize_from_yaml_slice`] for a simpler API.
282    #[cfg(feature = "serde_yaml")]
283    pub fn deserialize_from_yaml_slice_borrowed<'de, T>(
284        self,
285        InputPlusTrailer(prepared_yaml): &'de InputPlusTrailer<impl AsRef<[u8]>>,
286    ) -> Result<T, Error<serde_yaml::Error>>
287    where
288        T: serde::de::Deserialize<'de>,
289    {
290        self.deserialize_source(crate::source::YamlBytes(prepared_yaml.as_ref()))
291    }
292
293    /// Prepare a string for borrowed deserialization with a method
294    /// like [`Self::deserialize_from_json_str_borrowed`], by appending the random trailer.
295    ///
296    /// This returns a newtype wrapper, so you can undo the effects yourself.
297    #[cfg(feature = "rand")]
298    pub fn prepare_str_for_borrowed_deserialization<'a>(
299        &self,
300        mut input: Cow<'a, str>,
301    ) -> InputPlusTrailer<Cow<'a, str>> {
302        use RandomTrailer as _;
303
304        #[cfg(feature = "rand")]
305        if let Some(tag) = self.random_tag.as_ref() {
306            self.extra
307                .get_random_trailer()
308                .prepare_string_with_tag(Cow::to_mut(&mut input), tag);
309        }
310        InputPlusTrailer(input)
311    }
312
313    /// Prepare a slice for borrowed deserialization with a method
314    /// like [`Self::deserialize_from_json_slice_borrowed`], by appending the random trailer.
315    ///
316    /// This returns a newtype wrapper, so you can undo the effects yourself.
317    #[cfg(feature = "rand")]
318    pub fn prepare_slice_for_borrowed_deserialization<'a>(
319        &self,
320        mut input: Cow<'a, [u8]>,
321    ) -> InputPlusTrailer<Cow<'a, [u8]>> {
322        use RandomTrailer as _;
323
324        #[cfg(feature = "rand")]
325        if let Some(tag) = self.random_tag.as_ref() {
326            self.extra
327                .get_random_trailer()
328                .prepare_vec_with_tag(Cow::to_mut(&mut input), tag);
329        }
330        InputPlusTrailer(input)
331    }
332
333    /// Customize internal behavior.
334    ///
335    /// This is meant for data formats where the defaults may not work well, but
336    /// it's unclear if such customization helps anywhere.
337    ///
338    /// ## Example
339    ///
340    /// ```
341    /// # use deser_incomplete::Options;
342    ///
343    /// let mut behavior : deser_incomplete::unstable::UnstableCustomBehavior
344    ///     = Default::default();
345    /// behavior.fallback_any_as_none = true;
346    ///
347    /// let result =
348    ///     Options::new_json()
349    ///     .custom_behavior(behavior)
350    ///     .deserialize_from_json_str::<serde_json::Value>("".into());
351    ///
352    /// assert_eq!(result.unwrap(), serde_json::Value::Null);
353    ///
354    /// // Normally, this would be Err.
355    /// assert_eq!(
356    ///     deser_incomplete::from_json_str::<serde_json::Value>("").unwrap_err().to_string(),
357    ///     "could not find a potential backtrack point (do you have #[serde(default)] on your top-level type? are your settings too strict?) (after 0 backtracks)");
358    /// ```
359    #[cfg(feature = "unstable")]
360    pub fn custom_behavior(self, behavior: UnstableCustomBehavior) -> Self {
361        Options { behavior, ..self }
362    }
363
364    /// Don't use a random tag. This can make deserialization a tiny bit cheaper,
365    /// because the input does not have to be reallocated.
366    #[cfg(feature = "rand")]
367    pub fn disable_random_tag(mut self) -> Self {
368        self.random_tag = None;
369        self
370    }
371}
372
373#[cfg(feature = "rand")]
374impl<R, F, RT> Options<ExtraOptionsStruct<R, F, RT>>
375where
376    R: MakeReporter,
377    F: MakeFallbackProvider,
378    RT: RandomTrailer,
379{
380    /// Set a different method for randomized trailers.
381    pub fn set_random_trailer<RT2>(
382        self,
383        random_trailer: RT2,
384    ) -> Options<ExtraOptionsStruct<R, F, RT2>>
385    where
386        RT2: RandomTrailer,
387    {
388        let Options {
389            random_tag,
390            max_n_backtracks,
391            behavior,
392            extra,
393        } = self;
394
395        Options {
396            random_tag,
397            max_n_backtracks,
398            behavior,
399            extra: ExtraOptionsStruct {
400                make_reporter: extra.make_reporter,
401                make_fallback_provider: extra.make_fallback_provider,
402                random_trailer,
403            },
404        }
405    }
406
407    /// Set a way to report progress internally. (The default reporter logs on [`tracing`].)
408    ///
409    /// ## Example
410    ///
411    /// ```
412    /// # use deser_incomplete::Options;
413    ///
414    /// let x =
415    ///     Options::new_json()
416    ///     .set_reporter(deser_incomplete::unstable::DefaultReporter::new())
417    ///     .deserialize_from_json_str::<i32>("3".into())
418    ///     .unwrap();
419    ///
420    /// assert_eq!(x, 3);
421    /// ```
422    #[cfg(feature = "unstable")]
423    pub fn set_reporter<R2>(
424        self,
425        reporter: R2,
426    ) -> Options<ExtraOptionsStruct<CustomReporter<R2>, F, RT>>
427    where
428        R2: crate::reporter::Reporter + Clone,
429    {
430        let Options {
431            random_tag,
432            max_n_backtracks,
433            behavior,
434            extra,
435        } = self;
436
437        Options {
438            random_tag,
439            max_n_backtracks,
440            behavior,
441            extra: ExtraOptionsStruct {
442                make_reporter: CustomReporter(reporter),
443                make_fallback_provider: extra.make_fallback_provider,
444                random_trailer: extra.random_trailer,
445            },
446        }
447    }
448
449    /// Set a way to provide fallback values. (The default fallback provider
450    /// has tuned defaults that should be reasonable for many data formats,
451    /// and they are good for JSON and YAML.)
452    #[doc(hidden)]
453    #[cfg(feature = "unstable")]
454    pub fn set_fallback_provider<F2>(
455        self,
456        fallback_provider: F2,
457    ) -> Options<ExtraOptionsStruct<R, CustomFallbackProvider<F2>, RT>>
458    where
459        F2: Fallbacks + Clone,
460    {
461        let Options {
462            random_tag,
463            max_n_backtracks,
464            behavior,
465            extra,
466        } = self;
467
468        Options {
469            random_tag,
470            max_n_backtracks,
471            behavior,
472            extra: ExtraOptionsStruct {
473                make_reporter: extra.make_reporter,
474                make_fallback_provider: CustomFallbackProvider(fallback_provider),
475                random_trailer: extra.random_trailer,
476            },
477        }
478    }
479}
480
481impl<Extra: ExtraOptions> Options<Extra> {
482    /// Do our best to take off any potential junk that was only added by us,
483    /// caused by the random trailer.
484    ///
485    /// Return true if the input was modified and this value seems to be incomplete.
486    #[must_use]
487    pub(crate) fn remove_tag_from_stringlike(&self, stringy: &mut impl StringLike) -> bool {
488        #![cfg_attr(not(feature = "rand"), allow(unused_variables))]
489
490        #[cfg(feature = "rand")]
491        {
492            if let Some(tag) = self.random_tag.as_ref() {
493                return self.extra.get_random_trailer().remove_trailer(stringy, tag);
494            }
495        }
496
497        false
498    }
499}
500
501/// Monomorphized options.
502///
503/// This is a parameter pack for type parameters.
504///
505/// All of this is unstable.
506#[doc(hidden)]
507#[allow(private_bounds)]
508pub trait ExtraOptions: ExtraOptionsIsUnstable {
509    /// Will only be called once per invocation of a public function in this crate
510    fn make_reporter(&mut self) -> Self::Reporter;
511    type Reporter: crate::reporter::Reporter;
512
513    /// Will only be called once per invocation of a public function in this crate
514    fn make_fallback_provider(
515        &mut self,
516        behavior: &UnstableCustomBehavior,
517    ) -> Self::FallbackProvider;
518    type FallbackProvider: Fallbacks;
519
520    fn get_random_trailer(&self) -> &Self::RandomTrailer;
521    type RandomTrailer: RandomTrailer;
522}
523
524pub type DefaultExtraOptions =
525    ExtraOptionsStruct<MakeDefaultReporter, MakeDefaultFallbacks, NoopRandomTrailer>;
526#[cfg(all(feature = "rand", feature = "serde_json"))]
527pub type JsonExtraOptions = ExtraOptionsStruct<
528    MakeDefaultReporter,
529    MakeDefaultFallbacks,
530    crate::random_trailer::json::JsonRandomTrailer,
531>;
532#[cfg(all(feature = "rand", feature = "serde_yaml"))]
533pub type YamlExtraOptions = ExtraOptionsStruct<
534    MakeDefaultReporter,
535    MakeDefaultFallbacks,
536    crate::random_trailer::yaml::YamlRandomTrailer,
537>;
538
539#[doc(hidden)]
540#[derive(Debug, Clone, Default)]
541pub struct ExtraOptionsStruct<MakeReporter, MakeFallbackProvider, RandomTrailer> {
542    pub(crate) make_reporter: MakeReporter,
543    pub(crate) make_fallback_provider: MakeFallbackProvider,
544    pub(crate) random_trailer: RandomTrailer,
545}
546
547#[doc(hidden)]
548pub trait MakeReporter {
549    type Reporter: crate::reporter::Reporter;
550    fn make_reporter(&mut self) -> Self::Reporter;
551}
552#[doc(hidden)]
553pub trait MakeFallbackProvider {
554    type FallbackProvider: Fallbacks;
555    fn make_fallback_provider(
556        &mut self,
557        behavior: &UnstableCustomBehavior,
558    ) -> Self::FallbackProvider;
559}
560
561#[doc(hidden)]
562#[derive(Debug, Clone, Default)]
563pub struct MakeDefaultReporter;
564impl MakeReporter for MakeDefaultReporter {
565    type Reporter = DefaultReporter;
566    fn make_reporter(&mut self) -> Self::Reporter {
567        DefaultReporter::new()
568    }
569}
570#[doc(hidden)]
571#[derive(Debug, Clone, Default)]
572pub struct MakeDefaultFallbacks;
573impl MakeFallbackProvider for MakeDefaultFallbacks {
574    type FallbackProvider = DefaultFallbacks;
575    fn make_fallback_provider(
576        &mut self,
577        behavior: &UnstableCustomBehavior,
578    ) -> Self::FallbackProvider {
579        DefaultFallbacks {
580            behavior: behavior.clone(),
581        }
582    }
583}
584
585#[derive(Debug, Clone)]
586pub struct CustomReporter<T>(T);
587impl<T: crate::reporter::Reporter + Clone> MakeReporter for CustomReporter<T> {
588    type Reporter = T;
589    fn make_reporter(&mut self) -> Self::Reporter {
590        self.0.clone()
591    }
592}
593
594#[derive(Debug, Clone)]
595pub struct CustomFallbackProvider<T>(T);
596impl<T: Fallbacks + Clone> MakeFallbackProvider for CustomFallbackProvider<T> {
597    type FallbackProvider = T;
598    fn make_fallback_provider(
599        &mut self,
600        _behavior: &UnstableCustomBehavior,
601    ) -> Self::FallbackProvider {
602        self.0.clone()
603    }
604}
605
606impl<R, F, RT> ExtraOptions for ExtraOptionsStruct<R, F, RT>
607where
608    R: MakeReporter,
609    F: MakeFallbackProvider,
610    RT: RandomTrailer,
611{
612    fn make_reporter(&mut self) -> Self::Reporter {
613        self.make_reporter.make_reporter()
614    }
615    type Reporter = R::Reporter;
616
617    fn make_fallback_provider(
618        &mut self,
619        behavior: &UnstableCustomBehavior,
620    ) -> Self::FallbackProvider {
621        self.make_fallback_provider.make_fallback_provider(behavior)
622    }
623    type FallbackProvider = F::FallbackProvider;
624
625    fn get_random_trailer(&self) -> &RT {
626        &self.random_trailer
627    }
628    type RandomTrailer = RT;
629}
630
631impl<R, F, RT> ExtraOptionsIsUnstable for ExtraOptionsStruct<R, F, RT> {}
632
633/// Customize behavior.
634///
635/// This both controls
636///
637///   - when deserializer encounters end-of-input, but we still have
638///     a chance to fill in the value and succeed deserialization, then
639///     we can make an educated guess based on what the data type expected
640///     (which method of [`crate::Deserializer`] was called).
641///
642///     For instance, when deserializing an option, JSON `fa` will choose the
643///     `Some` case, the deserializer will error, but can save deserialization
644///     and fill in `none`.
645///
646///   - which points are eligible for backtracking, e.g. is it okay to retry
647///     but omit a list item, a map item, or convert `Some` into `None`.
648///
649/// The default is an educated guess that should make many data types deserialize
650/// successfully on the first backtrack, without trying to apply too many
651/// fallbacks: incomplete list items are skipped, but no fallback numbers are
652/// filled in.
653///
654/// ## Limitations
655///
656/// Consider that fallback values are not a good substitute for `#[serde(default)]`:
657///
658/// ```
659/// struct Point {
660///     // note: missing #[serde(default)]
661///     x: i32,
662///     // note: missing #[serde(default)]
663///     y: i32,
664/// }
665/// ```
666///
667/// We could put a fallback of `0` for integers, and that will make `{"x": 1, "y":` parse successfully,
668/// but `{"x": 1` will still not parse because all `Point`s require a value for `y`.
669///
670/// ## Stability
671///
672/// This interface is not subject to semver (as it is unstable), and may change
673/// or be removed at any time.
674#[derive(Debug, Clone)]
675#[non_exhaustive]
676pub struct UnstableCustomBehavior {
677    /// If the visitor returns Ok but the deserializer returns an error, then return
678    /// the visitor's value.
679    pub tolerate_deserializer_fail_after_visit_success: bool,
680    pub fallback_any_as_none: bool,
681    pub fallback_ignored_any_as_none: bool,
682    pub fallback_default_bool: Option<bool>,
683    pub fallback_int_zero: bool,
684    pub fallback_default_float: Option<f32>,
685    pub fallback_default_char: Option<char>,
686    pub fallback_default_str: Option<&'static str>,
687    pub fallback_bytes_empty: bool,
688    /// In case [`Deserializer::deserialize_option`] does not do anything, then
689    /// just go in and visit a None.
690    pub fallback_none: bool,
691    pub fallback_none_at_mandatory: bool,
692    /// In case [`Deserializer::deserialize_unit`] does not do anything, then
693    /// just go in and visit a unit.
694    ///
695    /// ## Caveat
696    ///
697    /// Especially with a random trailer, this can sometimes generate spurious
698    /// list elements.
699    pub fallback_unit: bool,
700    pub fallback_unit_at_mandatory: bool,
701
702    /// In case [`Deserializer::deserialize_unit_struct`] does not do anything, then
703    /// just go in and visit a unit struct.
704    ///
705    /// ## Caveat
706    ///
707    /// Especially with a random trailer, this can sometimes generate spurious
708    /// list elements.
709    pub fallback_unit_struct: bool,
710    pub fallback_unit_struct_at_mandatory: bool,
711
712    pub fallback_seq_empty: bool,
713    pub fallback_seq_empty_at_root: bool,
714    pub backtrack_seq_empty_for_value: bool,
715    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
716    /// point that is better.
717    pub fallback_seq_skip_item: bool,
718    pub backtrack_seq_skip_item: bool,
719    pub fallback_tuple_empty: bool,
720    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
721    /// point that is better.
722    pub fallback_tuple_skip_item: bool,
723    pub backtrack_tuple_skip_item: bool,
724    pub fallback_tuple_struct_empty: bool,
725    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
726    /// point that is better.
727    pub fallback_tuple_struct_skip_item: bool,
728    pub backtrack_tuple_struct_skip_item: bool,
729    pub fallback_map_empty: bool,
730    pub fallback_map_empty_at_root: bool,
731    pub backtrack_map_empty_for_value: bool,
732    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
733    /// point that is better.
734    pub fallback_map_skip_item: bool,
735    pub backtrack_map_skip_item: bool,
736    pub fallback_struct_empty: bool,
737    pub fallback_struct_empty_at_root: bool,
738    pub backtrack_struct_empty_for_value: bool,
739    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
740    /// point that is better.
741    pub fallback_struct_skip_field: bool,
742    pub backtrack_struct_skip_field: bool,
743    pub fallback_unit_variant: bool,
744
745    /// Whether it's okay to fallback to skipping an element or field in circumstances
746    /// other than [`Deserializer::deserialize_seq`] or [`Deserializer::deserialize_tuple`].
747    ///
748    /// `fallback_*_skip_item` are probably a bad idea, because they can mask a backtracking
749    /// point that is better.
750    pub fallback_other_skip_item: bool,
751    pub backtrack_other_skip_item: bool,
752
753    /// Whether incomplete strings should be allowed or rejected
754    /// in [`MapAccess::next_key`] or [`EnumAccess::variant`].
755    pub allow_incomplete_string_in_key_or_variant: bool,
756}
757
758impl Default for UnstableCustomBehavior {
759    fn default() -> Self {
760        Self {
761            tolerate_deserializer_fail_after_visit_success: true,
762            fallback_any_as_none: false,
763            fallback_ignored_any_as_none: false,
764            fallback_default_bool: None,
765            fallback_int_zero: false,
766            fallback_default_float: None,
767            fallback_default_char: None,
768            fallback_default_str: None,
769            fallback_bytes_empty: false,
770            fallback_none: true,
771            fallback_none_at_mandatory: true,
772            fallback_unit: false,
773            fallback_unit_at_mandatory: true,
774            fallback_unit_struct: false,
775            fallback_unit_struct_at_mandatory: true,
776            fallback_seq_empty: false,
777            fallback_seq_empty_at_root: true,
778            backtrack_seq_empty_for_value: true,
779            fallback_seq_skip_item: false,
780            backtrack_seq_skip_item: true,
781            fallback_tuple_empty: false,
782            fallback_tuple_skip_item: false,
783            backtrack_tuple_skip_item: true,
784            fallback_tuple_struct_empty: false,
785            fallback_tuple_struct_skip_item: false,
786            backtrack_tuple_struct_skip_item: true,
787            fallback_map_empty: false,
788            fallback_map_empty_at_root: true,
789            backtrack_map_empty_for_value: true,
790            fallback_map_skip_item: false,
791            backtrack_map_skip_item: true,
792            fallback_struct_empty: false,
793            fallback_struct_empty_at_root: true,
794            backtrack_struct_empty_for_value: true,
795            fallback_struct_skip_field: true,
796            backtrack_struct_skip_field: true,
797            fallback_unit_variant: true,
798            fallback_other_skip_item: false,
799            backtrack_other_skip_item: true,
800            allow_incomplete_string_in_key_or_variant: false,
801        }
802    }
803}
804
805impl UnstableCustomBehavior {
806    pub fn no_fallbacks(mut self) -> Self {
807        let Self {
808            tolerate_deserializer_fail_after_visit_success: _,
809            fallback_any_as_none,
810            fallback_ignored_any_as_none,
811            fallback_default_bool,
812            fallback_int_zero,
813            fallback_default_float,
814            fallback_default_char,
815            fallback_default_str,
816            fallback_bytes_empty,
817            fallback_none,
818            fallback_none_at_mandatory,
819            fallback_unit,
820            fallback_unit_at_mandatory,
821            fallback_unit_struct,
822            fallback_unit_struct_at_mandatory,
823            fallback_seq_empty,
824            fallback_seq_empty_at_root,
825            backtrack_seq_empty_for_value: _,
826            fallback_seq_skip_item,
827            backtrack_seq_skip_item: _,
828            fallback_tuple_empty,
829            fallback_tuple_skip_item,
830            backtrack_tuple_skip_item: _,
831            fallback_tuple_struct_empty,
832            fallback_tuple_struct_skip_item: fallback_tuple_struct_skip_field,
833            backtrack_tuple_struct_skip_item: _,
834            fallback_map_empty,
835            fallback_map_empty_at_root,
836            backtrack_map_empty_for_value: _,
837            fallback_map_skip_item,
838            backtrack_map_skip_item: _,
839            fallback_struct_empty,
840            fallback_struct_empty_at_root,
841            backtrack_struct_empty_for_value: _,
842            fallback_struct_skip_field,
843            backtrack_struct_skip_field: _,
844            fallback_unit_variant,
845            fallback_other_skip_item,
846            backtrack_other_skip_item: _,
847            allow_incomplete_string_in_key_or_variant: allow_incomplete_string_in_key,
848        } = &mut self;
849
850        *fallback_any_as_none = false;
851        *fallback_ignored_any_as_none = false;
852        *fallback_default_bool = None;
853        *fallback_int_zero = false;
854        *fallback_default_float = None;
855        *fallback_default_char = None;
856        *fallback_default_str = None;
857        *fallback_bytes_empty = false;
858        *fallback_none = false;
859        *fallback_none_at_mandatory = false;
860        *fallback_unit = false;
861        *fallback_unit_at_mandatory = false;
862        *fallback_unit_struct = false;
863        *fallback_unit_struct_at_mandatory = false;
864        *fallback_seq_empty = false;
865        *fallback_seq_empty_at_root = false;
866        *fallback_seq_skip_item = false;
867        *fallback_tuple_empty = false;
868        *fallback_tuple_skip_item = false;
869        *fallback_tuple_struct_empty = false;
870        *fallback_tuple_struct_skip_field = false;
871        *fallback_map_empty = false;
872        *fallback_map_empty_at_root = false;
873        *fallback_map_skip_item = false;
874        *fallback_struct_empty = false;
875        *fallback_struct_empty_at_root = false;
876        *fallback_struct_skip_field = false;
877        *fallback_unit_variant = false;
878        *fallback_other_skip_item = false;
879        *allow_incomplete_string_in_key = false;
880
881        self
882    }
883
884    /// Maximally strict behavior. Probably this library behaves like ordinary
885    /// deserialization with this behavior.
886    pub fn strict() -> Self {
887        Self {
888            tolerate_deserializer_fail_after_visit_success: false,
889            fallback_any_as_none: false,
890            fallback_ignored_any_as_none: false,
891            fallback_default_bool: None,
892            fallback_int_zero: false,
893            fallback_default_float: None,
894            fallback_default_char: None,
895            fallback_default_str: None,
896            fallback_bytes_empty: false,
897            fallback_none: false,
898            fallback_none_at_mandatory: false,
899            fallback_unit: false,
900            fallback_unit_at_mandatory: false,
901            fallback_unit_struct: false,
902            fallback_unit_struct_at_mandatory: false,
903            fallback_seq_empty: false,
904            fallback_seq_empty_at_root: false,
905            backtrack_seq_empty_for_value: false,
906            fallback_seq_skip_item: false,
907            backtrack_seq_skip_item: false,
908            fallback_tuple_empty: false,
909            fallback_tuple_skip_item: false,
910            backtrack_tuple_skip_item: false,
911            fallback_tuple_struct_skip_item: false,
912            backtrack_tuple_struct_skip_item: false,
913            fallback_tuple_struct_empty: false,
914            fallback_map_empty: false,
915            fallback_map_empty_at_root: false,
916            backtrack_map_empty_for_value: false,
917            fallback_map_skip_item: false,
918            backtrack_map_skip_item: false,
919            fallback_struct_empty: false,
920            fallback_struct_empty_at_root: false,
921            backtrack_struct_empty_for_value: false,
922            fallback_struct_skip_field: false,
923            backtrack_struct_skip_field: false,
924            fallback_unit_variant: false,
925            fallback_other_skip_item: false,
926            backtrack_other_skip_item: false,
927            allow_incomplete_string_in_key_or_variant: false,
928        }
929    }
930
931    pub fn lenient() -> Self {
932        Self {
933            tolerate_deserializer_fail_after_visit_success: true,
934            fallback_any_as_none: true,
935            fallback_ignored_any_as_none: true,
936            fallback_default_bool: Some(false),
937            fallback_int_zero: true,
938            fallback_default_float: Some(0.0),
939            fallback_default_char: Some('\0'),
940            fallback_default_str: Some(""),
941            fallback_bytes_empty: true,
942            fallback_none: true,
943            fallback_none_at_mandatory: true,
944            fallback_unit: true,
945            fallback_unit_at_mandatory: true,
946            fallback_unit_struct: true,
947            fallback_unit_struct_at_mandatory: true,
948            fallback_seq_empty: true,
949            fallback_seq_empty_at_root: true,
950            backtrack_seq_empty_for_value: true,
951            fallback_seq_skip_item: true,
952            backtrack_seq_skip_item: true,
953            fallback_tuple_empty: true,
954            fallback_tuple_skip_item: true,
955            backtrack_tuple_skip_item: true,
956            fallback_tuple_struct_empty: true,
957            fallback_tuple_struct_skip_item: true,
958            backtrack_tuple_struct_skip_item: true,
959            fallback_map_empty: true,
960            fallback_map_empty_at_root: true,
961            backtrack_map_empty_for_value: true,
962            fallback_map_skip_item: true,
963            backtrack_map_skip_item: true,
964            fallback_struct_empty: true,
965            fallback_struct_empty_at_root: true,
966            backtrack_struct_empty_for_value: true,
967            fallback_struct_skip_field: true,
968            backtrack_struct_skip_field: true,
969            fallback_unit_variant: true,
970            fallback_other_skip_item: true,
971            backtrack_other_skip_item: true,
972            allow_incomplete_string_in_key_or_variant: true,
973        }
974    }
975}
976
977impl<Extra: ExtraOptions> Options<Extra> {
978    /// Deserialize from a generic [`Source`].
979    ///
980    /// Unlike [`Self::deserialize_from_json_str`] etc, this method does not automatically append
981    /// a random trailer. If you want that, then you can use
982    /// [`Self::prepare_str_for_borrowed_deserialization`].
983    ///
984    /// You can use [`Options::deserialize_seed`] instead if you need to pass a seed.
985    pub fn deserialize_source<'de, T, S>(self, source: S) -> Result<T, Error<S::Error>>
986    where
987        T: Deserialize<'de>,
988        S: Source<'de>,
989    {
990        self.deserialize_seed(PhantomData, source)
991    }
992
993    /// Deserialize from a seed.
994    ///
995    /// Unlike [`Self::deserialize_from_json_str`] etc, this method does not automatically append
996    /// a random trailer. If you want that, then you can use
997    /// [`Self::prepare_str_for_borrowed_deserialization`].
998    ///
999    /// If you don't need a seed, then you can use [`Options::deserialize_source`].
1000    pub fn deserialize_seed<'de, T, S>(
1001        self,
1002        seed: T,
1003        mut source: S,
1004    ) -> Result<T::Value, Error<S::Error>>
1005    where
1006        T: DeserializeSeed<'de> + Clone,
1007        S: Source<'de>,
1008    {
1009        let mut state = self.build();
1010        let mut attempt = AttemptState::initial(&state);
1011
1012        while {
1013            let max_n_backtracks = state.config.max_n_backtracks;
1014            max_n_backtracks
1015                .map(|max| state.n_backtracks <= max)
1016                .unwrap_or(true)
1017        } {
1018            let mut inner_deserializer_storage = Some(source.recreate_deserializer_storage());
1019            let inner_deserializer =
1020                S::use_deserializer_from_storage(&mut inner_deserializer_storage);
1021
1022            let deserializer = crate::attempt::Deserializer {
1023                global: &mut state,
1024                attempt: &mut attempt,
1025                is_at_root: true,
1026                is_for_key_or_variant: false,
1027                is_for_map_value: false,
1028                inner: inner_deserializer,
1029            };
1030
1031            match seed.clone().deserialize(deserializer) {
1032                Ok(value) => return Ok(value),
1033                Err(error) => {
1034                    debug!(attempt = state.n_backtracks, %error, "attempt failed");
1035                }
1036            }
1037
1038            attempt = match attempt.next_attempt_state_after_failure()? {
1039                Some(new_attempt) => new_attempt,
1040                None => {
1041                    return Err(InternalError::NoPotentialBacktrackPoint {
1042                        after_backtracks: state.n_backtracks,
1043                    }
1044                    .into());
1045                }
1046            };
1047            state.n_backtracks += 1;
1048        }
1049
1050        Err(InternalError::TooManyBacktracks.into())
1051    }
1052}