use std::string::String;
use std::vec::Vec;
use serde::de::{self, DeserializeSeed, IgnoredAny, MapAccess, SeqAccess};
use super::skips::{self, mark};
use super::Unfit;
#[derive(Default)]
pub struct Parts {
at: usize,
}
fn fail<E: de::Error>(e: E, step: impl FnOnce(Unfit) -> Unfit) -> E {
match Unfit::raised() {
Some(unfit) => step(unfit).raise(),
None => e,
}
}
fn part<T, E: de::Error>(
read: impl FnOnce() -> Result<T, E>,
step: impl Fn(Unfit) -> Unfit,
) -> Result<T, E> {
let at = mark();
match read() {
Ok(v) => {
skips::lead(at, &step);
Ok(v)
}
Err(e) => Err(fail(e, step)),
}
}
impl Parts {
pub fn field<'de, A: MapAccess<'de>, S: DeserializeSeed<'de>>(
slot: &mut Option<S::Value>,
name: &'static str,
m: &mut A,
seed: S,
) -> Result<(), A::Error> {
*slot = Some(part(|| m.next_value_seed(seed), |u| u.step(name))?);
Ok(())
}
pub fn optional<'de, A: MapAccess<'de>, T, S: DeserializeSeed<'de, Value = Option<T>>>(
slot: &mut Option<T>,
name: &'static str,
m: &mut A,
seed: S,
) -> Result<(), A::Error> {
if let Some(v) = part(|| m.next_value_seed(seed), |u| u.step(name))? {
*slot = Some(v);
}
Ok(())
}
pub fn other<T, K: AsRef<str> + Into<String>, E: de::Error>(
out: &mut Vec<(String, T)>,
key: K,
read: impl FnOnce() -> Result<T, E>,
) -> Result<(), E> {
let v = part(read, |u| u.field(key.as_ref()))?;
put(out, key.into(), v);
Ok(())
}
pub fn require<T, E: de::Error>(value: &Option<T>, name: &'static str) -> Result<(), E> {
match value {
Some(_) => Ok(()),
None => Err(Unfit::absent().step(name).raise()),
}
}
pub fn unnamed<E: de::Error>(key: &str) -> E {
Unfit::unnamed().field(key).raise()
}
pub fn item<'de, A: SeqAccess<'de>, S: DeserializeSeed<'de>>(
&mut self,
a: &mut A,
seed: S,
) -> Result<Option<S::Value>, A::Error> {
let at = self.at;
self.at = at.saturating_add(1);
part(|| a.next_element_seed(seed), |u| u.index(at))
}
pub fn tail<'de, A: SeqAccess<'de>, S: DeserializeSeed<'de> + Copy>(
&mut self,
a: &mut A,
seed: S,
) -> Result<Vec<S::Value>, A::Error> {
let mut out = Vec::new();
while let Some(item) = self.item(a, seed)? {
out.push(item);
}
Ok(out)
}
pub fn fixed<'de, A: SeqAccess<'de>>(&mut self, a: &mut A) -> Result<(), A::Error> {
match a.next_element::<IgnoredAny>()? {
Some(_) => {
let extra = Unfit::kind("no more items than the tuple holds").index(self.at);
Err(extra.raise())
}
None => Ok(()),
}
}
pub fn finish<T, E: de::Error>(out: Option<T>) -> Result<T, E> {
out.ok_or_else(|| Unfit::absent().raise())
}
}
pub(super) fn put<T>(out: &mut Vec<(String, T)>, key: String, value: T) {
match out.iter_mut().find(|(k, _)| *k == key) {
Some(entry) => entry.1 = value,
None => out.push((key, value)),
}
}