use crate::State;
use crate::Text;
#[cfg(feature = "derive")]
use crate::de::Deserialize;
use crate::de::lexical::ContentKey;
#[cfg(feature = "derive")]
use crate::de::lexical::is_empty_null;
use crate::de::{Sink, SinkHandle};
use crate::error::{Error, ErrorKind, discarded_error};
use crate::event::{Atom, Implicit};
use alloc::format;
#[cfg(feature = "derive")]
#[inline(never)]
pub fn field_update<'a, 'de, T: Deserialize<'de>>(
value: &'a mut T,
state: &mut State,
) -> SinkHandle<'a, 'de> {
T::deserialize_update(value, state)
}
#[cfg(feature = "derive")]
#[inline]
pub fn atom_into<'de, T: Deserialize<'de>>(
slot: &mut Option<T>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
T::__private_atom_into(slot, atom, state)
}
#[cfg(feature = "derive")]
#[inline]
pub fn borrowed_atom_into<'de, T: Deserialize<'de>>(
slot: &mut Option<T>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
T::__private_borrowed_atom_into(slot, atom, state)
}
#[cfg(feature = "derive")]
pub fn unit_struct(atom: &Atom<'_>, expecting: &str, state: &State) -> Result<(), Error> {
match atom {
Atom::Null => Ok(()),
Atom::Lexical(value) if is_empty_null(value, state) => Ok(()),
Atom::Implicit(value) if value.value() == crate::ImplicitValue::Null => Ok(()),
Atom::Ext(ext) => match ext.fallback() {
Atom::Ext(_) => Err(atom.unexpected_error(expecting)),
fallback => unit_struct(&fallback, expecting, state),
},
_ => Err(atom.unexpected_error(expecting)),
}
}
#[inline(never)]
pub fn atom_into_handle(
mut sink: SinkHandle<'_, '_>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
let rv = sink.atom(atom, state).and_then(|()| sink.finish(state));
sink.release(state);
rv
}
#[inline(never)]
pub fn borrowed_atom_into_handle<'de>(
mut sink: SinkHandle<'_, 'de>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
let rv = sink
.borrowed_atom(atom, state)
.and_then(|()| sink.finish(state));
sink.release(state);
rv
}
#[inline(never)]
pub(crate) fn default_key_atom(
sink: &mut dyn Sink<'_>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
atom_into_handle(sink.next_key(state)?, atom, state)
}
#[inline(never)]
pub(crate) fn default_value_atom(
sink: &mut dyn Sink<'_>,
atom: Atom,
state: &mut State,
) -> Result<(), Error> {
atom_into_handle(sink.next_value(state)?, atom, state)
}
#[inline(never)]
pub(crate) fn default_borrowed_key_atom<'de>(
sink: &mut dyn Sink<'de>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
borrowed_atom_into_handle(sink.next_key(state)?, atom, state)
}
#[inline(never)]
pub(crate) fn default_borrowed_value_atom<'de>(
sink: &mut dyn Sink<'de>,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
borrowed_atom_into_handle(sink.next_value(state)?, atom, state)
}
#[inline(never)]
pub fn default_atom(sink: &mut dyn Sink<'_>, atom: Atom, state: &mut State) -> Result<(), Error> {
let atom = match atom {
Atom::F32(value) => return sink.atom(Atom::F64(f64::from(value)), state),
Atom::Lexical(value) => {
if let Some(key) = ContentKey::of(state) {
return lexical_into_map(sink, value, key, state);
}
return sink.atom(Atom::Str(value), state);
}
Atom::Implicit(value) => return implicit_into(sink, value, state),
atom => atom,
};
if let Atom::Ext(ref ext) = atom {
if let Some(input) = ext.downcast_value_ref::<crate::ext::RawInput>() {
return crate::ext::raw::parse_into(input, sink, state);
}
let fallback = ext.fallback();
debug_assert!(
!matches!(fallback, Atom::Ext(_)),
"the fallback of an extension value must not be an extension value"
);
if !matches!(fallback, Atom::Ext(_)) {
return sink.atom(fallback, state);
}
}
if state.discards_errors {
return Err(discarded_error(ErrorKind::InvalidType));
}
Err(atom.unexpected_error(&sink.expecting()))
}
#[cold]
#[inline(never)]
fn lexical_into_map(
sink: &mut dyn Sink<'_>,
text: Text<'_>,
key: &'static str,
state: &mut State,
) -> Result<(), Error> {
let err = match sink.atom(Atom::Str(text.clone()), state) {
Err(err) if err.kind().is_rejection() => err,
rv => return rv,
};
if sink.map(state).is_err() {
return Err(err);
}
if !text.is_empty() {
sink.__private_key_atom(Atom::Lexical(Text::borrowed(key)), state)?;
sink.__private_value_atom(Atom::Lexical(text), state)?;
}
Ok(())
}
fn implicit_into(sink: &mut dyn Sink<'_>, value: Implicit, state: &mut State) -> Result<(), Error> {
let (text, value) = value.into_parts();
match sink.atom(value.to_atom(), state) {
Err(err) if err.kind().is_rejection() => sink.atom(Atom::Str(text), state).map_err(|_| err),
rv => rv,
}
}
#[cold]
#[inline(never)]
pub(crate) fn default_container(
sink: &mut dyn Sink<'_>,
got: &str,
state: &State,
) -> Result<(), Error> {
if state.discards_errors {
return Err(discarded_error(ErrorKind::InvalidType));
}
Err(Error::new(
ErrorKind::InvalidType,
format!("unexpected {}, expected {}", got, sink.expecting()),
))
}