use std::borrow::Cow;
use deser_core::State;
use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle};
use deser_core::ser::{Chunk, Describe, Serialize};
use deser_core::{Atom, ContainerShape, Error};
#[derive(Debug, Default)]
pub(crate) struct RootData {
pub(crate) name: Option<String>,
pub(crate) namespaces: Vec<(String, String)>,
}
impl Clone for RootData {
fn clone(&self) -> RootData {
RootData {
name: self.name.clone(),
namespaces: self.namespaces.clone(),
}
}
fn clone_from(&mut self, source: &RootData) {
self.name.clone_from(&source.name);
self.namespaces.clone_from(&source.namespaces);
}
}
#[derive(Debug, Default)]
pub(crate) struct Declarations(pub(crate) Vec<(String, String)>);
impl Clone for Declarations {
fn clone(&self) -> Declarations {
Declarations(self.0.clone())
}
fn clone_from(&mut self, source: &Declarations) {
self.0.clone_from(&source.0);
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct Root<T> {
pub name: Option<String>,
pub namespaces: Vec<(String, String)>,
pub value: T,
}
impl<T> Root<T> {
pub fn new<S: Into<String>>(name: S, value: T) -> Root<T> {
Root {
name: Some(name.into()),
namespaces: Vec::new(),
value,
}
}
pub fn with_namespace<P: Into<String>, U: Into<String>>(
mut self,
prefix: P,
uri: U,
) -> Root<T> {
self.namespaces.push((prefix.into(), uri.into()));
self
}
pub fn into_inner(self) -> T {
self.value
}
}
impl<T: Serialize> Serialize for Root<T> {
fn serialize(&self, state: &mut State) -> Result<Chunk<'_>, Error> {
let chunk = self.value.serialize(state)?;
if self.name.is_some() || !self.namespaces.is_empty() {
let data = state.event_mut::<RootData>();
data.name.clone_from(&self.name);
data.namespaces.clone_from(&self.namespaces);
}
Ok(chunk)
}
fn finish(&self, state: &mut State) -> Result<(), Error> {
self.value.finish(state)
}
fn is_optional(&self) -> bool {
self.value.is_optional()
}
fn container_shape(&self) -> ContainerShape {
self.value.container_shape()
}
fn describe(&self, d: &mut dyn Describe) {
self.value.describe(d)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Root<T> {
fn deserialize_into<'out>(
out: &'out mut Option<Self>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
SinkHandle::arena(
RootSink {
out,
slot: None,
compound: None,
data: RootData::default(),
},
state,
)
}
}
struct RootSink<'a, 'de, T> {
out: &'a mut Option<Root<T>>,
slot: Option<T>,
compound: Option<OwnedSink<'de, T>>,
data: RootData,
}
impl<'a, 'de, T: Deserialize<'de>> RootSink<'a, 'de, T> {
fn take_data(&mut self, state: &mut State) {
if let Some(data) = state.take_event::<RootData>() {
self.data = data;
}
}
fn compound(&mut self, state: &mut State) -> &mut dyn Sink<'de> {
self.compound
.get_or_insert_with(|| OwnedSink::deserialize(state))
.borrow_mut()
}
}
impl<'a, 'de, T: Deserialize<'de>> Sink<'de> for RootSink<'a, 'de, T> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.take_data(state);
let mut sink = T::deserialize_into(&mut self.slot, state);
sink.atom(atom, state)?;
sink.finish(state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.take_data(state);
let mut sink = T::deserialize_into(&mut self.slot, state);
sink.borrowed_atom(atom, state)?;
sink.finish(state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.take_data(state);
self.compound(state).map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.take_data(state);
self.compound(state).seq(state)
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.compound(state).next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.compound(state).next_value(state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.compound(state).value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
match self.compound {
Some(ref mut compound) => compound.borrow_mut().recover(err, state),
None => Err(err),
}
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
let value = match self.compound {
Some(ref mut compound) => {
compound.borrow_mut().finish(state)?;
compound.take()
}
None => self.slot.take(),
};
let RootData { name, namespaces } = std::mem::take(&mut self.data);
*self.out = value.map(|value| Root {
name,
namespaces,
value,
});
Ok(())
}
fn expecting(&self) -> Cow<'_, str> {
if let Some(ref compound) = self.compound {
return compound.borrow().expecting();
}
let mut slot = None;
let mut state = State::new();
Cow::Owned(
T::deserialize_into(&mut slot, &mut state)
.expecting()
.into_owned(),
)
}
}