use std::borrow::Cow;
use crate::de::Node;
use crate::{Deserializer, Error, FromXml, Id, Kind};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AnyElement<'xml> {
pub ns: Cow<'xml, str>,
pub name: Cow<'xml, str>,
pub attributes: Vec<AnyAttribute<'xml>>,
pub text: Option<Cow<'xml, str>>,
pub children: Vec<AnyElement<'xml>>,
}
impl<'a> AnyElement<'a> {
fn deserialize<'xml: 'a>(
deserializer: &mut Deserializer<'_, 'xml>,
id: Id<'xml>,
) -> Result<Self, Error> {
let mut elem = Self {
ns: Cow::Borrowed(id.ns),
name: Cow::Borrowed(id.name),
attributes: Vec::new(),
text: None,
children: Vec::new(),
};
loop {
match deserializer.next() {
Some(Ok(Node::Attribute(attr))) => {
let id = deserializer.attribute_id(&attr)?;
elem.attributes.push(AnyAttribute {
ns: Cow::Borrowed(id.ns),
name: Cow::Borrowed(id.name),
value: attr.value,
});
}
Some(Ok(Node::Open(element))) => {
let child_id = deserializer.element_id(&element)?;
let mut nested = deserializer.nested(element);
elem.children
.push(Self::deserialize(&mut nested, child_id)?);
}
Some(Ok(Node::Text(text))) => elem.text = Some(text),
Some(Ok(Node::Close { .. })) => break,
Some(Ok(_)) => continue,
Some(Err(e)) => return Err(e),
None => break,
}
}
Ok(elem)
}
pub fn into_owned(self) -> AnyElement<'static> {
AnyElement {
ns: Cow::Owned(self.ns.into_owned()),
name: Cow::Owned(self.name.into_owned()),
attributes: self
.attributes
.into_iter()
.map(|a| a.into_owned())
.collect(),
text: self.text.map(|t| Cow::Owned(t.into_owned())),
children: self.children.into_iter().map(|c| c.into_owned()).collect(),
}
}
}
impl<'xml, 'a> FromXml<'xml> for AnyElement<'a>
where
'xml: 'a,
{
fn matches(_id: Id<'_>, _field: Option<Id<'_>>) -> bool {
true
}
fn deserialize<'cx>(
into: &mut Self::Accumulator,
_field: &'static str,
deserializer: &mut Deserializer<'cx, 'xml>,
) -> Result<(), Error> {
let id = deserializer.parent();
*into = Some(Self::deserialize(deserializer, id)?);
Ok(())
}
type Accumulator = Option<Self>;
const KIND: Kind = Kind::Element;
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AnyAttribute<'xml> {
pub ns: Cow<'xml, str>,
pub name: Cow<'xml, str>,
pub value: Cow<'xml, str>,
}
impl<'a> AnyAttribute<'a> {
pub fn into_owned(self) -> AnyAttribute<'static> {
AnyAttribute {
ns: Cow::Owned(self.ns.into_owned()),
name: Cow::Owned(self.name.into_owned()),
value: Cow::Owned(self.value.into_owned()),
}
}
}