use core::{
fmt::{self, Debug},
str,
};
use std::{
borrow::Cow,
collections::VecDeque,
fmt::Formatter,
iter,
ops::{Deref, DerefMut},
};
use crate::{
de,
ser::{self, IncludePrefix},
types::iterator::IteratorVisitor,
ExpandedName, ExpandedNameBuf, PrefixBuf,
};
pub mod deserialize;
mod deserializer;
mod serialize;
mod serializer;
pub fn from_value<'de, T: crate::Deserialize<'de>>(
value: &'de XmlValue,
) -> Result<T, XmlValueDeserializerError> {
T::deserialize_seq(value)
}
pub fn to_value<T: crate::Serialize>(input: &T) -> Result<XmlValue, XmlValueSerializerError> {
let mut value = XmlValue::None;
input.serialize(&mut value)?;
Ok(value)
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum XmlValue {
Text(XmlText),
CData(XmlCData),
Element(XmlElement),
Seq(XmlSeq<XmlValue>),
PI(XmlProcessingInstruction),
Decl(XmlDecl),
Comment(XmlComment),
Doctype(XmlDoctype),
#[default]
None,
}
impl From<XmlText> for XmlValue {
fn from(value: XmlText) -> Self {
XmlValue::Text(value)
}
}
impl From<XmlCData> for XmlValue {
fn from(value: XmlCData) -> Self {
XmlValue::CData(value)
}
}
impl From<XmlElement> for XmlValue {
fn from(value: XmlElement) -> Self {
XmlValue::Element(value)
}
}
impl From<XmlSeq<XmlValue>> for XmlValue {
fn from(value: XmlSeq<XmlValue>) -> Self {
XmlValue::Seq(value)
}
}
impl From<XmlProcessingInstruction> for XmlValue {
fn from(value: XmlProcessingInstruction) -> Self {
XmlValue::PI(value)
}
}
impl From<XmlDecl> for XmlValue {
fn from(value: XmlDecl) -> Self {
XmlValue::Decl(value)
}
}
impl From<XmlComment> for XmlValue {
fn from(value: XmlComment) -> Self {
XmlValue::Comment(value)
}
}
impl From<XmlDoctype> for XmlValue {
fn from(value: XmlDoctype) -> Self {
XmlValue::Doctype(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
enum XmlValueWithoutSeq {
Text(XmlText),
CData(XmlCData),
Element(XmlElement),
PI(XmlProcessingInstruction),
Decl(XmlDecl),
Comment(XmlComment),
Doctype(XmlDoctype),
#[default]
None,
}
impl From<XmlValueWithoutSeq> for XmlValue {
fn from(value: XmlValueWithoutSeq) -> Self {
match value {
XmlValueWithoutSeq::Text(xml_text) => XmlValue::Text(xml_text),
XmlValueWithoutSeq::CData(xml_cdata) => XmlValue::CData(xml_cdata),
XmlValueWithoutSeq::Element(xml_element) => XmlValue::Element(xml_element),
XmlValueWithoutSeq::PI(xml_processing_instruction) => {
XmlValue::PI(xml_processing_instruction)
}
XmlValueWithoutSeq::Decl(xml_decl) => XmlValue::Decl(xml_decl),
XmlValueWithoutSeq::Comment(xml_comment) => XmlValue::Comment(xml_comment),
XmlValueWithoutSeq::Doctype(xml_doctype) => XmlValue::Doctype(xml_doctype),
XmlValueWithoutSeq::None => XmlValue::None,
}
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlText(pub Vec<u8>);
impl XmlText {
pub fn new<T: AsRef<str>>(text: T) -> Self {
Self(text.as_ref().as_bytes().to_vec())
}
}
impl Debug for XmlText {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("XmlText")
.field(&String::from_utf8_lossy(&self.0))
.finish()
}
}
impl From<String> for XmlText {
fn from(value: String) -> Self {
Self(value.into_bytes())
}
}
impl From<&str> for XmlText {
fn from(value: &str) -> Self {
Self(value.to_owned().into_bytes())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct XmlCData(pub Vec<u8>);
impl XmlCData {
pub fn new<T: Into<Vec<u8>>>(text: T) -> Self {
Self(text.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum XmlChild {
Text(XmlText),
CData(XmlCData),
Element(XmlElement),
PI(XmlProcessingInstruction),
Comment(XmlComment),
#[default]
None,
}
impl From<XmlText> for XmlChild {
fn from(value: XmlText) -> Self {
XmlChild::Text(value)
}
}
impl From<XmlCData> for XmlChild {
fn from(value: XmlCData) -> Self {
XmlChild::CData(value)
}
}
impl From<XmlElement> for XmlChild {
fn from(value: XmlElement) -> Self {
XmlChild::Element(value)
}
}
impl From<XmlProcessingInstruction> for XmlChild {
fn from(value: XmlProcessingInstruction) -> Self {
XmlChild::PI(value)
}
}
impl From<XmlComment> for XmlChild {
fn from(value: XmlComment) -> Self {
XmlChild::Comment(value)
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlElement {
pub name: ExpandedNameBuf,
pub attributes: VecDeque<XmlAttribute>,
pub children: XmlSeq<XmlChild>,
pub enforce_prefix: IncludePrefix,
pub preferred_prefix: Option<PrefixBuf>,
}
impl XmlElement {
pub fn new<T: Into<ExpandedNameBuf>>(name: T) -> Self {
Self {
name: name.into(),
attributes: VecDeque::new(),
children: XmlSeq::new(),
enforce_prefix: IncludePrefix::default(),
preferred_prefix: None,
}
}
pub fn with_attribute<T: Into<XmlAttribute>>(mut self, attribute: T) -> Self {
self.attributes.push_back(attribute.into());
self
}
pub fn with_attributes<U: Into<XmlAttribute>, T: IntoIterator<Item = U>>(
mut self,
attributes: T,
) -> Self {
self.attributes
.extend(attributes.into_iter().map(Into::into));
self
}
pub fn with_child<T: Into<XmlChild>>(mut self, child: T) -> Self {
self.children.values.push_back(child.into());
self
}
pub fn with_children<U: Into<XmlChild>, T: IntoIterator<Item = U>>(
mut self,
children: T,
) -> Self {
self.children
.values
.extend(children.into_iter().map(Into::into));
self
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlAttribute {
pub name: ExpandedNameBuf,
pub value: XmlText,
}
impl XmlAttribute {
pub fn new<T: Into<ExpandedNameBuf>, U: Into<XmlText>>(name: T, value: U) -> Self {
Self {
name: name.into(),
value: value.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlSeq<T> {
values: VecDeque<T>,
}
impl<T> IntoIterator for XmlSeq<T> {
type Item = T;
type IntoIter = std::collections::vec_deque::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.values.into_iter()
}
}
impl<T> FromIterator<T> for XmlSeq<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
values: iter.into_iter().collect(),
}
}
}
impl<T> From<VecDeque<T>> for XmlSeq<T> {
fn from(value: VecDeque<T>) -> Self {
Self::from_vec_deque(value)
}
}
impl<T> XmlSeq<T> {
pub fn new() -> Self {
Self::from_vec_deque(VecDeque::new())
}
pub fn from_vec_deque(values: VecDeque<T>) -> Self {
Self { values }
}
pub fn into_inner(self) -> VecDeque<T> {
self.values
}
}
impl Deref for XmlSeq<XmlValue> {
type Target = VecDeque<XmlValue>;
fn deref(&self) -> &Self::Target {
&self.values
}
}
impl DerefMut for XmlSeq<XmlValue> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.values
}
}
impl<T> Default for XmlSeq<T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlProcessingInstruction {
target: Vec<u8>,
content: Vec<u8>,
}
impl XmlProcessingInstruction {
pub fn new<T: Into<Vec<u8>>, U: Into<Vec<u8>>>(target: T, content: U) -> Self {
Self {
target: target.into(),
content: content.into(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlDecl {
pub version: String,
pub encoding: Option<String>,
pub standalone: Option<String>,
}
impl XmlDecl {
pub fn new<T: AsRef<str>>(version: T, encoding: Option<T>, standalone: Option<T>) -> Self {
Self {
version: version.as_ref().to_string(),
encoding: encoding.map(|e| e.as_ref().to_string()),
standalone: standalone.map(|s| s.as_ref().to_string()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlComment(pub Vec<u8>);
impl XmlComment {
pub fn new<T: Into<Vec<u8>>>(comment: T) -> Self {
Self(comment.into())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[non_exhaustive]
pub struct XmlDoctype(pub Vec<u8>);
impl XmlDoctype {
pub fn new<T: Into<Vec<u8>>>(value: T) -> Self {
Self(value.into())
}
}
#[derive(Debug, thiserror::Error)]
pub enum XmlValueSerializerError {
#[error("Custom error: {0}")]
Custom(String),
#[error("Unexpected serialization: {0}")]
UnexpectedSerialize(ser::Unexpected),
}
impl ser::Error for XmlValueSerializerError {
fn unexpected_serialize(unexpected: ser::Unexpected) -> Self {
Self::UnexpectedSerialize(unexpected)
}
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
Self::Custom(msg.to_string())
}
}
#[derive(Debug, thiserror::Error)]
pub enum XmlValueDeserializerError {
#[error("Unexpected visit: {0}")]
UnexpectedVisit(crate::de::Unexpected),
#[error("Custom error: {0}")]
Custom(String),
#[error("Wrong name: {actual:?}, expected: {expected:?}")]
WrongName {
actual: Box<ExpandedNameBuf>,
expected: Box<ExpandedNameBuf>,
},
#[error("Missing field: {0}")]
MissingField(String),
#[error("Unknown child")]
UnknownChild,
#[error("Invalid string")]
InvalidString,
#[error("No possible variant")]
NoPossibleVariant {
ident: String,
},
#[error("Missing data")]
MissingData,
}
impl de::Error for XmlValueDeserializerError {
fn custom<T>(msg: T) -> Self
where
T: std::fmt::Display,
{
Self::Custom(msg.to_string())
}
fn wrong_name(name: &ExpandedName<'_>, expected: &ExpandedName<'_>) -> Self {
Self::WrongName {
actual: Box::new(name.into_owned()),
expected: Box::new(expected.into_owned()),
}
}
fn unexpected_visit<T>(unexpected: de::Unexpected, _expected: &T) -> Self {
Self::UnexpectedVisit(unexpected)
}
fn missing_field(field: &str) -> Self {
Self::MissingField(field.to_string())
}
fn no_possible_variant(ident: &str) -> Self {
Self::NoPossibleVariant {
ident: ident.to_string(),
}
}
fn missing_data() -> Self {
Self::MissingData
}
fn unknown_child() -> Self {
Self::UnknownChild
}
fn invalid_string() -> Self {
Self::InvalidString
}
}