use std::borrow::Cow;
use crate::attribute::Attribute;
use crate::common::XmlVersion;
use crate::name::Name;
use crate::namespace::{Namespace, NS_NO_PREFIX};
use crate::reader::ErrorKind;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum XmlEvent<'a> {
StartDocument {
version: XmlVersion,
encoding: Option<&'a str>,
standalone: Option<bool>,
},
ProcessingInstruction {
name: &'a str,
data: Option<&'a str>,
},
StartElement {
name: Name<'a>,
attributes: Cow<'a, [Attribute<'a>]>,
namespace: Cow<'a, Namespace>,
},
EndElement {
name: Option<Name<'a>>,
},
CData(&'a str),
Comment(&'a str),
Characters(&'a str),
RawCharacters(&'a str),
Doctype(&'a str),
}
impl<'a> XmlEvent<'a> {
#[inline]
#[must_use]
pub const fn processing_instruction(name: &'a str, data: Option<&'a str>) -> Self {
XmlEvent::ProcessingInstruction { name, data }
}
#[inline]
pub fn start_element<S>(name: S) -> StartElementBuilder<'a> where S: Into<Name<'a>> {
StartElementBuilder {
name: name.into(),
attributes: Vec::new(),
namespace: Namespace::empty(),
}
}
#[inline]
#[must_use]
pub const fn end_element() -> EndElementBuilder<'a> {
EndElementBuilder { name: None }
}
#[inline]
#[must_use]
pub const fn cdata(data: &'a str) -> Self {
XmlEvent::CData(data)
}
#[inline]
#[must_use]
pub const fn characters(data: &'a str) -> Self {
XmlEvent::Characters(data)
}
#[inline]
#[must_use]
pub const fn raw_characters(data: &'a str) -> Self {
XmlEvent::RawCharacters(data)
}
#[inline]
#[must_use]
pub const fn comment(data: &'a str) -> Self {
XmlEvent::Comment(data)
}
}
impl<'a> From<&'a str> for XmlEvent<'a> {
#[inline]
fn from(s: &'a str) -> Self {
XmlEvent::Characters(s)
}
}
pub struct EndElementBuilder<'a> {
name: Option<Name<'a>>,
}
impl<'a> EndElementBuilder<'a> {
#[inline]
#[must_use]
pub fn name<N>(mut self, name: N) -> Self where N: Into<Name<'a>> {
self.name = Some(name.into());
self
}
}
impl<'a> From<EndElementBuilder<'a>> for XmlEvent<'a> {
fn from(b: EndElementBuilder<'a>) -> Self {
XmlEvent::EndElement { name: b.name }
}
}
pub struct StartElementBuilder<'a> {
name: Name<'a>,
attributes: Vec<Attribute<'a>>,
namespace: Namespace,
}
impl<'a> StartElementBuilder<'a> {
#[inline]
#[must_use]
pub fn attr<N>(mut self, name: N, value: &'a str) -> Self
where N: Into<Name<'a>> {
self.attributes.push(Attribute::new(name.into(), value));
self
}
#[inline]
#[must_use]
pub fn ns<S1, S2>(mut self, prefix: S1, uri: S2) -> Self
where S1: Into<String>, S2: Into<String>
{
self.namespace.put(prefix, uri);
self
}
#[inline]
#[must_use]
pub fn default_ns<S>(mut self, uri: S) -> Self
where S: Into<String> {
self.namespace.put(NS_NO_PREFIX, uri);
self
}
}
impl<'a> From<StartElementBuilder<'a>> for XmlEvent<'a> {
#[inline]
fn from(b: StartElementBuilder<'a>) -> Self {
XmlEvent::StartElement {
name: b.name,
attributes: Cow::Owned(b.attributes),
namespace: Cow::Owned(b.namespace),
}
}
}
impl<'a> TryFrom<&'a crate::reader::XmlEvent> for XmlEvent<'a> {
type Error = crate::reader::Error;
fn try_from(event: &crate::reader::XmlEvent) -> Result<XmlEvent<'_>, Self::Error> {
Ok(event.as_writer_event().ok_or(ErrorKind::UnexpectedEof)?)
}
}