deser_core/source.rs
1use alloc::sync::Arc;
2use core::fmt;
3
4use crate::State;
5
6/// The source the input ranges refer to.
7///
8/// Formats can publish the byte range in the input of every event (see
9/// [`State::input_range`](crate::State::input_range)). This is cheap, but
10/// resolving the ranges into lines and columns (see
11/// [`Position::of`](crate::Position::of)) requires the source. As
12/// this requires a copy of the input, formats only provide it when asked to
13/// with [`TrackLocations`]. They store it in the [`State`] as an extension
14/// value with [`set`](Self::set) before they emit the first event:
15///
16/// ```
17/// use deser::de::DeserializeDriver;
18/// use deser::Source;
19///
20/// let mut out = None::<bool>;
21/// let mut driver = DeserializeDriver::new(&mut out);
22/// Source("true".into()).set(driver.state_mut());
23/// assert_eq!(&*driver.state().get::<Source>().unwrap().0, "true");
24/// ```
25#[derive(Clone, Default)]
26pub struct Source(pub Arc<str>);
27
28impl Source {
29 /// Sets the source in the state.
30 #[inline]
31 pub fn set(self, state: &mut State) {
32 *state.get_mut::<Source>() = self;
33 }
34}
35
36impl fmt::Debug for Source {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 // the source can be large, it's not included
39 f.debug_struct("Source")
40 .field("len", &self.0.len())
41 .finish()
42 }
43}
44
45/// Asks the formats to provide the [`Source`] (a value of the
46/// [`Context`](crate::Context)).
47///
48/// Formats publish the byte range of every event, resolving them into
49/// lines and columns (for instance with the `Spanned` type of
50/// [`deser-location`](https://docs.rs/deser-location)) also requires the
51/// source, which is a copy of the input. Formats only provide it if this
52/// is set to `true` in the context (or the state). The errors a
53/// deserialization fails with have their line and column either way, but
54/// for instance the keys collected with
55/// [`UnknownFields::Collect`](crate::de::UnknownFields::Collect) only
56/// have them with the source:
57///
58/// ```
59/// use deser::de::{Deserializer, IgnoredFields, UnknownFields};
60/// use deser::{Context, Deserialize, TrackLocations};
61///
62/// #[derive(Deserialize)]
63/// struct Config {
64/// name: String,
65/// }
66///
67/// let config = deser_json::DeserializerConfig::builder()
68/// .context(Context::with(TrackLocations(true)))
69/// .build();
70/// let input = "{\n \"name\": \"demo\",\n \"nmae\": \"x\"\n}";
71/// let ignored = IgnoredFields::new();
72/// deser_json::Deserializer::from_str_with_config(input, config)
73/// .deserialize_with::<Config, _>(|driver| {
74/// UnknownFields::Collect(ignored.clone()).set(driver.state_mut())
75/// })
76/// .unwrap();
77/// let ignored = ignored.take();
78/// assert_eq!((ignored[0].line(), ignored[0].column()), (Some(3), Some(3)));
79/// ```
80///
81/// Formats check this with [`of`](Self::of) and set the [`Source`] before
82/// they emit the first event:
83///
84/// ```
85/// use deser::de::{DeserializeDriver, Deserializer};
86/// use deser::{Error, Source, TrackLocations};
87///
88/// /// A format which provides the source if asked to.
89/// struct Text<'a>(&'a str);
90///
91/// impl<'de> Deserializer<'de> for Text<'de> {
92/// fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'de>) -> Result<(), Error> {
93/// if TrackLocations::of(driver.state()) {
94/// Source(self.0.into()).set(driver.state_mut());
95/// }
96/// driver.state_mut().set_input_range(0, self.0.len());
97/// driver.emit(self.0)
98/// }
99/// }
100/// ```
101#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
102pub struct TrackLocations(pub bool);
103
104impl TrackLocations {
105 /// Returns `true` if the formats provide the source.
106 // not inlined: formats read it once per value
107 #[inline(never)]
108 pub fn of(state: &State) -> bool {
109 state.get::<TrackLocations>().is_some_and(|track| track.0)
110 }
111
112 /// Sets if the formats provide the source.
113 #[inline]
114 pub fn set(self, state: &mut State) {
115 *state.get_mut::<TrackLocations>() = self;
116 }
117}