Skip to main content

deser_core/de/
atoms.rs

1//! Deserializes atoms without going through the sink of a slot.
2//!
3//! These functions are not part of the public API.  They are used by the
4//! implementations in this crate and by the derive (through
5//! `deser::__derive`).
6use crate::State;
7use crate::Text;
8#[cfg(feature = "derive")]
9use crate::de::Deserialize;
10use crate::de::lexical::ContentKey;
11#[cfg(feature = "derive")]
12use crate::de::lexical::is_empty_null;
13use crate::de::{Sink, SinkHandle};
14use crate::error::{Error, ErrorKind, discarded_error};
15use crate::event::{Atom, Implicit};
16use alloc::format;
17
18/// Creates the sink that updates a field of a derived struct.
19///
20/// This is not inlined so that it exists once per type (updates are not
21/// performance critical).
22#[cfg(feature = "derive")]
23#[inline(never)]
24pub fn field_update<'a, 'de, T: Deserialize<'de>>(
25    value: &'a mut T,
26    state: &mut State,
27) -> SinkHandle<'a, 'de> {
28    T::deserialize_update(value, state)
29}
30
31/// Deserializes an atom into a slot.
32///
33/// This is equivalent to what the default implementation of
34/// `Sink::__private_value_atom` does with the sink of the slot.
35#[cfg(feature = "derive")]
36#[inline]
37pub fn atom_into<'de, T: Deserialize<'de>>(
38    slot: &mut Option<T>,
39    atom: Atom,
40    state: &mut State,
41) -> Result<(), Error> {
42    T::__private_atom_into(slot, atom, state)
43}
44
45/// Deserializes a borrowed atom into a slot.
46///
47/// This is equivalent to what the default implementation of
48/// `Sink::__private_borrowed_value_atom` does with the sink of the slot.
49#[cfg(feature = "derive")]
50#[inline]
51pub fn borrowed_atom_into<'de, T: Deserialize<'de>>(
52    slot: &mut Option<T>,
53    atom: Atom<'de>,
54    state: &mut State,
55) -> Result<(), Error> {
56    T::__private_borrowed_atom_into(slot, atom, state)
57}
58
59/// Checks that an atom is the value of a unit struct.
60///
61/// Unit structs are null (and empty lexical atoms if empty text is a
62/// missing value, like for `()`, see
63/// [`LexicalRules`](crate::de::LexicalRules)).  Other atoms are rejected
64/// with `expecting` as expected type.
65#[cfg(feature = "derive")]
66pub fn unit_struct(atom: &Atom<'_>, expecting: &str, state: &State) -> Result<(), Error> {
67    match atom {
68        Atom::Null => Ok(()),
69        Atom::Lexical(value) if is_empty_null(value, state) => Ok(()),
70        Atom::Implicit(value) if value.value() == crate::ImplicitValue::Null => Ok(()),
71        Atom::Ext(ext) => match ext.fallback() {
72            Atom::Ext(_) => Err(atom.unexpected_error(expecting)),
73            fallback => unit_struct(&fallback, expecting, state),
74        },
75        _ => Err(atom.unexpected_error(expecting)),
76    }
77}
78
79/// Deserializes an atom into a sink handle.
80///
81/// This is intentionally not inlined as it's used by the default
82/// implementations of the sink methods which exist for every sink.
83#[inline(never)]
84pub fn atom_into_handle(
85    mut sink: SinkHandle<'_, '_>,
86    atom: Atom,
87    state: &mut State,
88) -> Result<(), Error> {
89    let rv = sink.atom(atom, state).and_then(|()| sink.finish(state));
90    sink.release(state);
91    rv
92}
93
94/// Deserializes a borrowed atom into a sink handle.
95#[inline(never)]
96pub fn borrowed_atom_into_handle<'de>(
97    mut sink: SinkHandle<'_, 'de>,
98    atom: Atom<'de>,
99    state: &mut State,
100) -> Result<(), Error> {
101    let rv = sink
102        .borrowed_atom(atom, state)
103        .and_then(|()| sink.finish(state));
104    sink.release(state);
105    rv
106}
107
108// The following functions implement the default methods of `Sink`.  The
109// default methods exist for every sink type, so they only forward to these
110// functions which exist once.
111
112/// The default of `Sink::__private_key_atom`.
113#[inline(never)]
114pub(crate) fn default_key_atom(
115    sink: &mut dyn Sink<'_>,
116    atom: Atom,
117    state: &mut State,
118) -> Result<(), Error> {
119    atom_into_handle(sink.next_key(state)?, atom, state)
120}
121
122/// The default of `Sink::__private_value_atom`.
123#[inline(never)]
124pub(crate) fn default_value_atom(
125    sink: &mut dyn Sink<'_>,
126    atom: Atom,
127    state: &mut State,
128) -> Result<(), Error> {
129    atom_into_handle(sink.next_value(state)?, atom, state)
130}
131
132/// The default of `Sink::__private_borrowed_key_atom`.
133#[inline(never)]
134pub(crate) fn default_borrowed_key_atom<'de>(
135    sink: &mut dyn Sink<'de>,
136    atom: Atom<'de>,
137    state: &mut State,
138) -> Result<(), Error> {
139    borrowed_atom_into_handle(sink.next_key(state)?, atom, state)
140}
141
142/// The default of `Sink::__private_borrowed_value_atom`.
143#[inline(never)]
144pub(crate) fn default_borrowed_value_atom<'de>(
145    sink: &mut dyn Sink<'de>,
146    atom: Atom<'de>,
147    state: &mut State,
148) -> Result<(), Error> {
149    borrowed_atom_into_handle(sink.next_value(state)?, atom, state)
150}
151
152/// The default handling of atoms, which is what [`Sink::atom`] does by
153/// default.
154///
155/// Sinks pass the atoms they do not accept to this (and values the atoms
156/// their [`deserialize_atom`](crate::de::Deserialize::deserialize_atom) does
157/// not accept, with the slot as sink).  Some atoms are passed on to
158/// [`Sink::atom`] of the sink again in another form:
159///
160/// * [`Atom::Ext`] values are lowered into the core data model with their
161///   [`fallback`](crate::ext::ExtValue::fallback) (the input of raw values
162///   is parsed into the sink).
163/// * [`Atom::F32`] is widened into an [`Atom::F64`], so sinks that accept
164///   floats only need to handle `F64`.
165/// * [`Atom::Lexical`] is passed on as [`Atom::Str`], so sinks that accept
166///   strings accept lexical atoms too.
167/// * [`Atom::Implicit`] is passed on as its value and, if that is rejected,
168///   as its text (see [`Implicit`]).
169///
170/// For all other atoms an error is returned that is based on
171/// [`Sink::expecting`] of the sink, which is
172/// [`Deserialize::expecting`](crate::de::Deserialize::expecting) for a
173/// [`Slot`](crate::de::Slot).
174///
175/// ```
176/// use deser::de::{Deserialize, Slot, default_atom};
177/// use deser::{Atom, Error, State};
178///
179/// struct MyBool(bool);
180///
181/// impl<'de> Deserialize<'de> for MyBool {
182///     fn deserialize_atom(
183///         slot: &mut Slot<Self>,
184///         atom: Atom,
185///         state: &mut State,
186///     ) -> Result<(), Error> {
187///         match atom {
188///             Atom::Bool(value) => {
189///                 slot.set(MyBool(value));
190///                 Ok(())
191///             }
192///             other => default_atom(slot, other, state),
193///         }
194///     }
195/// }
196///
197/// // a lexical atom is passed on as string, which is rejected
198/// let mut out = None::<MyBool>;
199/// let mut driver = deser::de::DeserializeDriver::new(&mut out);
200/// let err = driver.emit(Atom::Lexical("true".into())).unwrap_err();
201/// assert_eq!(err.message(), "unexpected string, expected MyBool");
202/// ```
203#[inline(never)]
204pub fn default_atom(sink: &mut dyn Sink<'_>, atom: Atom, state: &mut State) -> Result<(), Error> {
205    let atom = match atom {
206        Atom::F32(value) => return sink.atom(Atom::F64(f64::from(value)), state),
207        Atom::Lexical(value) => {
208            if let Some(key) = ContentKey::of(state) {
209                return lexical_into_map(sink, value, key, state);
210            }
211            return sink.atom(Atom::Str(value), state);
212        }
213        Atom::Implicit(value) => return implicit_into(sink, value, state),
214        atom => atom,
215    };
216    if let Atom::Ext(ref ext) = atom {
217        // the input of a raw value is parsed into the sink
218        if let Some(input) = ext.downcast_value_ref::<crate::ext::RawInput>() {
219            return crate::ext::raw::parse_into(input, sink, state);
220        }
221        let fallback = ext.fallback();
222        debug_assert!(
223            !matches!(fallback, Atom::Ext(_)),
224            "the fallback of an extension value must not be an extension value"
225        );
226        if !matches!(fallback, Atom::Ext(_)) {
227            return sink.atom(fallback, state);
228        }
229    }
230    if state.discards_errors {
231        return Err(discarded_error(ErrorKind::InvalidType));
232    }
233    Err(atom.unexpected_error(&sink.expecting()))
234}
235
236/// Delivers text that a sink rejected as string or as map with the text
237/// under the key of the content (see [`ContentKey`]).
238///
239/// If the sink rejects both, the error of the string is returned.
240#[cold]
241#[inline(never)]
242fn lexical_into_map(
243    sink: &mut dyn Sink<'_>,
244    text: Text<'_>,
245    key: &'static str,
246    state: &mut State,
247) -> Result<(), Error> {
248    let err = match sink.atom(Atom::Str(text.clone()), state) {
249        Err(err) if err.kind().is_rejection() => err,
250        rv => return rv,
251    };
252    if sink.map(state).is_err() {
253        return Err(err);
254    }
255    // empty text is no content
256    if !text.is_empty() {
257        sink.__private_key_atom(Atom::Lexical(Text::borrowed(key)), state)?;
258        sink.__private_value_atom(Atom::Lexical(text), state)?;
259    }
260    Ok(())
261}
262
263/// Delivers an implicit atom as its value or its text.
264///
265/// The text is only tried if the value is rejected for its type, errors of
266/// the value (like an integer that is out of range) are passed on.  If the
267/// text is rejected too, the error of the value is returned.
268fn implicit_into(sink: &mut dyn Sink<'_>, value: Implicit, state: &mut State) -> Result<(), Error> {
269    let (text, value) = value.into_parts();
270    match sink.atom(value.to_atom(), state) {
271        Err(err) if err.kind().is_rejection() => sink.atom(Atom::Str(text), state).map_err(|_| err),
272        rv => rv,
273    }
274}
275
276/// The default of `Sink::map` and `Sink::seq`.
277#[cold]
278#[inline(never)]
279pub(crate) fn default_container(
280    sink: &mut dyn Sink<'_>,
281    got: &str,
282    state: &State,
283) -> Result<(), Error> {
284    if state.discards_errors {
285        return Err(discarded_error(ErrorKind::InvalidType));
286    }
287    Err(Error::new(
288        ErrorKind::InvalidType,
289        format!("unexpected {}, expected {}", got, sink.expecting()),
290    ))
291}