quick_xml/events/
mod.rs

1//! Defines zero-copy XML events used throughout this library.
2//!
3//! A XML event often represents part of a XML element.
4//! They occur both during reading and writing and are
5//! usually used with the stream-oriented API.
6//!
7//! For example, the XML element
8//! ```xml
9//! <name attr="value">Inner text</name>
10//! ```
11//! consists of the three events `Start`, `Text` and `End`.
12//! They can also represent other parts in an XML document like the
13//! XML declaration. Each Event usually contains further information,
14//! like the tag name, the attribute or the inner text.
15//!
16//! See [`Event`] for a list of all possible events.
17//!
18//! # Reading
19//! When reading a XML stream, the events are emitted by [`Reader::read_event`]
20//! and [`Reader::read_event_into`]. You must listen
21//! for the different types of events you are interested in.
22//!
23//! See [`Reader`] for further information.
24//!
25//! # Writing
26//! When writing the XML document, you must create the XML element
27//! by constructing the events it consists of and pass them to the writer
28//! sequentially.
29//!
30//! See [`Writer`] for further information.
31//!
32//! [`Reader::read_event`]: crate::reader::Reader::read_event
33//! [`Reader::read_event_into`]: crate::reader::Reader::read_event_into
34//! [`Reader`]: crate::reader::Reader
35//! [`Writer`]: crate::writer::Writer
36//! [`Event`]: crate::events::Event
37
38pub mod attributes;
39
40#[cfg(feature = "encoding")]
41use encoding_rs::Encoding;
42use std::borrow::Cow;
43use std::fmt::{self, Debug, Formatter};
44use std::mem::replace;
45use std::ops::Deref;
46use std::str::from_utf8;
47
48use crate::encoding::Decoder;
49use crate::errors::{Error, IllFormedError, Result};
50use crate::escape::{
51    escape, minimal_escape, partial_escape, resolve_predefined_entity, unescape_with,
52};
53use crate::name::{LocalName, QName};
54#[cfg(feature = "serialize")]
55use crate::utils::CowRef;
56use crate::utils::{name_len, trim_xml_end, trim_xml_start, write_cow_string};
57use attributes::{Attribute, Attributes};
58
59/// Opening tag data (`Event::Start`), with optional attributes: `<name attr="value">`.
60///
61/// The name can be accessed using the [`name`] or [`local_name`] methods.
62/// An iterator over the attributes is returned by the [`attributes`] method.
63///
64/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
65/// returns the content of this event between `<` and `>` or `/>`:
66///
67/// ```
68/// # use quick_xml::events::{BytesStart, Event};
69/// # use quick_xml::reader::Reader;
70/// # use pretty_assertions::assert_eq;
71/// // Remember, that \ at the end of string literal strips
72/// // all space characters to the first non-space character
73/// let mut reader = Reader::from_str("\
74///     <element a1 = 'val1' a2=\"val2\" />\
75///     <element a1 = 'val1' a2=\"val2\" >"
76/// );
77/// let content = "element a1 = 'val1' a2=\"val2\" ";
78/// let event = BytesStart::from_content(content, 7);
79///
80/// assert_eq!(reader.read_event().unwrap(), Event::Empty(event.borrow()));
81/// assert_eq!(reader.read_event().unwrap(), Event::Start(event.borrow()));
82/// // deref coercion of &BytesStart to &[u8]
83/// assert_eq!(&event as &[u8], content.as_bytes());
84/// // AsRef<[u8]> for &T + deref coercion
85/// assert_eq!(event.as_ref(), content.as_bytes());
86/// ```
87///
88/// [`name`]: Self::name
89/// [`local_name`]: Self::local_name
90/// [`attributes`]: Self::attributes
91#[derive(Clone, Eq, PartialEq)]
92pub struct BytesStart<'a> {
93    /// content of the element, before any utf8 conversion
94    pub(crate) buf: Cow<'a, [u8]>,
95    /// end of the element name, the name starts at that the start of `buf`
96    pub(crate) name_len: usize,
97}
98
99impl<'a> BytesStart<'a> {
100    /// Internal constructor, used by `Reader`. Supplies data in reader's encoding
101    #[inline]
102    pub(crate) const fn wrap(content: &'a [u8], name_len: usize) -> Self {
103        BytesStart {
104            buf: Cow::Borrowed(content),
105            name_len,
106        }
107    }
108
109    /// Creates a new `BytesStart` from the given name.
110    ///
111    /// # Warning
112    ///
113    /// `name` must be a valid name.
114    #[inline]
115    pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
116        let buf = str_cow_to_bytes(name);
117        BytesStart {
118            name_len: buf.len(),
119            buf,
120        }
121    }
122
123    /// Creates a new `BytesStart` from the given content (name + attributes).
124    ///
125    /// # Warning
126    ///
127    /// `&content[..name_len]` must be a valid name, and the remainder of `content`
128    /// must be correctly-formed attributes. Neither are checked, it is possible
129    /// to generate invalid XML if `content` or `name_len` are incorrect.
130    #[inline]
131    pub fn from_content<C: Into<Cow<'a, str>>>(content: C, name_len: usize) -> Self {
132        BytesStart {
133            buf: str_cow_to_bytes(content),
134            name_len,
135        }
136    }
137
138    /// Converts the event into an owned event.
139    pub fn into_owned(self) -> BytesStart<'static> {
140        BytesStart {
141            buf: Cow::Owned(self.buf.into_owned()),
142            name_len: self.name_len,
143        }
144    }
145
146    /// Converts the event into an owned event without taking ownership of Event
147    pub fn to_owned(&self) -> BytesStart<'static> {
148        BytesStart {
149            buf: Cow::Owned(self.buf.clone().into_owned()),
150            name_len: self.name_len,
151        }
152    }
153
154    /// Converts the event into a borrowed event. Most useful when paired with [`to_end`].
155    ///
156    /// # Example
157    ///
158    /// ```
159    /// use quick_xml::events::{BytesStart, Event};
160    /// # use quick_xml::writer::Writer;
161    /// # use quick_xml::Error;
162    ///
163    /// struct SomeStruct<'a> {
164    ///     attrs: BytesStart<'a>,
165    ///     // ...
166    /// }
167    /// # impl<'a> SomeStruct<'a> {
168    /// # fn example(&self) -> Result<(), Error> {
169    /// # let mut writer = Writer::new(Vec::new());
170    ///
171    /// writer.write_event(Event::Start(self.attrs.borrow()))?;
172    /// // ...
173    /// writer.write_event(Event::End(self.attrs.to_end()))?;
174    /// # Ok(())
175    /// # }}
176    /// ```
177    ///
178    /// [`to_end`]: Self::to_end
179    pub fn borrow(&self) -> BytesStart {
180        BytesStart {
181            buf: Cow::Borrowed(&self.buf),
182            name_len: self.name_len,
183        }
184    }
185
186    /// Creates new paired close tag
187    #[inline]
188    pub fn to_end(&self) -> BytesEnd {
189        BytesEnd::from(self.name())
190    }
191
192    /// Gets the undecoded raw tag name, as present in the input stream.
193    #[inline]
194    pub fn name(&self) -> QName {
195        QName(&self.buf[..self.name_len])
196    }
197
198    /// Gets the undecoded raw local tag name (excluding namespace) as present
199    /// in the input stream.
200    ///
201    /// All content up to and including the first `:` character is removed from the tag name.
202    #[inline]
203    pub fn local_name(&self) -> LocalName {
204        self.name().into()
205    }
206
207    /// Edit the name of the BytesStart in-place
208    ///
209    /// # Warning
210    ///
211    /// `name` must be a valid name.
212    pub fn set_name(&mut self, name: &[u8]) -> &mut BytesStart<'a> {
213        let bytes = self.buf.to_mut();
214        bytes.splice(..self.name_len, name.iter().cloned());
215        self.name_len = name.len();
216        self
217    }
218
219    /// Gets the undecoded raw tag name, as present in the input stream, which
220    /// is borrowed either to the input, or to the event.
221    ///
222    /// # Lifetimes
223    ///
224    /// - `'a`: Lifetime of the input data from which this event is borrow
225    /// - `'e`: Lifetime of the concrete event instance
226    // TODO: We should made this is a part of public API, but with safe wrapped for a name
227    #[cfg(feature = "serialize")]
228    pub(crate) fn raw_name<'e>(&'e self) -> CowRef<'a, 'e, [u8]> {
229        match self.buf {
230            Cow::Borrowed(b) => CowRef::Input(&b[..self.name_len]),
231            Cow::Owned(ref o) => CowRef::Slice(&o[..self.name_len]),
232        }
233    }
234}
235
236/// Attribute-related methods
237impl<'a> BytesStart<'a> {
238    /// Consumes `self` and yield a new `BytesStart` with additional attributes from an iterator.
239    ///
240    /// The yielded items must be convertible to [`Attribute`] using `Into`.
241    pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
242    where
243        I: IntoIterator,
244        I::Item: Into<Attribute<'b>>,
245    {
246        self.extend_attributes(attributes);
247        self
248    }
249
250    /// Add additional attributes to this tag using an iterator.
251    ///
252    /// The yielded items must be convertible to [`Attribute`] using `Into`.
253    pub fn extend_attributes<'b, I>(&mut self, attributes: I) -> &mut BytesStart<'a>
254    where
255        I: IntoIterator,
256        I::Item: Into<Attribute<'b>>,
257    {
258        for attr in attributes {
259            self.push_attribute(attr);
260        }
261        self
262    }
263
264    /// Adds an attribute to this element.
265    pub fn push_attribute<'b, A>(&mut self, attr: A)
266    where
267        A: Into<Attribute<'b>>,
268    {
269        self.buf.to_mut().push(b' ');
270        self.push_attr(attr.into());
271    }
272
273    /// Remove all attributes from the ByteStart
274    pub fn clear_attributes(&mut self) -> &mut BytesStart<'a> {
275        self.buf.to_mut().truncate(self.name_len);
276        self
277    }
278
279    /// Returns an iterator over the attributes of this tag.
280    pub fn attributes(&self) -> Attributes {
281        Attributes::wrap(&self.buf, self.name_len, false)
282    }
283
284    /// Returns an iterator over the HTML-like attributes of this tag (no mandatory quotes or `=`).
285    pub fn html_attributes(&self) -> Attributes {
286        Attributes::wrap(&self.buf, self.name_len, true)
287    }
288
289    /// Gets the undecoded raw string with the attributes of this tag as a `&[u8]`,
290    /// including the whitespace after the tag name if there is any.
291    #[inline]
292    pub fn attributes_raw(&self) -> &[u8] {
293        &self.buf[self.name_len..]
294    }
295
296    /// Try to get an attribute
297    pub fn try_get_attribute<N: AsRef<[u8]> + Sized>(
298        &'a self,
299        attr_name: N,
300    ) -> Result<Option<Attribute<'a>>> {
301        for a in self.attributes().with_checks(false) {
302            let a = a?;
303            if a.key.as_ref() == attr_name.as_ref() {
304                return Ok(Some(a));
305            }
306        }
307        Ok(None)
308    }
309
310    /// Adds an attribute to this element.
311    pub(crate) fn push_attr<'b>(&mut self, attr: Attribute<'b>) {
312        let bytes = self.buf.to_mut();
313        bytes.extend_from_slice(attr.key.as_ref());
314        bytes.extend_from_slice(b"=\"");
315        // FIXME: need to escape attribute content
316        bytes.extend_from_slice(attr.value.as_ref());
317        bytes.push(b'"');
318    }
319
320    /// Adds new line in existing element
321    pub(crate) fn push_newline(&mut self) {
322        self.buf.to_mut().push(b'\n');
323    }
324
325    /// Adds indentation bytes in existing element
326    pub(crate) fn push_indent(&mut self, indent: &[u8]) {
327        self.buf.to_mut().extend_from_slice(indent);
328    }
329}
330
331impl<'a> Debug for BytesStart<'a> {
332    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
333        write!(f, "BytesStart {{ buf: ")?;
334        write_cow_string(f, &self.buf)?;
335        write!(f, ", name_len: {} }}", self.name_len)
336    }
337}
338
339impl<'a> Deref for BytesStart<'a> {
340    type Target = [u8];
341
342    fn deref(&self) -> &[u8] {
343        &self.buf
344    }
345}
346
347impl<'a> From<QName<'a>> for BytesStart<'a> {
348    #[inline]
349    fn from(name: QName<'a>) -> Self {
350        let name = name.into_inner();
351        Self::wrap(name, name.len())
352    }
353}
354
355#[cfg(feature = "arbitrary")]
356impl<'a> arbitrary::Arbitrary<'a> for BytesStart<'a> {
357    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
358        let s = <&str>::arbitrary(u)?;
359        if s.is_empty() || !s.chars().all(char::is_alphanumeric) {
360            return Err(arbitrary::Error::IncorrectFormat);
361        }
362        let mut result = Self::new(s);
363        result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?.into_iter());
364        Ok(result)
365    }
366
367    fn size_hint(depth: usize) -> (usize, Option<usize>) {
368        return <&str as arbitrary::Arbitrary>::size_hint(depth);
369    }
370}
371////////////////////////////////////////////////////////////////////////////////////////////////////
372
373/// Closing tag data (`Event::End`): `</name>`.
374///
375/// The name can be accessed using the [`name`] or [`local_name`] methods.
376///
377/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
378/// returns the content of this event between `</` and `>`.
379///
380/// Note, that inner text will not contain `>` character inside:
381///
382/// ```
383/// # use quick_xml::events::{BytesEnd, Event};
384/// # use quick_xml::reader::Reader;
385/// # use pretty_assertions::assert_eq;
386/// let mut reader = Reader::from_str(r#"<element></element a1 = 'val1' a2="val2" >"#);
387/// // Note, that this entire string considered as a .name()
388/// let content = "element a1 = 'val1' a2=\"val2\" ";
389/// let event = BytesEnd::new(content);
390///
391/// reader.config_mut().trim_markup_names_in_closing_tags = false;
392/// reader.config_mut().check_end_names = false;
393/// reader.read_event().unwrap(); // Skip `<element>`
394///
395/// assert_eq!(reader.read_event().unwrap(), Event::End(event.borrow()));
396/// assert_eq!(event.name().as_ref(), content.as_bytes());
397/// // deref coercion of &BytesEnd to &[u8]
398/// assert_eq!(&event as &[u8], content.as_bytes());
399/// // AsRef<[u8]> for &T + deref coercion
400/// assert_eq!(event.as_ref(), content.as_bytes());
401/// ```
402///
403/// [`name`]: Self::name
404/// [`local_name`]: Self::local_name
405#[derive(Clone, Eq, PartialEq)]
406pub struct BytesEnd<'a> {
407    name: Cow<'a, [u8]>,
408}
409
410impl<'a> BytesEnd<'a> {
411    /// Internal constructor, used by `Reader`. Supplies data in reader's encoding
412    #[inline]
413    pub(crate) const fn wrap(name: Cow<'a, [u8]>) -> Self {
414        BytesEnd { name }
415    }
416
417    /// Creates a new `BytesEnd` borrowing a slice.
418    ///
419    /// # Warning
420    ///
421    /// `name` must be a valid name.
422    #[inline]
423    pub fn new<C: Into<Cow<'a, str>>>(name: C) -> Self {
424        Self::wrap(str_cow_to_bytes(name))
425    }
426
427    /// Converts the event into an owned event.
428    pub fn into_owned(self) -> BytesEnd<'static> {
429        BytesEnd {
430            name: Cow::Owned(self.name.into_owned()),
431        }
432    }
433
434    /// Converts the event into a borrowed event.
435    #[inline]
436    pub fn borrow(&self) -> BytesEnd {
437        BytesEnd {
438            name: Cow::Borrowed(&self.name),
439        }
440    }
441
442    /// Gets the undecoded raw tag name, as present in the input stream.
443    #[inline]
444    pub fn name(&self) -> QName {
445        QName(&self.name)
446    }
447
448    /// Gets the undecoded raw local tag name (excluding namespace) as present
449    /// in the input stream.
450    ///
451    /// All content up to and including the first `:` character is removed from the tag name.
452    #[inline]
453    pub fn local_name(&self) -> LocalName {
454        self.name().into()
455    }
456}
457
458impl<'a> Debug for BytesEnd<'a> {
459    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
460        write!(f, "BytesEnd {{ name: ")?;
461        write_cow_string(f, &self.name)?;
462        write!(f, " }}")
463    }
464}
465
466impl<'a> Deref for BytesEnd<'a> {
467    type Target = [u8];
468
469    fn deref(&self) -> &[u8] {
470        &self.name
471    }
472}
473
474impl<'a> From<QName<'a>> for BytesEnd<'a> {
475    #[inline]
476    fn from(name: QName<'a>) -> Self {
477        Self::wrap(name.into_inner().into())
478    }
479}
480
481#[cfg(feature = "arbitrary")]
482impl<'a> arbitrary::Arbitrary<'a> for BytesEnd<'a> {
483    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
484        Ok(Self::new(<&str>::arbitrary(u)?))
485    }
486    fn size_hint(depth: usize) -> (usize, Option<usize>) {
487        return <&str as arbitrary::Arbitrary>::size_hint(depth);
488    }
489}
490
491////////////////////////////////////////////////////////////////////////////////////////////////////
492
493/// Data from various events (most notably, `Event::Text`) that stored in XML
494/// in escaped form. Internally data is stored in escaped form.
495///
496/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
497/// returns the content of this event. In case of comment this is everything
498/// between `<!--` and `-->` and the text of comment will not contain `-->` inside.
499/// In case of DTD this is everything between `<!DOCTYPE` + spaces and closing `>`
500/// (i.e. in case of DTD the first character is never space):
501///
502/// ```
503/// # use quick_xml::events::{BytesText, Event};
504/// # use quick_xml::reader::Reader;
505/// # use pretty_assertions::assert_eq;
506/// // Remember, that \ at the end of string literal strips
507/// // all space characters to the first non-space character
508/// let mut reader = Reader::from_str("\
509///     <!DOCTYPE comment or text >\
510///     comment or text \
511///     <!--comment or text -->"
512/// );
513/// let content = "comment or text ";
514/// let event = BytesText::new(content);
515///
516/// assert_eq!(reader.read_event().unwrap(), Event::DocType(event.borrow()));
517/// assert_eq!(reader.read_event().unwrap(), Event::Text(event.borrow()));
518/// assert_eq!(reader.read_event().unwrap(), Event::Comment(event.borrow()));
519/// // deref coercion of &BytesText to &[u8]
520/// assert_eq!(&event as &[u8], content.as_bytes());
521/// // AsRef<[u8]> for &T + deref coercion
522/// assert_eq!(event.as_ref(), content.as_bytes());
523/// ```
524#[derive(Clone, Eq, PartialEq)]
525pub struct BytesText<'a> {
526    /// Escaped then encoded content of the event. Content is encoded in the XML
527    /// document encoding when event comes from the reader and should be in the
528    /// document encoding when event passed to the writer
529    content: Cow<'a, [u8]>,
530    /// Encoding in which the `content` is stored inside the event
531    decoder: Decoder,
532}
533
534impl<'a> BytesText<'a> {
535    /// Creates a new `BytesText` from an escaped byte sequence in the specified encoding.
536    #[inline]
537    pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
538        Self {
539            content: content.into(),
540            decoder,
541        }
542    }
543
544    /// Creates a new `BytesText` from an escaped string.
545    #[inline]
546    pub fn from_escaped<C: Into<Cow<'a, str>>>(content: C) -> Self {
547        Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
548    }
549
550    /// Creates a new `BytesText` from a string. The string is expected not to
551    /// be escaped.
552    #[inline]
553    pub fn new(content: &'a str) -> Self {
554        Self::from_escaped(escape(content))
555    }
556
557    /// Ensures that all data is owned to extend the object's lifetime if
558    /// necessary.
559    #[inline]
560    pub fn into_owned(self) -> BytesText<'static> {
561        BytesText {
562            content: self.content.into_owned().into(),
563            decoder: self.decoder,
564        }
565    }
566
567    /// Extracts the inner `Cow` from the `BytesText` event container.
568    #[inline]
569    pub fn into_inner(self) -> Cow<'a, [u8]> {
570        self.content
571    }
572
573    /// Converts the event into a borrowed event.
574    #[inline]
575    pub fn borrow(&self) -> BytesText {
576        BytesText {
577            content: Cow::Borrowed(&self.content),
578            decoder: self.decoder,
579        }
580    }
581
582    /// Decodes then unescapes the content of the event.
583    ///
584    /// This will allocate if the value contains any escape sequences or in
585    /// non-UTF-8 encoding.
586    pub fn unescape(&self) -> Result<Cow<'a, str>> {
587        self.unescape_with(resolve_predefined_entity)
588    }
589
590    /// Decodes then unescapes the content of the event with custom entities.
591    ///
592    /// This will allocate if the value contains any escape sequences or in
593    /// non-UTF-8 encoding.
594    pub fn unescape_with<'entity>(
595        &self,
596        resolve_entity: impl FnMut(&str) -> Option<&'entity str>,
597    ) -> Result<Cow<'a, str>> {
598        let decoded = self.decoder.decode_cow(&self.content)?;
599
600        match unescape_with(&decoded, resolve_entity)? {
601            // Because result is borrowed, no replacements was done and we can use original string
602            Cow::Borrowed(_) => Ok(decoded),
603            Cow::Owned(s) => Ok(s.into()),
604        }
605    }
606
607    /// Removes leading XML whitespace bytes from text content.
608    ///
609    /// Returns `true` if content is empty after that
610    pub fn inplace_trim_start(&mut self) -> bool {
611        self.content = trim_cow(
612            replace(&mut self.content, Cow::Borrowed(b"")),
613            trim_xml_start,
614        );
615        self.content.is_empty()
616    }
617
618    /// Removes trailing XML whitespace bytes from text content.
619    ///
620    /// Returns `true` if content is empty after that
621    pub fn inplace_trim_end(&mut self) -> bool {
622        self.content = trim_cow(replace(&mut self.content, Cow::Borrowed(b"")), trim_xml_end);
623        self.content.is_empty()
624    }
625}
626
627impl<'a> Debug for BytesText<'a> {
628    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
629        write!(f, "BytesText {{ content: ")?;
630        write_cow_string(f, &self.content)?;
631        write!(f, " }}")
632    }
633}
634
635impl<'a> Deref for BytesText<'a> {
636    type Target = [u8];
637
638    fn deref(&self) -> &[u8] {
639        &self.content
640    }
641}
642
643#[cfg(feature = "arbitrary")]
644impl<'a> arbitrary::Arbitrary<'a> for BytesText<'a> {
645    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
646        let s = <&str>::arbitrary(u)?;
647        if !s.chars().all(char::is_alphanumeric) {
648            return Err(arbitrary::Error::IncorrectFormat);
649        }
650        Ok(Self::new(s))
651    }
652
653    fn size_hint(depth: usize) -> (usize, Option<usize>) {
654        return <&str as arbitrary::Arbitrary>::size_hint(depth);
655    }
656}
657
658////////////////////////////////////////////////////////////////////////////////////////////////////
659
660/// CDATA content contains unescaped data from the reader. If you want to write them as a text,
661/// [convert](Self::escape) it to [`BytesText`].
662///
663/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
664/// returns the content of this event between `<![CDATA[` and `]]>`.
665///
666/// Note, that inner text will not contain `]]>` sequence inside:
667///
668/// ```
669/// # use quick_xml::events::{BytesCData, Event};
670/// # use quick_xml::reader::Reader;
671/// # use pretty_assertions::assert_eq;
672/// let mut reader = Reader::from_str("<![CDATA[ CDATA section ]]>");
673/// let content = " CDATA section ";
674/// let event = BytesCData::new(content);
675///
676/// assert_eq!(reader.read_event().unwrap(), Event::CData(event.borrow()));
677/// // deref coercion of &BytesCData to &[u8]
678/// assert_eq!(&event as &[u8], content.as_bytes());
679/// // AsRef<[u8]> for &T + deref coercion
680/// assert_eq!(event.as_ref(), content.as_bytes());
681/// ```
682#[derive(Clone, Eq, PartialEq)]
683pub struct BytesCData<'a> {
684    content: Cow<'a, [u8]>,
685    /// Encoding in which the `content` is stored inside the event
686    decoder: Decoder,
687}
688
689impl<'a> BytesCData<'a> {
690    /// Creates a new `BytesCData` from a byte sequence in the specified encoding.
691    #[inline]
692    pub(crate) fn wrap<C: Into<Cow<'a, [u8]>>>(content: C, decoder: Decoder) -> Self {
693        Self {
694            content: content.into(),
695            decoder,
696        }
697    }
698
699    /// Creates a new `BytesCData` from a string.
700    ///
701    /// # Warning
702    ///
703    /// `content` must not contain the `]]>` sequence.
704    #[inline]
705    pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
706        Self::wrap(str_cow_to_bytes(content), Decoder::utf8())
707    }
708
709    /// Ensures that all data is owned to extend the object's lifetime if
710    /// necessary.
711    #[inline]
712    pub fn into_owned(self) -> BytesCData<'static> {
713        BytesCData {
714            content: self.content.into_owned().into(),
715            decoder: self.decoder,
716        }
717    }
718
719    /// Extracts the inner `Cow` from the `BytesCData` event container.
720    #[inline]
721    pub fn into_inner(self) -> Cow<'a, [u8]> {
722        self.content
723    }
724
725    /// Converts the event into a borrowed event.
726    #[inline]
727    pub fn borrow(&self) -> BytesCData {
728        BytesCData {
729            content: Cow::Borrowed(&self.content),
730            decoder: self.decoder,
731        }
732    }
733
734    /// Converts this CDATA content to an escaped version, that can be written
735    /// as an usual text in XML.
736    ///
737    /// This function performs following replacements:
738    ///
739    /// | Character | Replacement
740    /// |-----------|------------
741    /// | `<`       | `&lt;`
742    /// | `>`       | `&gt;`
743    /// | `&`       | `&amp;`
744    /// | `'`       | `&apos;`
745    /// | `"`       | `&quot;`
746    pub fn escape(self) -> Result<BytesText<'a>> {
747        let decoded = self.decode()?;
748        Ok(BytesText::wrap(
749            match escape(&decoded) {
750                // Because result is borrowed, no replacements was done and we can use original content
751                Cow::Borrowed(_) => self.content,
752                Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
753            },
754            Decoder::utf8(),
755        ))
756    }
757
758    /// Converts this CDATA content to an escaped version, that can be written
759    /// as an usual text in XML.
760    ///
761    /// In XML text content, it is allowed (though not recommended) to leave
762    /// the quote special characters `"` and `'` unescaped.
763    ///
764    /// This function performs following replacements:
765    ///
766    /// | Character | Replacement
767    /// |-----------|------------
768    /// | `<`       | `&lt;`
769    /// | `>`       | `&gt;`
770    /// | `&`       | `&amp;`
771    pub fn partial_escape(self) -> Result<BytesText<'a>> {
772        let decoded = self.decode()?;
773        Ok(BytesText::wrap(
774            match partial_escape(&decoded) {
775                // Because result is borrowed, no replacements was done and we can use original content
776                Cow::Borrowed(_) => self.content,
777                Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
778            },
779            Decoder::utf8(),
780        ))
781    }
782
783    /// Converts this CDATA content to an escaped version, that can be written
784    /// as an usual text in XML. This method escapes only those characters that
785    /// must be escaped according to the [specification].
786    ///
787    /// This function performs following replacements:
788    ///
789    /// | Character | Replacement
790    /// |-----------|------------
791    /// | `<`       | `&lt;`
792    /// | `&`       | `&amp;`
793    ///
794    /// [specification]: https://www.w3.org/TR/xml11/#syntax
795    pub fn minimal_escape(self) -> Result<BytesText<'a>> {
796        let decoded = self.decode()?;
797        Ok(BytesText::wrap(
798            match minimal_escape(&decoded) {
799                // Because result is borrowed, no replacements was done and we can use original content
800                Cow::Borrowed(_) => self.content,
801                Cow::Owned(escaped) => Cow::Owned(escaped.into_bytes()),
802            },
803            Decoder::utf8(),
804        ))
805    }
806
807    /// Gets content of this text buffer in the specified encoding
808    pub(crate) fn decode(&self) -> Result<Cow<'a, str>> {
809        self.decoder.decode_cow(&self.content)
810    }
811}
812
813impl<'a> Debug for BytesCData<'a> {
814    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
815        write!(f, "BytesCData {{ content: ")?;
816        write_cow_string(f, &self.content)?;
817        write!(f, " }}")
818    }
819}
820
821impl<'a> Deref for BytesCData<'a> {
822    type Target = [u8];
823
824    fn deref(&self) -> &[u8] {
825        &self.content
826    }
827}
828
829#[cfg(feature = "arbitrary")]
830impl<'a> arbitrary::Arbitrary<'a> for BytesCData<'a> {
831    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
832        Ok(Self::new(<&str>::arbitrary(u)?))
833    }
834    fn size_hint(depth: usize) -> (usize, Option<usize>) {
835        return <&str as arbitrary::Arbitrary>::size_hint(depth);
836    }
837}
838
839////////////////////////////////////////////////////////////////////////////////////////////////////
840
841/// [Processing instructions][PI] (PIs) allow documents to contain instructions for applications.
842///
843/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
844/// returns the content of this event between `<?` and `?>`.
845///
846/// Note, that inner text will not contain `?>` sequence inside:
847///
848/// ```
849/// # use quick_xml::events::{BytesPI, Event};
850/// # use quick_xml::reader::Reader;
851/// # use pretty_assertions::assert_eq;
852/// let mut reader = Reader::from_str("<?processing instruction >:-<~ ?>");
853/// let content = "processing instruction >:-<~ ";
854/// let event = BytesPI::new(content);
855///
856/// assert_eq!(reader.read_event().unwrap(), Event::PI(event.borrow()));
857/// // deref coercion of &BytesPI to &[u8]
858/// assert_eq!(&event as &[u8], content.as_bytes());
859/// // AsRef<[u8]> for &T + deref coercion
860/// assert_eq!(event.as_ref(), content.as_bytes());
861/// ```
862///
863/// [PI]: https://www.w3.org/TR/xml11/#sec-pi
864#[derive(Clone, Eq, PartialEq)]
865pub struct BytesPI<'a> {
866    content: BytesStart<'a>,
867}
868
869impl<'a> BytesPI<'a> {
870    /// Creates a new `BytesPI` from a byte sequence in the specified encoding.
871    #[inline]
872    pub(crate) const fn wrap(content: &'a [u8], target_len: usize) -> Self {
873        Self {
874            content: BytesStart::wrap(content, target_len),
875        }
876    }
877
878    /// Creates a new `BytesPI` from a string.
879    ///
880    /// # Warning
881    ///
882    /// `content` must not contain the `?>` sequence.
883    #[inline]
884    pub fn new<C: Into<Cow<'a, str>>>(content: C) -> Self {
885        let buf = str_cow_to_bytes(content);
886        let name_len = name_len(&buf);
887        Self {
888            content: BytesStart { buf, name_len },
889        }
890    }
891
892    /// Ensures that all data is owned to extend the object's lifetime if
893    /// necessary.
894    #[inline]
895    pub fn into_owned(self) -> BytesPI<'static> {
896        BytesPI {
897            content: self.content.into_owned().into(),
898        }
899    }
900
901    /// Extracts the inner `Cow` from the `BytesPI` event container.
902    #[inline]
903    pub fn into_inner(self) -> Cow<'a, [u8]> {
904        self.content.buf
905    }
906
907    /// Converts the event into a borrowed event.
908    #[inline]
909    pub fn borrow(&self) -> BytesPI {
910        BytesPI {
911            content: self.content.borrow(),
912        }
913    }
914
915    /// A target used to identify the application to which the instruction is directed.
916    ///
917    /// # Example
918    ///
919    /// ```
920    /// # use pretty_assertions::assert_eq;
921    /// use quick_xml::events::BytesPI;
922    ///
923    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
924    /// assert_eq!(instruction.target(), b"xml-stylesheet");
925    /// ```
926    #[inline]
927    pub fn target(&self) -> &[u8] {
928        self.content.name().0
929    }
930
931    /// Content of the processing instruction. Contains everything between target
932    /// name and the end of the instruction. A direct consequence is that the first
933    /// character is always a space character.
934    ///
935    /// # Example
936    ///
937    /// ```
938    /// # use pretty_assertions::assert_eq;
939    /// use quick_xml::events::BytesPI;
940    ///
941    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
942    /// assert_eq!(instruction.content(), br#" href="style.css""#);
943    /// ```
944    #[inline]
945    pub fn content(&self) -> &[u8] {
946        self.content.attributes_raw()
947    }
948
949    /// A view of the processing instructions' content as a list of key-value pairs.
950    ///
951    /// Key-value pairs are used in some processing instructions, for example in
952    /// `<?xml-stylesheet?>`.
953    ///
954    /// Returned iterator does not validate attribute values as may required by
955    /// target's rules. For example, it doesn't check that substring `?>` is not
956    /// present in the attribute value. That shouldn't be the problem when event
957    /// is produced by the reader, because reader detects end of processing instruction
958    /// by the first `?>` sequence, as required by the specification, and therefore
959    /// this sequence cannot appear inside it.
960    ///
961    /// # Example
962    ///
963    /// ```
964    /// # use pretty_assertions::assert_eq;
965    /// use std::borrow::Cow;
966    /// use quick_xml::events::attributes::Attribute;
967    /// use quick_xml::events::BytesPI;
968    /// use quick_xml::name::QName;
969    ///
970    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
971    /// for attr in instruction.attributes() {
972    ///     assert_eq!(attr, Ok(Attribute {
973    ///         key: QName(b"href"),
974    ///         value: Cow::Borrowed(b"style.css"),
975    ///     }));
976    /// }
977    /// ```
978    #[inline]
979    pub fn attributes(&self) -> Attributes {
980        self.content.attributes()
981    }
982}
983
984impl<'a> Debug for BytesPI<'a> {
985    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
986        write!(f, "BytesPI {{ content: ")?;
987        write_cow_string(f, &self.content.buf)?;
988        write!(f, " }}")
989    }
990}
991
992impl<'a> Deref for BytesPI<'a> {
993    type Target = [u8];
994
995    fn deref(&self) -> &[u8] {
996        &self.content
997    }
998}
999
1000#[cfg(feature = "arbitrary")]
1001impl<'a> arbitrary::Arbitrary<'a> for BytesPI<'a> {
1002    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1003        Ok(Self::new(<&str>::arbitrary(u)?))
1004    }
1005    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1006        return <&str as arbitrary::Arbitrary>::size_hint(depth);
1007    }
1008}
1009
1010////////////////////////////////////////////////////////////////////////////////////////////////////
1011
1012/// An XML declaration (`Event::Decl`).
1013///
1014/// [W3C XML 1.1 Prolog and Document Type Declaration](http://w3.org/TR/xml11/#sec-prolog-dtd)
1015///
1016/// This event implements `Deref<Target = [u8]>`. The `deref()` implementation
1017/// returns the content of this event between `<?` and `?>`.
1018///
1019/// Note, that inner text will not contain `?>` sequence inside:
1020///
1021/// ```
1022/// # use quick_xml::events::{BytesDecl, BytesStart, Event};
1023/// # use quick_xml::reader::Reader;
1024/// # use pretty_assertions::assert_eq;
1025/// let mut reader = Reader::from_str("<?xml version = '1.0' ?>");
1026/// let content = "xml version = '1.0' ";
1027/// let event = BytesDecl::from_start(BytesStart::from_content(content, 3));
1028///
1029/// assert_eq!(reader.read_event().unwrap(), Event::Decl(event.borrow()));
1030/// // deref coercion of &BytesDecl to &[u8]
1031/// assert_eq!(&event as &[u8], content.as_bytes());
1032/// // AsRef<[u8]> for &T + deref coercion
1033/// assert_eq!(event.as_ref(), content.as_bytes());
1034/// ```
1035#[derive(Clone, Debug, Eq, PartialEq)]
1036pub struct BytesDecl<'a> {
1037    content: BytesStart<'a>,
1038}
1039
1040impl<'a> BytesDecl<'a> {
1041    /// Constructs a new `XmlDecl` from the (mandatory) _version_ (should be `1.0` or `1.1`),
1042    /// the optional _encoding_ (e.g., `UTF-8`) and the optional _standalone_ (`yes` or `no`)
1043    /// attribute.
1044    ///
1045    /// Does not escape any of its inputs. Always uses double quotes to wrap the attribute values.
1046    /// The caller is responsible for escaping attribute values. Shouldn't usually be relevant since
1047    /// the double quote character is not allowed in any of the attribute values.
1048    pub fn new(
1049        version: &str,
1050        encoding: Option<&str>,
1051        standalone: Option<&str>,
1052    ) -> BytesDecl<'static> {
1053        // Compute length of the buffer based on supplied attributes
1054        // ' encoding=""'   => 12
1055        let encoding_attr_len = if let Some(xs) = encoding {
1056            12 + xs.len()
1057        } else {
1058            0
1059        };
1060        // ' standalone=""' => 14
1061        let standalone_attr_len = if let Some(xs) = standalone {
1062            14 + xs.len()
1063        } else {
1064            0
1065        };
1066        // 'xml version=""' => 14
1067        let mut buf = String::with_capacity(14 + encoding_attr_len + standalone_attr_len);
1068
1069        buf.push_str("xml version=\"");
1070        buf.push_str(version);
1071
1072        if let Some(encoding_val) = encoding {
1073            buf.push_str("\" encoding=\"");
1074            buf.push_str(encoding_val);
1075        }
1076
1077        if let Some(standalone_val) = standalone {
1078            buf.push_str("\" standalone=\"");
1079            buf.push_str(standalone_val);
1080        }
1081        buf.push('"');
1082
1083        BytesDecl {
1084            content: BytesStart::from_content(buf, 3),
1085        }
1086    }
1087
1088    /// Creates a `BytesDecl` from a `BytesStart`
1089    pub const fn from_start(start: BytesStart<'a>) -> Self {
1090        Self { content: start }
1091    }
1092
1093    /// Gets xml version, excluding quotes (`'` or `"`).
1094    ///
1095    /// According to the [grammar], the version *must* be the first thing in the declaration.
1096    /// This method tries to extract the first thing in the declaration and return it.
1097    /// In case of multiple attributes value of the first one is returned.
1098    ///
1099    /// If version is missed in the declaration, or the first thing is not a version,
1100    /// [`IllFormedError::MissingDeclVersion`] will be returned.
1101    ///
1102    /// # Examples
1103    ///
1104    /// ```
1105    /// use quick_xml::errors::{Error, IllFormedError};
1106    /// use quick_xml::events::{BytesDecl, BytesStart};
1107    ///
1108    /// // <?xml version='1.1'?>
1109    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1110    /// assert_eq!(decl.version().unwrap(), b"1.1".as_ref());
1111    ///
1112    /// // <?xml version='1.0' version='1.1'?>
1113    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.0' version='1.1'", 0));
1114    /// assert_eq!(decl.version().unwrap(), b"1.0".as_ref());
1115    ///
1116    /// // <?xml encoding='utf-8'?>
1117    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8'", 0));
1118    /// match decl.version() {
1119    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1120    ///     _ => assert!(false),
1121    /// }
1122    ///
1123    /// // <?xml encoding='utf-8' version='1.1'?>
1124    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8' version='1.1'", 0));
1125    /// match decl.version() {
1126    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1127    ///     _ => assert!(false),
1128    /// }
1129    ///
1130    /// // <?xml?>
1131    /// let decl = BytesDecl::from_start(BytesStart::from_content("", 0));
1132    /// match decl.version() {
1133    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))) => {},
1134    ///     _ => assert!(false),
1135    /// }
1136    /// ```
1137    ///
1138    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1139    pub fn version(&self) -> Result<Cow<[u8]>> {
1140        // The version *must* be the first thing in the declaration.
1141        match self.content.attributes().with_checks(false).next() {
1142            Some(Ok(a)) if a.key.as_ref() == b"version" => Ok(a.value),
1143            // first attribute was not "version"
1144            Some(Ok(a)) => {
1145                let found = from_utf8(a.key.as_ref())?.to_string();
1146                Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(
1147                    found,
1148                ))))
1149            }
1150            // error parsing attributes
1151            Some(Err(e)) => Err(e.into()),
1152            // no attributes
1153            None => Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))),
1154        }
1155    }
1156
1157    /// Gets xml encoding, excluding quotes (`'` or `"`).
1158    ///
1159    /// Although according to the [grammar] encoding must appear before `"standalone"`
1160    /// and after `"version"`, this method does not check that. The first occurrence
1161    /// of the attribute will be returned even if there are several. Also, method does
1162    /// not restrict symbols that can forming the encoding, so the returned encoding
1163    /// name may not correspond to the grammar.
1164    ///
1165    /// # Examples
1166    ///
1167    /// ```
1168    /// use std::borrow::Cow;
1169    /// use quick_xml::Error;
1170    /// use quick_xml::events::{BytesDecl, BytesStart};
1171    ///
1172    /// // <?xml version='1.1'?>
1173    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1174    /// assert!(decl.encoding().is_none());
1175    ///
1176    /// // <?xml encoding='utf-8'?>
1177    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8'", 0));
1178    /// match decl.encoding() {
1179    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, b"utf-8"),
1180    ///     _ => assert!(false),
1181    /// }
1182    ///
1183    /// // <?xml encoding='something_WRONG' encoding='utf-8'?>
1184    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='something_WRONG' encoding='utf-8'", 0));
1185    /// match decl.encoding() {
1186    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, b"something_WRONG"),
1187    ///     _ => assert!(false),
1188    /// }
1189    /// ```
1190    ///
1191    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1192    pub fn encoding(&self) -> Option<Result<Cow<[u8]>>> {
1193        self.content
1194            .try_get_attribute("encoding")
1195            .map(|a| a.map(|a| a.value))
1196            .transpose()
1197    }
1198
1199    /// Gets xml standalone, excluding quotes (`'` or `"`).
1200    ///
1201    /// Although according to the [grammar] standalone flag must appear after `"version"`
1202    /// and `"encoding"`, this method does not check that. The first occurrence of the
1203    /// attribute will be returned even if there are several. Also, method does not
1204    /// restrict symbols that can forming the value, so the returned flag name may not
1205    /// correspond to the grammar.
1206    ///
1207    /// # Examples
1208    ///
1209    /// ```
1210    /// use std::borrow::Cow;
1211    /// use quick_xml::Error;
1212    /// use quick_xml::events::{BytesDecl, BytesStart};
1213    ///
1214    /// // <?xml version='1.1'?>
1215    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1216    /// assert!(decl.standalone().is_none());
1217    ///
1218    /// // <?xml standalone='yes'?>
1219    /// let decl = BytesDecl::from_start(BytesStart::from_content(" standalone='yes'", 0));
1220    /// match decl.standalone() {
1221    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, b"yes"),
1222    ///     _ => assert!(false),
1223    /// }
1224    ///
1225    /// // <?xml standalone='something_WRONG' encoding='utf-8'?>
1226    /// let decl = BytesDecl::from_start(BytesStart::from_content(" standalone='something_WRONG' encoding='utf-8'", 0));
1227    /// match decl.standalone() {
1228    ///     Some(Ok(Cow::Borrowed(flag))) => assert_eq!(flag, b"something_WRONG"),
1229    ///     _ => assert!(false),
1230    /// }
1231    /// ```
1232    ///
1233    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1234    pub fn standalone(&self) -> Option<Result<Cow<[u8]>>> {
1235        self.content
1236            .try_get_attribute("standalone")
1237            .map(|a| a.map(|a| a.value))
1238            .transpose()
1239    }
1240
1241    /// Gets the actual encoding using [_get an encoding_](https://encoding.spec.whatwg.org/#concept-encoding-get)
1242    /// algorithm.
1243    ///
1244    /// If encoding in not known, or `encoding` key was not found, returns `None`.
1245    /// In case of duplicated `encoding` key, encoding, corresponding to the first
1246    /// one, is returned.
1247    #[cfg(feature = "encoding")]
1248    pub fn encoder(&self) -> Option<&'static Encoding> {
1249        self.encoding()
1250            .and_then(|e| e.ok())
1251            .and_then(|e| Encoding::for_label(&e))
1252    }
1253
1254    /// Converts the event into an owned event.
1255    pub fn into_owned(self) -> BytesDecl<'static> {
1256        BytesDecl {
1257            content: self.content.into_owned(),
1258        }
1259    }
1260
1261    /// Converts the event into a borrowed event.
1262    #[inline]
1263    pub fn borrow(&self) -> BytesDecl {
1264        BytesDecl {
1265            content: self.content.borrow(),
1266        }
1267    }
1268}
1269
1270impl<'a> Deref for BytesDecl<'a> {
1271    type Target = [u8];
1272
1273    fn deref(&self) -> &[u8] {
1274        &self.content
1275    }
1276}
1277
1278#[cfg(feature = "arbitrary")]
1279impl<'a> arbitrary::Arbitrary<'a> for BytesDecl<'a> {
1280    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1281        Ok(Self::new(
1282            <&str>::arbitrary(u)?,
1283            Option::<&str>::arbitrary(u)?,
1284            Option::<&str>::arbitrary(u)?,
1285        ))
1286    }
1287
1288    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1289        return <&str as arbitrary::Arbitrary>::size_hint(depth);
1290    }
1291}
1292
1293////////////////////////////////////////////////////////////////////////////////////////////////////
1294
1295/// Event emitted by [`Reader::read_event_into`].
1296///
1297/// [`Reader::read_event_into`]: crate::reader::Reader::read_event_into
1298#[derive(Clone, Debug, Eq, PartialEq)]
1299#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1300pub enum Event<'a> {
1301    /// Start tag (with attributes) `<tag attr="value">`.
1302    Start(BytesStart<'a>),
1303    /// End tag `</tag>`.
1304    End(BytesEnd<'a>),
1305    /// Empty element tag (with attributes) `<tag attr="value" />`.
1306    Empty(BytesStart<'a>),
1307    /// Escaped character data between tags.
1308    Text(BytesText<'a>),
1309    /// Unescaped character data stored in `<![CDATA[...]]>`.
1310    CData(BytesCData<'a>),
1311    /// Comment `<!-- ... -->`.
1312    Comment(BytesText<'a>),
1313    /// XML declaration `<?xml ...?>`.
1314    Decl(BytesDecl<'a>),
1315    /// Processing instruction `<?...?>`.
1316    PI(BytesPI<'a>),
1317    /// Document type definition data (DTD) stored in `<!DOCTYPE ...>`.
1318    DocType(BytesText<'a>),
1319    /// End of XML document.
1320    Eof,
1321}
1322
1323impl<'a> Event<'a> {
1324    /// Converts the event to an owned version, untied to the lifetime of
1325    /// buffer used when reading but incurring a new, separate allocation.
1326    pub fn into_owned(self) -> Event<'static> {
1327        match self {
1328            Event::Start(e) => Event::Start(e.into_owned()),
1329            Event::End(e) => Event::End(e.into_owned()),
1330            Event::Empty(e) => Event::Empty(e.into_owned()),
1331            Event::Text(e) => Event::Text(e.into_owned()),
1332            Event::Comment(e) => Event::Comment(e.into_owned()),
1333            Event::CData(e) => Event::CData(e.into_owned()),
1334            Event::Decl(e) => Event::Decl(e.into_owned()),
1335            Event::PI(e) => Event::PI(e.into_owned()),
1336            Event::DocType(e) => Event::DocType(e.into_owned()),
1337            Event::Eof => Event::Eof,
1338        }
1339    }
1340
1341    /// Converts the event into a borrowed event.
1342    #[inline]
1343    pub fn borrow(&self) -> Event {
1344        match self {
1345            Event::Start(e) => Event::Start(e.borrow()),
1346            Event::End(e) => Event::End(e.borrow()),
1347            Event::Empty(e) => Event::Empty(e.borrow()),
1348            Event::Text(e) => Event::Text(e.borrow()),
1349            Event::Comment(e) => Event::Comment(e.borrow()),
1350            Event::CData(e) => Event::CData(e.borrow()),
1351            Event::Decl(e) => Event::Decl(e.borrow()),
1352            Event::PI(e) => Event::PI(e.borrow()),
1353            Event::DocType(e) => Event::DocType(e.borrow()),
1354            Event::Eof => Event::Eof,
1355        }
1356    }
1357}
1358
1359impl<'a> Deref for Event<'a> {
1360    type Target = [u8];
1361
1362    fn deref(&self) -> &[u8] {
1363        match *self {
1364            Event::Start(ref e) | Event::Empty(ref e) => e,
1365            Event::End(ref e) => e,
1366            Event::Text(ref e) => e,
1367            Event::Decl(ref e) => e,
1368            Event::PI(ref e) => e,
1369            Event::CData(ref e) => e,
1370            Event::Comment(ref e) => e,
1371            Event::DocType(ref e) => e,
1372            Event::Eof => &[],
1373        }
1374    }
1375}
1376
1377impl<'a> AsRef<Event<'a>> for Event<'a> {
1378    fn as_ref(&self) -> &Event<'a> {
1379        self
1380    }
1381}
1382
1383////////////////////////////////////////////////////////////////////////////////////////////////////
1384
1385#[inline]
1386fn str_cow_to_bytes<'a, C: Into<Cow<'a, str>>>(content: C) -> Cow<'a, [u8]> {
1387    match content.into() {
1388        Cow::Borrowed(s) => Cow::Borrowed(s.as_bytes()),
1389        Cow::Owned(s) => Cow::Owned(s.into_bytes()),
1390    }
1391}
1392
1393fn trim_cow<'a, F>(value: Cow<'a, [u8]>, trim: F) -> Cow<'a, [u8]>
1394where
1395    F: FnOnce(&[u8]) -> &[u8],
1396{
1397    match value {
1398        Cow::Borrowed(bytes) => Cow::Borrowed(trim(bytes)),
1399        Cow::Owned(mut bytes) => {
1400            let trimmed = trim(&bytes);
1401            if trimmed.len() != bytes.len() {
1402                bytes = trimmed.to_vec();
1403            }
1404            Cow::Owned(bytes)
1405        }
1406    }
1407}
1408
1409#[cfg(test)]
1410mod test {
1411    use super::*;
1412    use pretty_assertions::assert_eq;
1413
1414    #[test]
1415    fn bytestart_create() {
1416        let b = BytesStart::new("test");
1417        assert_eq!(b.len(), 4);
1418        assert_eq!(b.name(), QName(b"test"));
1419    }
1420
1421    #[test]
1422    fn bytestart_set_name() {
1423        let mut b = BytesStart::new("test");
1424        assert_eq!(b.len(), 4);
1425        assert_eq!(b.name(), QName(b"test"));
1426        assert_eq!(b.attributes_raw(), b"");
1427        b.push_attribute(("x", "a"));
1428        assert_eq!(b.len(), 10);
1429        assert_eq!(b.attributes_raw(), b" x=\"a\"");
1430        b.set_name(b"g");
1431        assert_eq!(b.len(), 7);
1432        assert_eq!(b.name(), QName(b"g"));
1433    }
1434
1435    #[test]
1436    fn bytestart_clear_attributes() {
1437        let mut b = BytesStart::new("test");
1438        b.push_attribute(("x", "y\"z"));
1439        b.push_attribute(("x", "y\"z"));
1440        b.clear_attributes();
1441        assert!(b.attributes().next().is_none());
1442        assert_eq!(b.len(), 4);
1443        assert_eq!(b.name(), QName(b"test"));
1444    }
1445}