use alloc::borrow::Cow;
use alloc::boxed::Box;
use alloc::format;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::ptr::NonNull;
use crate::State;
use crate::Text;
use crate::adapters::Same;
use crate::de::CollectedErrors;
use crate::de::atoms::{atom_into_handle, borrowed_atom_into_handle};
use crate::de::duplicates::{duplicate_field, is_seen, mark_seen};
use crate::de::sinkbox::ArenaStruct;
use crate::de::unknown::{unknown_field, wants_unknown_fields};
use crate::de::{Deserialize, Sink, SinkHandle, default_atom};
use crate::error::{Error, ErrorKind, discarded_error};
use crate::event::Atom;
const UNKNOWN: usize = usize::MAX;
pub(crate) type FieldLookup = fn(&str) -> Option<usize>;
pub(crate) type FieldCollects = fn(usize) -> bool;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Collect {
No,
First,
Next,
}
pub struct FieldKeySink {
index: usize,
other: Option<String>,
offset: Option<usize>,
lookup: FieldLookup,
collects: FieldCollects,
repeated: bool,
retain: bool,
}
pub enum NextField {
Ignore,
Field(usize),
Other(String),
}
impl FieldKeySink {
#[inline]
pub fn new(lookup: FieldLookup, collects: FieldCollects, retain: bool) -> FieldKeySink {
FieldKeySink {
index: UNKNOWN,
other: None,
offset: None,
lookup,
collects,
repeated: false,
retain,
}
}
#[inline]
pub fn collect(&mut self, index: usize, state: &State) -> Collect {
match (state.is_multimap() && (self.collects)(index), self.repeated) {
(false, _) => Collect::No,
(true, false) => Collect::First,
(true, true) => {
self.repeated = false;
Collect::Next
}
}
}
#[cold]
#[inline(never)]
fn duplicate(&mut self, index: usize, fields: &[&str], state: &State) -> Result<bool, Error> {
if state.is_multimap() && (self.collects)(index) {
self.repeated = true;
return Ok(true);
}
duplicate_field(fields[index], state)
}
#[inline]
pub fn reset(&mut self) {
self.index = UNKNOWN;
self.other = None;
}
#[inline]
pub fn set_index(&mut self, index: usize) {
self.reset();
self.index = index;
}
#[inline]
pub fn offset(&self) -> Option<usize> {
self.offset
}
#[inline(always)]
pub fn key_atom(
&mut self,
atom: Atom,
lookup: FieldLookup,
state: &mut State,
) -> Result<(), Error> {
match atom {
Atom::Str(key) | Atom::Lexical(key) => {
match lookup(&key) {
Some(index) => self.index = index,
None => self.other_key(key, state),
}
Ok(())
}
other => self.key_atom_slow(other, state),
}
}
#[inline(never)]
fn key_atom_slow(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.reset();
self.atom(atom, state)
}
#[inline(never)]
fn other_key(&mut self, key: Text<'_>, state: &State) {
self.index = UNKNOWN;
self.other = if self.retain || wants_unknown_fields(state) {
self.offset = state.input_range().map(|range| range.start);
Some(key.into_owned())
} else {
None
};
}
#[inline]
pub fn next_index(
&mut self,
seen: &mut [u64],
fields: &[&str],
deny: bool,
state: &mut State,
) -> Result<Option<usize>, Error> {
let index = core::mem::replace(&mut self.index, UNKNOWN);
if index != UNKNOWN {
Ok(
if !mark_seen(seen, index) || self.duplicate(index, fields, state)? {
Some(index)
} else {
None
},
)
} else {
if self.other.is_some() {
self.unknown_key(fields, deny, state)?;
}
Ok(None)
}
}
#[inline(never)]
fn unknown_key(&mut self, fields: &[&str], deny: bool, state: &mut State) -> Result<(), Error> {
match self.other.take() {
Some(key) => unknown_field(&key, self.offset, fields, deny, state),
None => Ok(()),
}
}
#[inline(never)]
pub fn next_field(
&mut self,
seen: &mut [u64],
fields: &[&str],
state: &State,
) -> Result<NextField, Error> {
let index = core::mem::replace(&mut self.index, UNKNOWN);
Ok(if index != UNKNOWN {
if !mark_seen(seen, index) || self.duplicate(index, fields, state)? {
NextField::Field(index)
} else {
NextField::Ignore
}
} else {
match self.other.take() {
Some(key) => NextField::Other(key),
None => NextField::Ignore,
}
})
}
}
impl<'de> Sink<'de> for FieldKeySink {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
match atom {
Atom::Str(key) | Atom::Lexical(key) => {
match (self.lookup)(&key) {
Some(index) => self.index = index,
None => self.other_key(key, state),
}
Ok(())
}
other => default_atom(self, other, state),
}
}
fn expecting(&self) -> Cow<'_, str> {
Cow::Borrowed("string")
}
}
pub struct StructInfo {
pub name: &'static str,
pub fields: &'static [&'static str],
pub lookup: FieldLookup,
pub deny: bool,
pub borrows: bool,
}
pub trait StructFields<'de>: Send {
fn field(&mut self, index: usize) -> &mut dyn FieldSlot<'de>;
#[inline(always)]
fn raw_fields() -> u64
where
Self: Sized,
{
0
}
#[inline(always)]
fn collect_fields() -> u64
where
Self: Sized,
{
u64::MAX
}
fn finish(&mut self, finish: &mut StructFinish<'_>, state: &mut State) -> Result<(), Error>;
}
pub trait FieldSlot<'de>: Send {
fn collects(&self) -> bool;
fn raw(&self) -> Option<&'static crate::ext::RawFormatInfo>;
fn sink(&mut self, collect: Collect, state: &mut State) -> SinkHandle<'_, 'de>;
fn atom(&mut self, collect: Collect, atom: Atom, state: &mut State) -> Result<(), Error>;
fn borrowed_atom(
&mut self,
collect: Collect,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error>;
}
pub struct FieldValue<T, A = Same> {
value: Option<T>,
_adapter: PhantomData<fn() -> A>,
}
impl<T, A> FieldValue<T, A> {
#[inline(always)]
pub fn new(value: Option<T>) -> FieldValue<T, A> {
FieldValue {
value,
_adapter: PhantomData,
}
}
#[inline(always)]
pub fn is_none(&self) -> bool {
self.value.is_none()
}
#[inline(always)]
pub fn set(&mut self, value: Option<T>) {
self.value = value;
}
#[inline(always)]
pub fn take(&mut self) -> Option<T> {
self.value.take()
}
}
struct NoField;
impl<'de> FieldSlot<'de> for NoField {
fn collects(&self) -> bool {
false
}
fn raw(&self) -> Option<&'static crate::ext::RawFormatInfo> {
None
}
fn sink(&mut self, _collect: Collect, _state: &mut State) -> SinkHandle<'_, 'de> {
SinkHandle::null()
}
fn atom(&mut self, _collect: Collect, _atom: Atom, _state: &mut State) -> Result<(), Error> {
Ok(())
}
fn borrowed_atom(
&mut self,
_collect: Collect,
_atom: Atom<'de>,
_state: &mut State,
) -> Result<(), Error> {
Ok(())
}
}
pub fn no_field_slot<'x, 'de>() -> &'x mut dyn FieldSlot<'de> {
Box::leak(Box::new(NoField))
}
impl<'de, T: Send, A: Deserialize<'de, T>> FieldSlot<'de> for FieldValue<T, A> {
fn collects(&self) -> bool {
A::__private_collects()
}
fn raw(&self) -> Option<&'static crate::ext::RawFormatInfo> {
A::__private_raw()
}
fn sink(&mut self, collect: Collect, state: &mut State) -> SinkHandle<'_, 'de> {
if A::__private_collects() && collect != Collect::No {
A::__private_collect_into(&mut self.value, state)
} else {
A::deserialize_into(&mut self.value, state)
}
}
fn atom(&mut self, collect: Collect, atom: Atom, state: &mut State) -> Result<(), Error> {
if A::__private_collects() && collect != Collect::No {
atom_into_handle(
A::__private_collect_into(&mut self.value, state),
atom,
state,
)
} else {
A::__private_atom_into(&mut self.value, atom, state)
}
}
fn borrowed_atom(
&mut self,
collect: Collect,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
if A::__private_collects() && collect != Collect::No {
borrowed_atom_into_handle(
A::__private_collect_into(&mut self.value, state),
atom,
state,
)
} else {
A::__private_borrowed_atom_into(&mut self.value, atom, state)
}
}
}
pub struct StructFinish<'a> {
seen: &'a Seen,
errors: &'a mut CollectedErrors,
fields: &'static [&'static str],
}
impl StructFinish<'_> {
#[inline(always)]
pub fn ok(&self) -> bool {
self.errors.is_empty()
}
#[cold]
#[inline(never)]
pub fn missing(&mut self, missing: &[bool], state: &State) -> Error {
if self.errors.is_empty() {
return missing_field(missing, self.fields, state);
}
for (index, (missing, name)) in missing.iter().zip(self.fields).enumerate() {
if *missing && !self.seen.contains(index) {
self.errors
.push(new_missing_field_error(name, state), state);
}
}
match self.errors.take() {
Some(err) => err,
None => unreachable!(),
}
}
}
struct Seen {
small: u64,
large: Option<Box<[u64]>>,
}
impl Seen {
fn contains(&self, index: usize) -> bool {
if index < 64 {
self.small & (1 << index) != 0
} else {
match self.large {
Some(ref large) => is_seen(large, index),
None => false,
}
}
}
}
pub struct StructSink<'a, 'de> {
fields: NonNull<dyn StructFields<'de> + 'a>,
key: FieldKeySink,
seen: Seen,
errors: CollectedErrors,
info: &'static StructInfo,
raw: u64,
collects: u64,
finished: bool,
}
unsafe impl Send for StructSink<'_, '_> {}
impl<'a, 'de> StructSink<'a, 'de> {
#[inline]
pub fn handle<F: StructFields<'de> + 'a>(
fields: F,
info: &'static StructInfo,
state: &mut State,
) -> SinkHandle<'a, 'de> {
SinkHandle::from_arena_struct(ArenaStruct::new(
fields,
info,
F::raw_fields(),
F::collect_fields(),
&mut state.arena,
))
}
#[inline(always)]
pub(crate) fn new(
fields: NonNull<dyn StructFields<'de> + 'a>,
info: &'static StructInfo,
raw: u64,
collects: u64,
) -> StructSink<'a, 'de> {
StructSink {
fields,
key: FieldKeySink::new(info.lookup, |_| false, info.deny),
seen: Seen {
small: 0,
large: None,
},
errors: CollectedErrors::new(),
info,
raw,
collects,
finished: false,
}
}
#[inline(always)]
pub(crate) fn fields_ptr(&self) -> (NonNull<dyn StructFields<'de> + 'a>, bool) {
(self.fields, !self.finished)
}
#[inline(always)]
fn fields(&mut self) -> &mut (dyn StructFields<'de> + 'a) {
unsafe { self.fields.as_mut() }
}
#[inline(never)]
fn request_raw(&mut self, state: &mut State) -> Result<(), Error> {
let index = self.key.index;
if self.raw & (1 << index.min(63)) != 0
&& index < self.info.fields.len()
&& let Some(format) = self.fields().field(index).raw()
{
return state.__private_request_raw(format);
}
Ok(())
}
fn collect(&mut self, index: usize, state: &State) -> Collect {
let collects = state.is_multimap()
&& self.collects & (1 << index.min(63)) != 0
&& self.fields().field(index).collects();
match (collects, core::mem::replace(&mut self.key.repeated, false)) {
(false, _) => Collect::No,
(true, false) => Collect::First,
(true, true) => Collect::Next,
}
}
#[inline(always)]
fn next_index(&mut self, state: &mut State) -> Result<Option<usize>, Error> {
self.finished = false;
let index = core::mem::replace(&mut self.key.index, UNKNOWN);
if index < 64 && self.seen.small & (1 << index) == 0 {
self.seen.small |= 1 << index;
return Ok(Some(index));
}
self.next_index_slow(index, state)
}
#[inline(never)]
fn next_index_slow(&mut self, index: usize, state: &mut State) -> Result<Option<usize>, Error> {
if index == UNKNOWN {
if self.key.other.is_some() {
self.key
.unknown_key(self.info.fields, self.info.deny, state)?;
}
return Ok(None);
}
let seen_before = if index < 64 {
true
} else {
let words = self.info.fields.len().div_ceil(64);
let large = self
.seen
.large
.get_or_insert_with(|| vec![0; words].into_boxed_slice());
mark_seen(large, index)
};
if !seen_before || (state.is_multimap() && self.fields().field(index).collects()) {
if seen_before {
self.key.repeated = true;
}
Ok(Some(index))
} else if duplicate_field(self.info.fields[index], state)? {
Ok(Some(index))
} else {
Ok(None)
}
}
}
impl<'a, 'de> Sink<'de> for StructSink<'a, 'de> {
fn expecting(&self) -> Cow<'_, str> {
Cow::Borrowed(self.info.name)
}
fn map(&mut self, _state: &mut State) -> Result<(), Error> {
Ok(())
}
fn next_key(&mut self, _state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.key.reset();
Ok(SinkHandle::to(&mut self.key))
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
Ok(match self.next_index(state)? {
Some(index) => {
let collect = self.collect(index, state);
self.fields().field(index).sink(collect, state)
}
None => SinkHandle::null(),
})
}
fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.key.key_atom(atom, self.key.lookup, state)?;
if self.raw != 0 {
return self.request_raw(state);
}
Ok(())
}
fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
match self.next_index(state)? {
Some(index) => {
let collect = self.collect(index, state);
self.fields().field(index).atom(collect, atom, state)
}
None => Ok(()),
}
}
fn __private_borrowed_key_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
self.key.key_atom(atom, self.key.lookup, state)?;
if self.raw != 0 {
return self.request_raw(state);
}
Ok(())
}
fn __private_borrowed_value_atom(
&mut self,
atom: Atom<'de>,
state: &mut State,
) -> Result<(), Error> {
match self.next_index(state)? {
Some(index) if self.info.borrows => {
let collect = self.collect(index, state);
self.fields()
.field(index)
.borrowed_atom(collect, atom, state)
}
Some(index) => {
let collect = self.collect(index, state);
self.fields().field(index).atom(collect, atom, state)
}
None => Ok(()),
}
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
match (self.info.lookup)(key) {
Some(index) => {
self.key.set_index(index);
self.next_value(state).map(Some)
}
None => Ok(None),
}
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
self.errors.collect(err, state)
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
let mut finish = StructFinish {
seen: &self.seen,
errors: &mut self.errors,
fields: self.info.fields,
};
let rv = unsafe { self.fields.as_mut() }.finish(&mut finish, state);
self.finished = true;
rv
}
}
pub trait UpdateFields<'de>: Send {
fn update_field(
&mut self,
index: usize,
collect: Collect,
state: &mut State,
) -> SinkHandle<'_, 'de>;
fn collects(&self, index: usize) -> bool;
}
pub struct StructUpdateSink<'a, 'de> {
value: &'a mut (dyn UpdateFields<'de> + 'a),
key: FieldKeySink,
seen: Vec<u64>,
info: &'static StructInfo,
}
impl<'a, 'de> StructUpdateSink<'a, 'de> {
pub fn handle(
value: &'a mut (dyn UpdateFields<'de> + 'a),
info: &'static StructInfo,
state: &mut State,
) -> SinkHandle<'a, 'de> {
SinkHandle::arena(
StructUpdateSink {
value,
key: FieldKeySink::new(info.lookup, |_| false, info.deny),
seen: vec![0; info.fields.len().div_ceil(64)],
info,
},
state,
)
}
}
impl<'a, 'de> Sink<'de> for StructUpdateSink<'a, 'de> {
fn expecting(&self) -> Cow<'_, str> {
Cow::Borrowed(self.info.name)
}
fn map(&mut self, _state: &mut State) -> Result<(), Error> {
Ok(())
}
fn next_key(&mut self, _state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.key.reset();
Ok(SinkHandle::to(&mut self.key))
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
let index = core::mem::replace(&mut self.key.index, UNKNOWN);
if index == UNKNOWN {
if self.key.other.is_some() {
self.key
.unknown_key(self.info.fields, self.info.deny, state)?;
}
return Ok(SinkHandle::null());
}
let repeated = mark_seen(&mut self.seen, index);
let collects = state.is_multimap() && self.value.collects(index);
if repeated && !collects && !duplicate_field(self.info.fields[index], state)? {
return Ok(SinkHandle::null());
}
let collect = if !collects {
Collect::No
} else if repeated {
Collect::Next
} else {
Collect::First
};
Ok(self.value.update_field(index, collect, state))
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
match (self.key.lookup)(key) {
Some(index) => {
self.key.set_index(index);
self.next_value(state).map(Some)
}
None => Ok(None),
}
}
}
#[cold]
#[inline(never)]
pub fn collected_errors(
errors: &mut CollectedErrors,
seen: &[u64],
missing: &[bool],
indexes: &[usize],
names: &[&str],
state: &State,
) -> Error {
for ((missing, index), name) in missing.iter().zip(indexes).zip(names) {
if *missing && !is_seen(seen, *index) {
errors.push(new_missing_field_error(name, state), state);
}
}
match errors.take() {
Some(err) => err,
None => unreachable!(),
}
}
#[cold]
pub fn missing_field(missing: &[bool], names: &[&str], state: &State) -> Error {
if state.collects_errors() {
let errors = missing
.iter()
.zip(names)
.filter(|(missing, _)| **missing)
.map(|(_, name)| state.error_in_context(new_missing_field_error(name, state)));
if let Some(err) = Error::from_errors(errors) {
return err;
}
}
let index = missing.iter().position(|x| *x).unwrap_or_default();
new_missing_field_error(names[index], state)
}
#[cold]
pub fn new_missing_field_error(name: &str, state: &State) -> Error {
if state.discards_errors {
return discarded_error(ErrorKind::MissingField);
}
Error::new(ErrorKind::MissingField, format!("missing field `{}`", name))
}