pub mod attributes;
#[cfg(feature = "encoding")]
use encoding_rs::Encoding;
use std::borrow::Cow;
use std::fmt::{self, Debug, Formatter};
use std::iter::FusedIterator;
use std::mem::replace;
use std::ops::Deref;
use std::str::from_utf8;
use crate::encoding::{Decoder, EncodingError};
use crate::errors::{Error, IllFormedError};
use crate::escape::{
escape, minimal_escape, normalize_xml10_eols, normalize_xml11_eols, parse_number,
partial_escape, EscapeError,
};
use crate::name::{LocalName, QName};
use crate::utils::{self, name_len, trim_xml_end, trim_xml_start, write_cow_string};
use attributes::{AttrError, Attribute, Attributes};
#[derive(Clone, Eq, PartialEq)]
pub struct BytesStart<'a> {
pub(crate) buf: Cow<'a, [u8]>,
pub(crate) name_len: usize,
decoder: Decoder,
}
impl<'a> BytesStart<'a> {
#[inline]
pub(crate) const fn wrap(content: &'a [u8], name_len: usize, decoder: Decoder) -> Self {
BytesStart {
buf: Cow::Borrowed(content),
name_len,
decoder,
}
}
#[inline]
pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
let buf = str_cow_to_bytes(name);
BytesStart {
name_len: buf.len(),
buf,
decoder: Decoder::utf8(),
}
}
#[inline]
pub fn from_content<C: Into<Cow<'a, str>>>(content: C, name_len: usize) -> Self {
BytesStart {
buf: str_cow_to_bytes(content),
name_len,
decoder: Decoder::utf8(),
}
}
pub fn into_owned(self) -> BytesStart<'static> {
BytesStart {
buf: Cow::Owned(self.buf.into_owned()),
name_len: self.name_len,
decoder: self.decoder,
}
}
pub fn to_owned(&self) -> BytesStart<'static> {
BytesStart {
buf: Cow::Owned(self.buf.clone().into_owned()),
name_len: self.name_len,
decoder: self.decoder,
}
}
pub fn borrow(&self) -> BytesStart<'_> {
BytesStart {
buf: Cow::Borrowed(&self.buf),
name_len: self.name_len,
decoder: self.decoder,
}
}
#[inline]
pub fn to_end(&self) -> BytesEnd<'_> {
BytesEnd::from(self.name())
}
#[inline]
pub const fn decoder(&self) -> Decoder {
self.decoder
}
#[inline]
pub fn name(&self) -> QName<'_> {
QName(&self.buf[..self.name_len])
}
#[inline]
pub fn local_name(&self) -> LocalName<'_> {
self.name().into()
}
pub fn set_name(&mut self, name: &[u8]) -> &mut BytesStart<'a> {
let bytes = self.buf.to_mut();
bytes.splice(..self.name_len, name.iter().cloned());
self.name_len = name.len();
self
}
}
impl<'a> BytesStart<'a> {
pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
where
I: IntoIterator,
I::Item: Into<Attribute<'b>>,
{
self.extend_attributes(attributes);
self
}
pub fn extend_attributes<'b, I>(&mut self, attributes: I) -> &mut BytesStart<'a>
where
I: IntoIterator,
I::Item: Into<Attribute<'b>>,
{
for attr in attributes {
self.push_attribute(attr);
}
self
}
pub fn push_attribute<'b, A>(&mut self, attr: A)
where
A: Into<Attribute<'b>>,
{
self.buf.to_mut().push(b' ');
self.push_attr(attr.into());
}
pub fn clear_attributes(&mut self) -> &mut BytesStart<'a> {
self.buf.to_mut().truncate(self.name_len);
self
}
pub fn attributes(&self) -> Attributes<'_> {
Attributes::wrap(&self.buf, self.name_len, false, self.decoder)
}
pub fn html_attributes(&self) -> Attributes<'_> {
Attributes::wrap(&self.buf, self.name_len, true, self.decoder)
}
#[inline]
pub fn attributes_raw(&self) -> &[u8] {
&self.buf[self.name_len..]
}
pub fn try_get_attribute<N: AsRef<[u8]> + Sized>(
&'a self,
attr_name: N,
) -> Result<Option<Attribute<'a>>, AttrError> {
for a in self.attributes().with_checks(false) {
let a = a?;
if a.key.as_ref() == attr_name.as_ref() {
return Ok(Some(a));
}
}
Ok(None)
}
pub(crate) fn push_attr<'b>(&mut self, attr: Attribute<'b>) {
let bytes = self.buf.to_mut();
bytes.extend_from_slice(attr.key.as_ref());
bytes.extend_from_slice(b"=\"");
bytes.extend_from_slice(attr.value.as_ref());
bytes.push(b'"');
}
pub(crate) fn push_newline(&mut self) {
self.buf.to_mut().push(b'\n');
}
pub(crate) fn push_indent(&mut self, indent: &[u8]) {
self.buf.to_mut().extend_from_slice(indent);
}
}
impl<'a> Debug for BytesStart<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesStart {{ buf: ")?;
write_cow_string(f, &self.buf)?;
write!(f, ", name_len: {} }}", self.name_len)
}
}
impl<'a> Deref for BytesStart<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.buf
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesStart<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let s = <&str>::arbitrary(u)?;
if s.is_empty() || !s.chars().all(char::is_alphanumeric) {
return Err(arbitrary::Error::IncorrectFormat);
}
let mut result = Self::new(s);
result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?);
Ok(result)
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct BytesEnd<'a> {
name: Cow<'a, [u8]>,
}
impl<'a> BytesEnd<'a> {
#[inline]
pub(crate) const fn wrap(name: Cow<'a, [u8]>) -> Self {
BytesEnd { name }
}
#[inline]
pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
Self::wrap(str_cow_to_bytes(name))
}
pub fn into_owned(self) -> BytesEnd<'static> {
BytesEnd {
name: Cow::Owned(self.name.into_owned()),
}
}
#[inline]
pub fn borrow(&self) -> BytesEnd<'_> {
BytesEnd {
name: Cow::Borrowed(&self.name),
}
}
#[inline]
pub fn name(&self) -> QName<'_> {
QName(&self.name)
}
#[inline]
pub fn local_name(&self) -> LocalName<'_> {
self.name().into()
}
}
impl<'a> Debug for BytesEnd<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesEnd {{ name: ")?;
write_cow_string(f, &self.name)?;
write!(f, " }}")
}
}
impl<'a> Deref for BytesEnd<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.name
}
}
impl<'a> From<QName<'a>> for BytesEnd<'a> {
#[inline]
fn from(name: QName<'a>) -> Self {
Self::wrap(name.into_inner().into())
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesEnd<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self::new(<&str>::arbitrary(u)?))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct BytesText<'a> {
content: Cow<'a, [u8]>,
decoder: Decoder,
}
impl<'a> BytesText<'a> {
#[inline]
pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
Self {
content: content.into(),
decoder,
}
}
#[inline]
pub fn from_escaped<C: Into<Cow<'a, str>>>(content: C) -> Self {
Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
}
#[inline]
pub fn new(content: &'a str) -> Self {
Self::from_escaped(escape(content))
}
#[inline]
pub fn into_owned(self) -> BytesText<'static> {
BytesText {
content: self.content.into_owned().into(),
decoder: self.decoder,
}
}
#[inline]
pub fn into_inner(self) -> Cow<'a, [u8]> {
self.content
}
#[inline]
pub fn borrow(&self) -> BytesText<'_> {
BytesText {
content: Cow::Borrowed(&self.content),
decoder: self.decoder,
}
}
pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.decode_cow(&self.content)
}
pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml10_eols)
}
pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml11_eols)
}
#[inline]
pub fn xml_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml11_content()
}
#[inline]
pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml10_content()
}
pub fn inplace_trim_start(&mut self) -> bool {
self.content = trim_cow(
replace(&mut self.content, Cow::Borrowed(b"")),
trim_xml_start,
);
self.content.is_empty()
}
pub fn inplace_trim_end(&mut self) -> bool {
self.content = trim_cow(replace(&mut self.content, Cow::Borrowed(b"")), trim_xml_end);
self.content.is_empty()
}
}
impl<'a> Debug for BytesText<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesText {{ content: ")?;
write_cow_string(f, &self.content)?;
write!(f, " }}")
}
}
impl<'a> Deref for BytesText<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.content
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesText<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let s = <&str>::arbitrary(u)?;
if !s.chars().all(char::is_alphanumeric) {
return Err(arbitrary::Error::IncorrectFormat);
}
Ok(Self::new(s))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct BytesCData<'a> {
content: Cow<'a, [u8]>,
decoder: Decoder,
}
impl<'a> BytesCData<'a> {
#[inline]
pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
Self {
content: content.into(),
decoder,
}
}
#[inline]
pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
}
#[inline]
pub fn escaped(content: &'a str) -> CDataIterator<'a> {
CDataIterator {
inner: utils::CDataIterator::new(content),
}
}
#[inline]
pub fn into_owned(self) -> BytesCData<'static> {
BytesCData {
content: self.content.into_owned().into(),
decoder: self.decoder,
}
}
#[inline]
pub fn into_inner(self) -> Cow<'a, [u8]> {
self.content
}
#[inline]
pub fn borrow(&self) -> BytesCData<'_> {
BytesCData {
content: Cow::Borrowed(&self.content),
decoder: self.decoder,
}
}
pub fn escape(self) -> Result<BytesText<'a>, EncodingError> {
let decoded = self.decode()?;
Ok(BytesText::wrap(
match escape(decoded) {
Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
},
Decoder::utf8(),
))
}
pub fn partial_escape(self) -> Result<BytesText<'a>, EncodingError> {
let decoded = self.decode()?;
Ok(BytesText::wrap(
match partial_escape(decoded) {
Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
},
Decoder::utf8(),
))
}
pub fn minimal_escape(self) -> Result<BytesText<'a>, EncodingError> {
let decoded = self.decode()?;
Ok(BytesText::wrap(
match minimal_escape(decoded) {
Cow::Borrowed(escaped) => Cow::Borrowed(escaped.as_bytes()),
Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
},
Decoder::utf8(),
))
}
pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.decode_cow(&self.content)
}
pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml10_eols)
}
pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml11_eols)
}
#[inline]
pub fn xml_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml11_content()
}
#[inline]
pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml10_content()
}
}
impl<'a> Debug for BytesCData<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesCData {{ content: ")?;
write_cow_string(f, &self.content)?;
write!(f, " }}")
}
}
impl<'a> Deref for BytesCData<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.content
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesCData<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self::new(<&str>::arbitrary(u)?))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Debug, Clone)]
pub struct CDataIterator<'a> {
inner: utils::CDataIterator<'a>,
}
impl<'a> Iterator for CDataIterator<'a> {
type Item = BytesCData<'a>;
fn next(&mut self) -> Option<BytesCData<'a>> {
self.inner
.next()
.map(|slice| BytesCData::wrap(slice.as_bytes(), Decoder::utf8()))
}
}
impl FusedIterator for CDataIterator<'_> {}
#[derive(Clone, Eq, PartialEq)]
pub struct BytesPI<'a> {
content: BytesStart<'a>,
}
impl<'a> BytesPI<'a> {
#[inline]
pub(crate) const fn wrap(content: &'a [u8], target_len: usize, decoder: Decoder) -> Self {
Self {
content: BytesStart::wrap(content, target_len, decoder),
}
}
#[inline]
pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
let buf = str_cow_to_bytes(content);
let name_len = name_len(&buf);
Self {
content: BytesStart {
buf,
name_len,
decoder: Decoder::utf8(),
},
}
}
#[inline]
pub fn into_owned(self) -> BytesPI<'static> {
BytesPI {
content: self.content.into_owned(),
}
}
#[inline]
pub fn into_inner(self) -> Cow<'a, [u8]> {
self.content.buf
}
#[inline]
pub fn borrow(&self) -> BytesPI<'_> {
BytesPI {
content: self.content.borrow(),
}
}
#[inline]
pub fn target(&self) -> &[u8] {
self.content.name().0
}
#[inline]
pub fn content(&self) -> &[u8] {
self.content.attributes_raw()
}
#[inline]
pub fn attributes(&self) -> Attributes<'_> {
self.content.attributes()
}
}
impl<'a> Debug for BytesPI<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesPI {{ content: ")?;
write_cow_string(f, &self.content.buf)?;
write!(f, " }}")
}
}
impl<'a> Deref for BytesPI<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.content
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesPI<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self::new(<&str>::arbitrary(u)?))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BytesDecl<'a> {
content: BytesStart<'a>,
}
impl<'a> BytesDecl<'a> {
pub fn new(
version: &str,
encoding: Option<&str>,
standalone: Option<&str>,
) -> BytesDecl<'static> {
let encoding_attr_len = if let Some(xs) = encoding {
12 + xs.len()
} else {
0
};
let standalone_attr_len = if let Some(xs) = standalone {
14 + xs.len()
} else {
0
};
let mut buf = String::with_capacity(14 + encoding_attr_len + standalone_attr_len);
buf.push_str("xml version=\"");
buf.push_str(version);
if let Some(encoding_val) = encoding {
buf.push_str("\" encoding=\"");
buf.push_str(encoding_val);
}
if let Some(standalone_val) = standalone {
buf.push_str("\" standalone=\"");
buf.push_str(standalone_val);
}
buf.push('"');
BytesDecl {
content: BytesStart::from_content(buf, 3),
}
}
pub const fn from_start(start: BytesStart<'a>) -> Self {
Self { content: start }
}
pub fn version(&self) -> Result<Cow<'_, [u8]>, Error> {
match self.content.attributes().with_checks(false).next() {
Some(Ok(a)) if a.key.as_ref() == b"version" => Ok(a.value),
Some(Ok(a)) => {
let found = from_utf8(a.key.as_ref())
.map_err(|_| IllFormedError::MissingDeclVersion(None))?
.to_string();
Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(
found,
))))
}
Some(Err(e)) => Err(e.into()),
None => Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))),
}
}
pub fn encoding(&self) -> Option<Result<Cow<'_, [u8]>, AttrError>> {
self.content
.try_get_attribute("encoding")
.map(|a| a.map(|a| a.value))
.transpose()
}
pub fn standalone(&self) -> Option<Result<Cow<'_, [u8]>, AttrError>> {
self.content
.try_get_attribute("standalone")
.map(|a| a.map(|a| a.value))
.transpose()
}
#[cfg(feature = "encoding")]
pub fn encoder(&self) -> Option<&'static Encoding> {
self.encoding()
.and_then(|e| e.ok())
.and_then(|e| Encoding::for_label(&e))
}
pub fn into_owned(self) -> BytesDecl<'static> {
BytesDecl {
content: self.content.into_owned(),
}
}
#[inline]
pub fn borrow(&self) -> BytesDecl<'_> {
BytesDecl {
content: self.content.borrow(),
}
}
}
impl<'a> Deref for BytesDecl<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.content
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesDecl<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self::new(
<&str>::arbitrary(u)?,
Option::<&str>::arbitrary(u)?,
Option::<&str>::arbitrary(u)?,
))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct BytesRef<'a> {
content: Cow<'a, [u8]>,
decoder: Decoder,
}
impl<'a> BytesRef<'a> {
#[inline]
pub(crate) const fn wrap(content: &'a [u8], decoder: Decoder) -> Self {
Self {
content: Cow::Borrowed(content),
decoder,
}
}
#[inline]
pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
Self {
content: str_cow_to_bytes(name),
decoder: Decoder::utf8(),
}
}
pub fn into_owned(self) -> BytesRef<'static> {
BytesRef {
content: Cow::Owned(self.content.into_owned()),
decoder: self.decoder,
}
}
#[inline]
pub fn into_inner(self) -> Cow<'a, [u8]> {
self.content
}
#[inline]
pub fn borrow(&self) -> BytesRef<'_> {
BytesRef {
content: Cow::Borrowed(&self.content),
decoder: self.decoder,
}
}
pub fn decode(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.decode_cow(&self.content)
}
pub fn xml10_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml10_eols)
}
pub fn xml11_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.decoder.content(&self.content, normalize_xml11_eols)
}
#[inline]
pub fn xml_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml11_content()
}
#[inline]
pub fn html_content(&self) -> Result<Cow<'a, str>, EncodingError> {
self.xml10_content()
}
pub fn is_char_ref(&self) -> bool {
matches!(self.content.first(), Some(b'#'))
}
pub fn resolve_char_ref(&self) -> Result<Option<char>, Error> {
if let Some(num) = self.decode()?.strip_prefix('#') {
let ch = parse_number(num).map_err(EscapeError::InvalidCharRef)?;
return Ok(Some(ch));
}
Ok(None)
}
}
impl<'a> Debug for BytesRef<'a> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "BytesRef {{ content: ")?;
write_cow_string(f, &self.content)?;
write!(f, " }}")
}
}
impl<'a> Deref for BytesRef<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.content
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for BytesRef<'a> {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(Self::new(<&str>::arbitrary(u)?))
}
fn size_hint(depth: usize) -> (usize, Option<usize>) {
<&str as arbitrary::Arbitrary>::size_hint(depth)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum Event<'a> {
Start(BytesStart<'a>),
End(BytesEnd<'a>),
Empty(BytesStart<'a>),
Text(BytesText<'a>),
CData(BytesCData<'a>),
Comment(BytesText<'a>),
Decl(BytesDecl<'a>),
PI(BytesPI<'a>),
DocType(BytesText<'a>),
GeneralRef(BytesRef<'a>),
Eof,
}
impl<'a> Event<'a> {
pub fn into_owned(self) -> Event<'static> {
match self {
Event::Start(e) => Event::Start(e.into_owned()),
Event::End(e) => Event::End(e.into_owned()),
Event::Empty(e) => Event::Empty(e.into_owned()),
Event::Text(e) => Event::Text(e.into_owned()),
Event::Comment(e) => Event::Comment(e.into_owned()),
Event::CData(e) => Event::CData(e.into_owned()),
Event::Decl(e) => Event::Decl(e.into_owned()),
Event::PI(e) => Event::PI(e.into_owned()),
Event::DocType(e) => Event::DocType(e.into_owned()),
Event::GeneralRef(e) => Event::GeneralRef(e.into_owned()),
Event::Eof => Event::Eof,
}
}
#[inline]
pub fn borrow(&self) -> Event<'_> {
match self {
Event::Start(e) => Event::Start(e.borrow()),
Event::End(e) => Event::End(e.borrow()),
Event::Empty(e) => Event::Empty(e.borrow()),
Event::Text(e) => Event::Text(e.borrow()),
Event::Comment(e) => Event::Comment(e.borrow()),
Event::CData(e) => Event::CData(e.borrow()),
Event::Decl(e) => Event::Decl(e.borrow()),
Event::PI(e) => Event::PI(e.borrow()),
Event::DocType(e) => Event::DocType(e.borrow()),
Event::GeneralRef(e) => Event::GeneralRef(e.borrow()),
Event::Eof => Event::Eof,
}
}
}
impl<'a> Deref for Event<'a> {
type Target = [u8];
fn deref(&self) -> &[u8] {
match *self {
Event::Start(ref e) | Event::Empty(ref e) => e,
Event::End(ref e) => e,
Event::Text(ref e) => e,
Event::Decl(ref e) => e,
Event::PI(ref e) => e,
Event::CData(ref e) => e,
Event::Comment(ref e) => e,
Event::DocType(ref e) => e,
Event::GeneralRef(ref e) => e,
Event::Eof => &[],
}
}
}
impl<'a> AsRef<Event<'a>> for Event<'a> {
fn as_ref(&self) -> &Event<'a> {
self
}
}
#[inline]
fn str_cow_to_bytes<'a, C: Into<Cow<'a, str>>>(content: C) -> Cow<'a, [u8]> {
match content.into() {
Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
Cow::Owned(s) => Cow::Owned(s.into_bytes()),
}
}
fn trim_cow<'a, F>(value: Cow<'a, [u8]>, trim: F) -> Cow<'a, [u8]>
where
F: FnOnce(&[u8]) -> &[u8],
{
match value {
Cow::Borrowed(bytes) => Cow::Borrowed(trim(bytes)),
Cow::Owned(mut bytes) => {
let trimmed = trim(&bytes);
if trimmed.len() != bytes.len() {
bytes = trimmed.to_vec();
}
Cow::Owned(bytes)
}
}
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn bytestart_create() {
let b = BytesStart::new("test");
assert_eq!(b.len(), 4);
assert_eq!(b.name(), QName(b"test"));
}
#[test]
fn bytestart_set_name() {
let mut b = BytesStart::new("test");
assert_eq!(b.len(), 4);
assert_eq!(b.name(), QName(b"test"));
assert_eq!(b.attributes_raw(), b"");
b.push_attribute(("x", "a"));
assert_eq!(b.len(), 10);
assert_eq!(b.attributes_raw(), b" x=\"a\"");
b.set_name(b"g");
assert_eq!(b.len(), 7);
assert_eq!(b.name(), QName(b"g"));
}
#[test]
fn bytestart_clear_attributes() {
let mut b = BytesStart::new("test");
b.push_attribute(("x", "y\"z"));
b.push_attribute(("x", "y\"z"));
b.clear_attributes();
assert!(b.attributes().next().is_none());
assert_eq!(b.len(), 4);
assert_eq!(b.name(), QName(b"test"));
}
}