Skip to main content

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::iter::FusedIterator;
45use std::mem::replace;
46use std::ops::Deref;
47
48use crate::XmlVersion;
49use crate::encoding::EncodingError;
50use crate::errors::{Error, IllFormedError};
51use crate::escape::{
52    EscapeError, escape, minimal_escape, normalize_xml10_eols, normalize_xml11_eols, parse_number,
53    partial_escape,
54};
55use crate::name::{LocalName, QName};
56use crate::utils::{self, name_len, trim_xml_end, trim_xml_start, write_cow_string};
57use attributes::{AttrError, 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 = str>`. 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 &str
83/// assert_eq!(event.as_ref(), content);
84/// ```
85///
86/// # Lifetime
87///
88/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
89/// In particular, when reader was created from a string, this is lifetime of the string.
90/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
91/// If such event need to outlive the single parsing loop iteration, take ownership of the data
92/// using [`.into_owned()`].
93///
94/// [`name`]: Self::name
95/// [`local_name`]: Self::local_name
96/// [`attributes`]: Self::attributes
97/// [`.into_owned()`]: Self::into_owned
98#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
99pub struct BytesStart<'i> {
100    /// content of the element
101    pub(crate) buf: Cow<'i, str>,
102    /// end of the element name, the name starts at that the start of `buf`
103    pub(crate) name_len: usize,
104}
105
106impl<'i> BytesStart<'i> {
107    /// Internal constructor, used by `Reader`. Supplies data in reader's encoding
108    #[inline]
109    pub(crate) const fn wrap(content: &'i str, name_len: usize) -> Self {
110        BytesStart {
111            buf: Cow::Borrowed(content),
112            name_len,
113        }
114    }
115
116    /// Creates a new `BytesStart` from the given name.
117    ///
118    /// # Warning
119    ///
120    /// `name` must be a valid name.
121    #[inline]
122    pub fn new<C: Into<Cow<'i, str>>>(name: C) -> Self {
123        let buf: Cow<'i, str> = name.into();
124        BytesStart {
125            name_len: buf.len(),
126            buf,
127        }
128    }
129
130    /// Creates a new `BytesStart` from the given content (name + attributes).
131    ///
132    /// # Warning
133    ///
134    /// `&content[..name_len]` must be a valid name, and the remainder of `content`
135    /// must be correctly-formed attributes. Neither are checked, it is possible
136    /// to generate invalid XML if `content` or `name_len` are incorrect.
137    #[inline]
138    pub fn from_content<C: Into<Cow<'i, str>>>(content: C, name_len: usize) -> Self {
139        BytesStart {
140            buf: content.into(),
141            name_len,
142        }
143    }
144
145    /// Converts the event into an owned event.
146    pub fn into_owned(self) -> BytesStart<'static> {
147        BytesStart {
148            buf: Cow::Owned(self.buf.into_owned()),
149            name_len: self.name_len,
150        }
151    }
152
153    /// Converts the event into an owned event without taking ownership of Event
154    pub fn to_owned(&self) -> BytesStart<'static> {
155        BytesStart {
156            buf: Cow::Owned(self.buf.clone().into_owned()),
157            name_len: self.name_len,
158        }
159    }
160
161    /// Converts the event into a borrowed event. Most useful when paired with [`to_end`].
162    ///
163    /// # Example
164    ///
165    /// ```
166    /// use quick_xml::events::{BytesStart, Event};
167    /// # use quick_xml::writer::Writer;
168    /// # use quick_xml::Error;
169    ///
170    /// struct SomeStruct<'i> {
171    ///     attrs: BytesStart<'i>,
172    ///     // ...
173    /// }
174    /// # impl<'i> SomeStruct<'i> {
175    /// # fn example(&self) -> Result<(), Error> {
176    /// # let mut writer = Writer::new(Vec::new());
177    ///
178    /// writer.write_event(Event::Start(self.attrs.borrow()))?;
179    /// // ...
180    /// writer.write_event(Event::End(self.attrs.to_end()))?;
181    /// # Ok(())
182    /// # }}
183    /// ```
184    ///
185    /// [`to_end`]: Self::to_end
186    pub fn borrow(&self) -> BytesStart<'_> {
187        BytesStart {
188            buf: Cow::Borrowed(&self.buf),
189            name_len: self.name_len,
190        }
191    }
192
193    /// Creates new paired close tag
194    #[inline]
195    pub fn to_end(&self) -> BytesEnd<'_> {
196        BytesEnd::from(self.name())
197    }
198
199    /// Gets the undecoded raw tag name, as present in the input stream.
200    #[inline]
201    pub fn name(&self) -> QName<'_> {
202        QName(&self.buf[..self.name_len])
203    }
204
205    /// Gets the undecoded raw local tag name (excluding namespace) as present
206    /// in the input stream.
207    ///
208    /// All content up to and including the first `:` character is removed from the tag name.
209    #[inline]
210    pub fn local_name(&self) -> LocalName<'_> {
211        self.name().into()
212    }
213
214    /// Edit the name of the BytesStart in-place
215    ///
216    /// # Warning
217    ///
218    /// `name` must be a valid name.
219    pub fn set_name(&mut self, name: &str) -> &mut BytesStart<'i> {
220        let s = self.buf.to_mut();
221        s.replace_range(..self.name_len, name);
222        self.name_len = name.len();
223        self
224    }
225}
226
227/// Attribute-related methods
228impl<'i> BytesStart<'i> {
229    /// Consumes `self` and yield a new `BytesStart` with additional attributes from an iterator.
230    ///
231    /// The yielded items must be convertible to [`Attribute`] using `Into`.
232    pub fn with_attributes<'a, I>(mut self, attributes: I) -> Self
233    where
234        I: IntoIterator,
235        I::Item: Into<Attribute<'a>>,
236    {
237        self.extend_attributes(attributes);
238        self
239    }
240
241    /// Add additional attributes to this tag using an iterator.
242    ///
243    /// The yielded items must be convertible to [`Attribute`] using `Into`.
244    pub fn extend_attributes<'a, I>(&mut self, attributes: I) -> &mut BytesStart<'i>
245    where
246        I: IntoIterator,
247        I::Item: Into<Attribute<'a>>,
248    {
249        for attr in attributes {
250            self.push_attribute(attr);
251        }
252        self
253    }
254
255    /// Adds an attribute to this element.
256    pub fn push_attribute<'a, A>(&mut self, attr: A)
257    where
258        A: Into<Attribute<'a>>,
259    {
260        self.buf.to_mut().push(' ');
261        self.push_attr(attr.into());
262    }
263
264    /// Remove all attributes from the ByteStart
265    pub fn clear_attributes(&mut self) -> &mut BytesStart<'i> {
266        self.buf.to_mut().truncate(self.name_len);
267        self
268    }
269
270    /// Returns an iterator over the attributes of this tag.
271    pub fn attributes(&self) -> Attributes<'_> {
272        Attributes::wrap(&self.buf, self.name_len, false)
273    }
274
275    /// Returns an iterator over the HTML-like attributes of this tag (no mandatory quotes or `=`).
276    pub fn html_attributes(&self) -> Attributes<'_> {
277        Attributes::wrap(&self.buf, self.name_len, true)
278    }
279
280    /// Gets the undecoded raw string with the attributes of this tag as a `&str`,
281    /// including the whitespace after the tag name if there is any.
282    #[inline]
283    pub fn attributes_raw(&self) -> &str {
284        &self.buf[self.name_len..]
285    }
286
287    /// Try to get an attribute
288    pub fn try_get_attribute<'a>(
289        &'a self,
290        attr_name: &str,
291    ) -> Result<Option<Attribute<'a>>, AttrError> {
292        for a in self.attributes().with_checks(false) {
293            let a = a?;
294            if a.key.as_ref() == attr_name {
295                return Ok(Some(a));
296            }
297        }
298        Ok(None)
299    }
300
301    /// Adds an attribute to this element.
302    pub(crate) fn push_attr<'a>(&mut self, attr: Attribute<'a>) {
303        let s = self.buf.to_mut();
304        s.push_str(attr.key.as_ref());
305        s.push_str("=\"");
306        // FIXME: need to escape attribute content
307        s.push_str(&attr.value);
308        s.push('"');
309    }
310
311    /// Adds new line in existing element
312    pub(crate) fn push_newline(&mut self) {
313        self.buf.to_mut().push('\n');
314    }
315
316    /// Adds indentation in existing element
317    pub(crate) fn push_indent(&mut self, indent: &str) {
318        self.buf.to_mut().push_str(indent);
319    }
320}
321
322impl<'i> Debug for BytesStart<'i> {
323    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
324        write!(f, "BytesStart {{ buf: ")?;
325        write_cow_string(f, &self.buf)?;
326        write!(f, ", name_len: {} }}", self.name_len)
327    }
328}
329
330impl<'i> Deref for BytesStart<'i> {
331    type Target = str;
332
333    fn deref(&self) -> &str {
334        &self.buf
335    }
336}
337
338impl AsRef<str> for BytesStart<'_> {
339    fn as_ref(&self) -> &str {
340        self
341    }
342}
343
344#[cfg(feature = "arbitrary")]
345impl<'i> arbitrary::Arbitrary<'i> for BytesStart<'i> {
346    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
347        let s = <&str>::arbitrary(u)?;
348        if s.is_empty() || !s.chars().all(char::is_alphanumeric) {
349            return Err(arbitrary::Error::IncorrectFormat);
350        }
351        let mut result = Self::new(s);
352        result.extend_attributes(Vec::<(&str, &str)>::arbitrary(u)?);
353        Ok(result)
354    }
355
356    fn size_hint(depth: usize) -> (usize, Option<usize>) {
357        <&str as arbitrary::Arbitrary>::size_hint(depth)
358    }
359}
360
361////////////////////////////////////////////////////////////////////////////////////////////////////
362
363/// Closing tag data (`Event::End`): `</name>`.
364///
365/// The name can be accessed using the [`name`] or [`local_name`] methods.
366///
367/// This event implements `Deref<Target = str>`. The `deref()` implementation
368/// returns the content of this event between `</` and `>`.
369///
370/// Note, that inner text will not contain `>` character inside:
371///
372/// ```
373/// # use quick_xml::events::{BytesEnd, Event};
374/// # use quick_xml::reader::Reader;
375/// # use pretty_assertions::assert_eq;
376/// let mut reader = Reader::from_str(r#"<element></element a1 = 'val1' a2="val2" >"#);
377/// // Note, that this entire string considered as a .name()
378/// let content = "element a1 = 'val1' a2=\"val2\" ";
379/// let event = BytesEnd::new(content);
380///
381/// reader.config_mut().trim_markup_names_in_closing_tags = false;
382/// reader.config_mut().check_end_names = false;
383/// reader.read_event().unwrap(); // Skip `<element>`
384///
385/// assert_eq!(reader.read_event().unwrap(), Event::End(event.borrow()));
386/// assert_eq!(event.name().as_ref(), content);
387/// // deref coercion of &BytesEnd to &str
388/// assert_eq!(event.as_ref(), content);
389/// ```
390///
391/// # Lifetime
392///
393/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
394/// In particular, when reader was created from a string, this is lifetime of the string.
395/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
396/// If such event need to outlive the single parsing loop iteration, take ownership of the data
397/// using [`.into_owned()`].
398///
399/// [`name`]: Self::name
400/// [`local_name`]: Self::local_name
401/// [`.into_owned()`]: Self::into_owned
402#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
403pub struct BytesEnd<'i> {
404    name: Cow<'i, str>,
405}
406
407impl<'i> BytesEnd<'i> {
408    /// Internal constructor, used by `Reader`. Supplies data in reader's encoding
409    #[inline]
410    pub(crate) const fn wrap(name: Cow<'i, str>) -> Self {
411        BytesEnd { name }
412    }
413
414    /// Creates a new `BytesEnd` borrowing a slice.
415    ///
416    /// # Warning
417    ///
418    /// `name` must be a valid name.
419    #[inline]
420    pub fn new<C: Into<Cow<'i, str>>>(name: C) -> Self {
421        Self::wrap(name.into())
422    }
423
424    /// Converts the event into an owned event.
425    pub fn into_owned(self) -> BytesEnd<'static> {
426        BytesEnd {
427            name: Cow::Owned(self.name.into_owned()),
428        }
429    }
430
431    /// Converts the event into a borrowed event.
432    #[inline]
433    pub fn borrow(&self) -> BytesEnd<'_> {
434        BytesEnd {
435            name: Cow::Borrowed(&self.name),
436        }
437    }
438
439    /// Gets the undecoded raw tag name, as present in the input stream.
440    #[inline]
441    pub fn name(&self) -> QName<'_> {
442        QName(&self.name)
443    }
444
445    /// Gets the undecoded raw local tag name (excluding namespace) as present
446    /// in the input stream.
447    ///
448    /// All content up to and including the first `:` character is removed from the tag name.
449    #[inline]
450    pub fn local_name(&self) -> LocalName<'_> {
451        self.name().into()
452    }
453}
454
455impl<'i> Debug for BytesEnd<'i> {
456    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
457        write!(f, "BytesEnd {{ name: ")?;
458        write_cow_string(f, &self.name)?;
459        write!(f, " }}")
460    }
461}
462
463impl<'i> Deref for BytesEnd<'i> {
464    type Target = str;
465
466    fn deref(&self) -> &str {
467        &self.name
468    }
469}
470
471impl AsRef<str> for BytesEnd<'_> {
472    fn as_ref(&self) -> &str {
473        self
474    }
475}
476
477impl<'i> From<QName<'i>> for BytesEnd<'i> {
478    #[inline]
479    fn from(name: QName<'i>) -> Self {
480        Self::wrap(Cow::Borrowed(name.into_inner()))
481    }
482}
483
484#[cfg(feature = "arbitrary")]
485impl<'i> arbitrary::Arbitrary<'i> for BytesEnd<'i> {
486    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
487        Ok(Self::new(<&str>::arbitrary(u)?))
488    }
489    fn size_hint(depth: usize) -> (usize, Option<usize>) {
490        <&str as arbitrary::Arbitrary>::size_hint(depth)
491    }
492}
493
494////////////////////////////////////////////////////////////////////////////////////////////////////
495
496/// Data from various events (most notably, `Event::Text`).
497///
498/// This event implements `Deref<Target = str>`. The `deref()` implementation
499/// returns the content of this event. In case of comment this is everything
500/// between `<!--` and `-->` and the text of comment may not contain `-->` inside
501/// (if [`Config::check_comments`] is set to `true`).
502/// In case of DTD this is everything between `<!DOCTYPE` + spaces and closing `>`
503/// (i.e. in case of DTD the first character is never space):
504///
505/// ```
506/// # use quick_xml::events::{BytesText, Event};
507/// # use quick_xml::reader::Reader;
508/// # use pretty_assertions::assert_eq;
509/// // Remember, that \ at the end of string literal strips
510/// // all space characters to the first non-space character
511/// let mut reader = Reader::from_str("\
512///     <!DOCTYPE comment or text >\
513///     comment or text \
514///     <!--comment or text -->"
515/// );
516/// let content = "comment or text ";
517/// let event = BytesText::new(content);
518///
519/// assert_eq!(reader.read_event().unwrap(), Event::DocType(event.borrow()));
520/// assert_eq!(reader.read_event().unwrap(), Event::Text(event.borrow()));
521/// assert_eq!(reader.read_event().unwrap(), Event::Comment(event.borrow()));
522/// // deref coercion of &BytesText to &str
523/// assert_eq!(event.as_ref(), content);
524/// ```
525///
526/// # Lifetime
527///
528/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
529/// In particular, when reader was created from a string, this is lifetime of the string.
530/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
531/// If such event need to outlive the single parsing loop iteration, take ownership of the data
532/// using [`.into_owned()`].
533///
534/// [`Config::check_comments`]: crate::reader::Config::check_comments
535/// [`.into_owned()`]: Self::into_owned
536#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
537pub struct BytesText<'i> {
538    /// Escaped content of the event
539    content: Cow<'i, str>,
540}
541
542impl<'i> BytesText<'i> {
543    /// Creates a new `BytesText` from a string as it appeared in the XML source.
544    #[inline]
545    pub(crate) const fn wrap(content: &'i str) -> Self {
546        Self {
547            content: Cow::Borrowed(content),
548        }
549    }
550
551    /// Creates a new `BytesText` from a raw string as it appeared in the XML source.
552    ///
553    /// # Warning
554    ///
555    /// `content` is not checked to not contain markup or entity references. Be warned
556    /// that writing such event may result to invalid XML if your content contains not
557    /// defined entity references or invalid XML markup.
558    ///
559    /// `content` may have any EOLs, they will be normalized when using [`xml_content()`] getters.
560    ///
561    /// [`xml_content()`]: Self::xml_content
562    #[inline]
563    pub fn from_escaped<C: Into<Cow<'i, str>>>(content: C) -> Self {
564        Self {
565            content: content.into(),
566        }
567    }
568
569    /// Creates a new `BytesText` from a string.
570    ///
571    /// # Warning
572    ///
573    /// `content` will be escaped using the [`escape`] function, but that may change
574    /// in the future, because events produced by the reader never contains `&` or `<`,
575    /// and escaping of `>`, `"` and `'` is not required. If you want to preserve exact
576    /// content, use [`from_escaped()`] method, but be warned that writing such event
577    /// may result to invalid XML if your content contains not defined entity references
578    /// or invalid XML markup.
579    ///
580    /// `content` may have any EOLs, they will be normalized when using [`xml_content()`] getters.
581    ///
582    /// [`escape`]: crate::escape::escape
583    /// [`from_escaped()`]: Self::from_escaped
584    /// [`xml_content()`]: Self::xml_content
585    #[inline]
586    pub fn new(content: &'i str) -> Self {
587        Self::from_escaped(escape(content))
588    }
589
590    /// Ensures that all data is owned to extend the object's lifetime if
591    /// necessary.
592    #[inline]
593    pub fn into_owned(self) -> BytesText<'static> {
594        BytesText {
595            content: Cow::Owned(self.content.into_owned()),
596        }
597    }
598
599    /// Extracts the inner `Cow` from the `BytesText` event container.
600    #[inline]
601    pub fn into_inner(self) -> Cow<'i, str> {
602        self.content
603    }
604
605    /// Converts the event into a borrowed event.
606    #[inline]
607    pub fn borrow(&self) -> BytesText<'_> {
608        BytesText {
609            content: Cow::Borrowed(&self.content),
610        }
611    }
612
613    /// Returns the content of the XML 1.0 or HTML event with EOL normalization applied.
614    ///
615    /// This will allocate if EOL normalization is required.
616    ///
617    /// Note, that this method should be used only if event represents XML 1.0 or HTML content,
618    /// because rules for normalizing EOLs for [XML 1.0] / [HTML] and [XML 1.1] differs.
619    ///
620    /// This method also can be used to get HTML content, because rules the same.
621    ///
622    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
623    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
624    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
625    pub fn xml10_content(&self) -> Cow<'i, str> {
626        match &self.content {
627            Cow::Borrowed(s) => normalize_xml10_eols(s),
628            Cow::Owned(s) => Cow::Owned(normalize_xml10_eols(s).into_owned()),
629        }
630    }
631
632    /// Returns the content of the XML 1.1 event with EOL normalization applied.
633    ///
634    /// This will allocate if EOL normalization is required.
635    ///
636    /// Note, that this method should be used only if event represents XML 1.1 content,
637    /// because rules for normalizing EOLs for [XML 1.0], [XML 1.1] and [HTML] differs.
638    ///
639    /// To get HTML content use [`xml10_content()`](Self::xml10_content).
640    ///
641    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
642    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
643    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
644    pub fn xml11_content(&self) -> Cow<'i, str> {
645        match &self.content {
646            Cow::Borrowed(s) => normalize_xml11_eols(s),
647            Cow::Owned(s) => Cow::Owned(normalize_xml11_eols(s).into_owned()),
648        }
649    }
650
651    /// Returns the content of the XML event with EOL normalization applied
652    /// according to the specified version.
653    ///
654    /// This will allocate if EOL normalization is required.
655    #[inline]
656    pub fn xml_content(&self, version: XmlVersion) -> Cow<'i, str> {
657        match version {
658            XmlVersion::Explicit1_1 => self.xml11_content(),
659            _ => self.xml10_content(),
660        }
661    }
662
663    /// Alias for [`xml10_content()`](Self::xml10_content).
664    #[inline]
665    pub fn html_content(&self) -> Cow<'i, str> {
666        self.xml10_content()
667    }
668
669    /// Removes leading XML whitespace bytes from text content.
670    ///
671    /// Returns `true` if content is empty after that
672    pub fn inplace_trim_start(&mut self) -> bool {
673        self.content = trim_cow(
674            replace(&mut self.content, Cow::Borrowed("")),
675            trim_xml_start,
676        );
677        self.content.is_empty()
678    }
679
680    /// Removes trailing XML whitespace bytes from text content.
681    ///
682    /// Returns `true` if content is empty after that
683    pub fn inplace_trim_end(&mut self) -> bool {
684        self.content = trim_cow(replace(&mut self.content, Cow::Borrowed("")), trim_xml_end);
685        self.content.is_empty()
686    }
687}
688
689impl<'i> Debug for BytesText<'i> {
690    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
691        write!(f, "BytesText {{ content: ")?;
692        write_cow_string(f, &self.content)?;
693        write!(f, " }}")
694    }
695}
696
697impl<'i> Deref for BytesText<'i> {
698    type Target = str;
699
700    fn deref(&self) -> &str {
701        &self.content
702    }
703}
704
705impl AsRef<str> for BytesText<'_> {
706    fn as_ref(&self) -> &str {
707        self
708    }
709}
710
711#[cfg(feature = "arbitrary")]
712impl<'i> arbitrary::Arbitrary<'i> for BytesText<'i> {
713    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
714        let s = <&str>::arbitrary(u)?;
715        if !s.chars().all(char::is_alphanumeric) {
716            return Err(arbitrary::Error::IncorrectFormat);
717        }
718        Ok(Self::new(s))
719    }
720
721    fn size_hint(depth: usize) -> (usize, Option<usize>) {
722        <&str as arbitrary::Arbitrary>::size_hint(depth)
723    }
724}
725
726////////////////////////////////////////////////////////////////////////////////////////////////////
727
728/// CDATA content contains unescaped data from the reader. If you want to write them as a text,
729/// [convert](Self::escape) it to [`BytesText`].
730///
731/// This event implements `Deref<Target = str>`. The `deref()` implementation
732/// returns the content of this event between `<![CDATA[` and `]]>`.
733///
734/// Note, that inner text will not contain `]]>` sequence inside:
735///
736/// ```
737/// # use quick_xml::events::{BytesCData, Event};
738/// # use quick_xml::reader::Reader;
739/// # use pretty_assertions::assert_eq;
740/// let mut reader = Reader::from_str("<![CDATA[ CDATA section ]]>");
741/// let content = " CDATA section ";
742/// let event = BytesCData::new(content);
743///
744/// assert_eq!(reader.read_event().unwrap(), Event::CData(event.borrow()));
745/// // deref coercion of &BytesCData to &str
746/// assert_eq!(event.as_ref(), content);
747/// ```
748///
749/// # Lifetime
750///
751/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
752/// In particular, when reader was created from a string, this is lifetime of the string.
753/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
754/// If such event need to outlive the single parsing loop iteration, take ownership of the data
755/// using [`.into_owned()`].
756///
757/// [`.into_owned()`]: Self::into_owned
758#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
759pub struct BytesCData<'i> {
760    content: Cow<'i, str>,
761}
762
763impl<'i> BytesCData<'i> {
764    /// Creates a new `BytesCData` from a string.
765    #[inline]
766    pub(crate) const fn wrap(content: &'i str) -> Self {
767        Self {
768            content: Cow::Borrowed(content),
769        }
770    }
771
772    /// Creates a new `BytesCData` from a string.
773    ///
774    /// # Warning
775    ///
776    /// `content` must not contain the `]]>` sequence. You can use
777    /// [`BytesCData::escaped`] to escape the content instead.
778    #[inline]
779    pub fn new<C: Into<Cow<'i, str>>>(content: C) -> Self {
780        Self {
781            content: content.into(),
782        }
783    }
784
785    /// Creates an iterator of `BytesCData` from a string.
786    ///
787    /// If a string contains `]]>`, it needs to be split into multiple `CDATA`
788    /// sections, splitting the `]]` and `>` characters, because the CDATA closing
789    /// sequence cannot be escaped. This iterator yields a `BytesCData` instance
790    /// for each of those sections.
791    ///
792    /// # Examples
793    ///
794    /// ```
795    /// # use quick_xml::events::BytesCData;
796    /// # use pretty_assertions::assert_eq;
797    /// let content = "";
798    /// let cdata = BytesCData::escaped(content).collect::<Vec<_>>();
799    /// assert_eq!(cdata, &[BytesCData::new("")]);
800    ///
801    /// let content = "Certain tokens like ]]> can be difficult and <invalid>";
802    /// let cdata = BytesCData::escaped(content).collect::<Vec<_>>();
803    /// assert_eq!(cdata, &[
804    ///     BytesCData::new("Certain tokens like ]]"),
805    ///     BytesCData::new("> can be difficult and <invalid>"),
806    /// ]);
807    ///
808    /// let content = "foo]]>bar]]>baz]]>quux";
809    /// let cdata = BytesCData::escaped(content).collect::<Vec<_>>();
810    /// assert_eq!(cdata, &[
811    ///     BytesCData::new("foo]]"),
812    ///     BytesCData::new(">bar]]"),
813    ///     BytesCData::new(">baz]]"),
814    ///     BytesCData::new(">quux"),
815    /// ]);
816    /// ```
817    #[inline]
818    pub const fn escaped(content: &'i str) -> CDataIterator<'i> {
819        CDataIterator {
820            inner: utils::CDataIterator::new(content),
821        }
822    }
823
824    /// Ensures that all data is owned to extend the object's lifetime if
825    /// necessary.
826    #[inline]
827    pub fn into_owned(self) -> BytesCData<'static> {
828        BytesCData {
829            content: Cow::Owned(self.content.into_owned()),
830        }
831    }
832
833    /// Extracts the inner `Cow` from the `BytesCData` event container.
834    #[inline]
835    pub fn into_inner(self) -> Cow<'i, str> {
836        self.content
837    }
838
839    /// Converts the event into a borrowed event.
840    #[inline]
841    pub fn borrow(&self) -> BytesCData<'_> {
842        BytesCData {
843            content: Cow::Borrowed(&self.content),
844        }
845    }
846
847    /// Converts this CDATA content to an escaped version, that can be written
848    /// as an usual text in XML.
849    ///
850    /// This function performs following replacements:
851    ///
852    /// | Character | Replacement
853    /// |-----------|------------
854    /// | `<`       | `&lt;`
855    /// | `>`       | `&gt;`
856    /// | `&`       | `&amp;`
857    /// | `'`       | `&apos;`
858    /// | `"`       | `&quot;`
859    pub fn escape(self) -> Result<BytesText<'i>, EncodingError> {
860        Ok(match self.content {
861            Cow::Borrowed(s) => BytesText::from_escaped(escape(s)),
862            Cow::Owned(s) => BytesText::from_escaped(escape(&s).into_owned()),
863        })
864    }
865
866    /// Converts this CDATA content to an escaped version, that can be written
867    /// as an usual text in XML.
868    ///
869    /// In XML text content, it is allowed (though not recommended) to leave
870    /// the quote special characters `"` and `'` unescaped.
871    ///
872    /// This function performs following replacements:
873    ///
874    /// | Character | Replacement
875    /// |-----------|------------
876    /// | `<`       | `&lt;`
877    /// | `>`       | `&gt;`
878    /// | `&`       | `&amp;`
879    pub fn partial_escape(self) -> Result<BytesText<'i>, EncodingError> {
880        Ok(match self.content {
881            Cow::Borrowed(s) => BytesText::from_escaped(partial_escape(s)),
882            Cow::Owned(s) => BytesText::from_escaped(partial_escape(&s).into_owned()),
883        })
884    }
885
886    /// Converts this CDATA content to an escaped version, that can be written
887    /// as an usual text in XML. This method escapes only those characters that
888    /// must be escaped according to the [specification].
889    ///
890    /// This function performs following replacements:
891    ///
892    /// | Character | Replacement
893    /// |-----------|------------
894    /// | `<`       | `&lt;`
895    /// | `&`       | `&amp;`
896    ///
897    /// [specification]: https://www.w3.org/TR/xml11/#syntax
898    pub fn minimal_escape(self) -> Result<BytesText<'i>, EncodingError> {
899        Ok(match self.content {
900            Cow::Borrowed(s) => BytesText::from_escaped(minimal_escape(s)),
901            Cow::Owned(s) => BytesText::from_escaped(minimal_escape(&s).into_owned()),
902        })
903    }
904
905    /// Returns the content of the CDATA section of the XML 1.0 or HTML event
906    /// with EOL normalization applied.
907    ///
908    /// This will allocate if EOL normalization is required.
909    ///
910    /// Note, that this method should be used only if event represents XML 1.0 or HTML content,
911    /// because rules for normalizing EOLs for [XML 1.0] / [HTML] and [XML 1.1] differs.
912    ///
913    /// This method also can be used to get HTML content, because rules the same.
914    ///
915    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
916    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
917    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
918    pub fn xml10_content(&self) -> Cow<'i, str> {
919        match &self.content {
920            Cow::Borrowed(s) => normalize_xml10_eols(s),
921            Cow::Owned(s) => Cow::Owned(normalize_xml10_eols(s).into_owned()),
922        }
923    }
924
925    /// Returns the content of the CDATA section of the XML 1.1 event
926    /// with EOL normalization applied.
927    ///
928    /// This will allocate if EOL normalization is required.
929    ///
930    /// Note, that this method should be used only if event represents XML 1.1 content,
931    /// because rules for normalizing EOLs for [XML 1.0], [XML 1.1] and [HTML] differs.
932    ///
933    /// To get HTML content use [`xml10_content()`](Self::xml10_content).
934    ///
935    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
936    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
937    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
938    pub fn xml11_content(&self) -> Cow<'i, str> {
939        match &self.content {
940            Cow::Borrowed(s) => normalize_xml11_eols(s),
941            Cow::Owned(s) => Cow::Owned(normalize_xml11_eols(s).into_owned()),
942        }
943    }
944
945    /// Returns the content of the CDATA section with EOL normalization applied
946    /// according to the specified version.
947    ///
948    /// This will allocate if EOL normalization is required.
949    #[inline]
950    pub fn xml_content(&self, version: XmlVersion) -> Cow<'i, str> {
951        match version {
952            XmlVersion::Explicit1_1 => self.xml11_content(),
953            _ => self.xml10_content(),
954        }
955    }
956
957    /// Alias for [`xml10_content()`](Self::xml10_content).
958    #[inline]
959    pub fn html_content(&self) -> Cow<'i, str> {
960        self.xml10_content()
961    }
962}
963
964impl<'i> Debug for BytesCData<'i> {
965    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
966        write!(f, "BytesCData {{ content: ")?;
967        write_cow_string(f, &self.content)?;
968        write!(f, " }}")
969    }
970}
971
972impl<'i> Deref for BytesCData<'i> {
973    type Target = str;
974
975    fn deref(&self) -> &str {
976        &self.content
977    }
978}
979
980impl AsRef<str> for BytesCData<'_> {
981    fn as_ref(&self) -> &str {
982        self
983    }
984}
985
986#[cfg(feature = "arbitrary")]
987impl<'i> arbitrary::Arbitrary<'i> for BytesCData<'i> {
988    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
989        Ok(Self::new(<&str>::arbitrary(u)?))
990    }
991    fn size_hint(depth: usize) -> (usize, Option<usize>) {
992        <&str as arbitrary::Arbitrary>::size_hint(depth)
993    }
994}
995
996/// Iterator over `CDATA` sections in a string.
997///
998/// This iterator is created by the [`BytesCData::escaped`] method.
999#[derive(Debug, Clone)]
1000pub struct CDataIterator<'a> {
1001    inner: utils::CDataIterator<'a>,
1002}
1003
1004impl<'a> Iterator for CDataIterator<'a> {
1005    type Item = BytesCData<'a>;
1006
1007    fn next(&mut self) -> Option<BytesCData<'a>> {
1008        self.inner.next().map(BytesCData::wrap)
1009    }
1010}
1011
1012impl FusedIterator for CDataIterator<'_> {}
1013
1014////////////////////////////////////////////////////////////////////////////////////////////////////
1015
1016/// [Processing instructions][PI] (PIs) allow documents to contain instructions for applications.
1017///
1018/// This event implements `Deref<Target = str>`. The `deref()` implementation
1019/// returns the content of this event between `<?` and `?>`.
1020///
1021/// Note, that inner text will not contain `?>` sequence inside:
1022///
1023/// ```
1024/// # use quick_xml::events::{BytesPI, Event};
1025/// # use quick_xml::reader::Reader;
1026/// # use pretty_assertions::assert_eq;
1027/// let mut reader = Reader::from_str("<?processing instruction >:-<~ ?>");
1028/// let content = "processing instruction >:-<~ ";
1029/// let event = BytesPI::new(content);
1030///
1031/// assert_eq!(reader.read_event().unwrap(), Event::PI(event.borrow()));
1032/// // deref coercion of &BytesPI to &str
1033/// assert_eq!(event.as_ref(), content);
1034/// ```
1035///
1036/// # Lifetime
1037///
1038/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
1039/// In particular, when reader was created from a string, this is lifetime of the string.
1040/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
1041/// If such event need to outlive the single parsing loop iteration, take ownership of the data
1042/// using [`.into_owned()`].
1043///
1044/// [PI]: https://www.w3.org/TR/xml11/#sec-pi
1045/// [`.into_owned()`]: Self::into_owned
1046#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
1047pub struct BytesPI<'i> {
1048    content: BytesStart<'i>,
1049}
1050
1051impl<'i> BytesPI<'i> {
1052    /// Creates a new `BytesPI` from a string.
1053    #[inline]
1054    pub(crate) const fn wrap(content: &'i str, target_len: usize) -> Self {
1055        Self {
1056            content: BytesStart::wrap(content, target_len),
1057        }
1058    }
1059
1060    /// Creates a new `BytesPI` from a string.
1061    ///
1062    /// # Warning
1063    ///
1064    /// `content` must not contain the `?>` sequence.
1065    #[inline]
1066    pub fn new<C: Into<Cow<'i, str>>>(content: C) -> Self {
1067        let buf: Cow<'i, str> = content.into();
1068        let name_len = name_len(buf.as_bytes());
1069        Self {
1070            content: BytesStart { buf, name_len },
1071        }
1072    }
1073
1074    /// Ensures that all data is owned to extend the object's lifetime if
1075    /// necessary.
1076    #[inline]
1077    pub fn into_owned(self) -> BytesPI<'static> {
1078        BytesPI {
1079            content: self.content.into_owned(),
1080        }
1081    }
1082
1083    /// Extracts the inner `Cow` from the `BytesPI` event container.
1084    #[inline]
1085    pub fn into_inner(self) -> Cow<'i, str> {
1086        self.content.buf
1087    }
1088
1089    /// Converts the event into a borrowed event.
1090    #[inline]
1091    pub fn borrow(&self) -> BytesPI<'_> {
1092        BytesPI {
1093            content: self.content.borrow(),
1094        }
1095    }
1096
1097    /// A target used to identify the application to which the instruction is directed.
1098    ///
1099    /// # Example
1100    ///
1101    /// ```
1102    /// # use pretty_assertions::assert_eq;
1103    /// use quick_xml::events::BytesPI;
1104    ///
1105    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
1106    /// assert_eq!(instruction.target(), "xml-stylesheet");
1107    /// ```
1108    #[inline]
1109    pub fn target(&self) -> &str {
1110        self.content.name().0
1111    }
1112
1113    /// Content of the processing instruction. Contains everything between target
1114    /// name and the end of the instruction. A direct consequence is that the first
1115    /// character is always a space character.
1116    ///
1117    /// # Example
1118    ///
1119    /// ```
1120    /// # use pretty_assertions::assert_eq;
1121    /// use quick_xml::events::BytesPI;
1122    ///
1123    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
1124    /// assert_eq!(instruction.content(), r#" href="style.css""#);
1125    /// ```
1126    #[inline]
1127    pub fn content(&self) -> &str {
1128        self.content.attributes_raw()
1129    }
1130
1131    /// A view of the processing instructions' content as a list of key-value pairs.
1132    ///
1133    /// Key-value pairs are used in some processing instructions, for example in
1134    /// `<?xml-stylesheet?>`.
1135    ///
1136    /// Returned iterator does not validate attribute values as may required by
1137    /// target's rules. For example, it doesn't check that substring `?>` is not
1138    /// present in the attribute value. That shouldn't be the problem when event
1139    /// is produced by the reader, because reader detects end of processing instruction
1140    /// by the first `?>` sequence, as required by the specification, and therefore
1141    /// this sequence cannot appear inside it.
1142    ///
1143    /// # Example
1144    ///
1145    /// ```
1146    /// # use pretty_assertions::assert_eq;
1147    /// use std::borrow::Cow;
1148    /// use quick_xml::events::attributes::Attribute;
1149    /// use quick_xml::events::BytesPI;
1150    /// use quick_xml::name::QName;
1151    ///
1152    /// let instruction = BytesPI::new(r#"xml-stylesheet href="style.css""#);
1153    /// for attr in instruction.attributes() {
1154    ///     assert_eq!(attr, Ok(Attribute {
1155    ///         key: QName("href"),
1156    ///         value: Cow::Borrowed("style.css"),
1157    ///     }));
1158    /// }
1159    /// ```
1160    #[inline]
1161    pub fn attributes(&self) -> Attributes<'_> {
1162        self.content.attributes()
1163    }
1164}
1165
1166impl<'i> Debug for BytesPI<'i> {
1167    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1168        write!(f, "BytesPI {{ content: ")?;
1169        write_cow_string(f, &self.content.buf)?;
1170        write!(f, " }}")
1171    }
1172}
1173
1174impl<'i> Deref for BytesPI<'i> {
1175    type Target = str;
1176
1177    fn deref(&self) -> &str {
1178        &self.content.buf
1179    }
1180}
1181
1182impl AsRef<str> for BytesPI<'_> {
1183    fn as_ref(&self) -> &str {
1184        self
1185    }
1186}
1187
1188#[cfg(feature = "arbitrary")]
1189impl<'i> arbitrary::Arbitrary<'i> for BytesPI<'i> {
1190    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
1191        Ok(Self::new(<&str>::arbitrary(u)?))
1192    }
1193    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1194        <&str as arbitrary::Arbitrary>::size_hint(depth)
1195    }
1196}
1197
1198////////////////////////////////////////////////////////////////////////////////////////////////////
1199
1200/// An XML declaration (`Event::Decl`).
1201///
1202/// [W3C XML 1.1 Prolog and Document Type Declaration](http://w3.org/TR/xml11/#sec-prolog-dtd)
1203///
1204/// This event implements `Deref<Target = str>`. The `deref()` implementation
1205/// returns the content of this event between `<?` and `?>`.
1206///
1207/// Note, that inner text will not contain `?>` sequence inside:
1208///
1209/// ```
1210/// # use quick_xml::events::{BytesDecl, BytesStart, Event};
1211/// # use quick_xml::reader::Reader;
1212/// # use pretty_assertions::assert_eq;
1213/// let mut reader = Reader::from_str("<?xml version = '1.0' ?>");
1214/// let content = "xml version = '1.0' ";
1215/// let event = BytesDecl::from_start(BytesStart::from_content(content, 3));
1216///
1217/// assert_eq!(reader.read_event().unwrap(), Event::Decl(event.borrow()));
1218/// // deref coercion of &BytesDecl to &str
1219/// assert_eq!(event.as_ref(), content);
1220/// ```
1221///
1222/// # Lifetime
1223///
1224/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
1225/// In particular, when reader was created from a string, this is lifetime of the string.
1226/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
1227/// If such event need to outlive the single parsing loop iteration, take ownership of the data
1228/// using [`.into_owned()`].
1229///
1230/// [`.into_owned()`]: Self::into_owned
1231#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
1232pub struct BytesDecl<'i> {
1233    content: BytesStart<'i>,
1234}
1235
1236impl<'i> BytesDecl<'i> {
1237    /// Constructs a new `XmlDecl` from the (mandatory) _version_ (should be `1.0` or `1.1`),
1238    /// the optional _encoding_ (e.g., `UTF-8`) and the optional _standalone_ (`yes` or `no`)
1239    /// attribute.
1240    ///
1241    /// Does not escape any of its inputs. Always uses double quotes to wrap the attribute values.
1242    /// The caller is responsible for escaping attribute values. Shouldn't usually be relevant since
1243    /// the double quote character is not allowed in any of the attribute values.
1244    pub fn new(
1245        version: &str,
1246        encoding: Option<&str>,
1247        standalone: Option<&str>,
1248    ) -> BytesDecl<'static> {
1249        // Compute length of the buffer based on supplied attributes
1250        // ' encoding=""'   => 12
1251        let encoding_attr_len = if let Some(xs) = encoding {
1252            12 + xs.len()
1253        } else {
1254            0
1255        };
1256        // ' standalone=""' => 14
1257        let standalone_attr_len = if let Some(xs) = standalone {
1258            14 + xs.len()
1259        } else {
1260            0
1261        };
1262        // 'xml version=""' => 14
1263        let mut buf = String::with_capacity(14 + encoding_attr_len + standalone_attr_len);
1264
1265        buf.push_str("xml version=\"");
1266        buf.push_str(version);
1267
1268        if let Some(encoding_val) = encoding {
1269            buf.push_str("\" encoding=\"");
1270            buf.push_str(encoding_val);
1271        }
1272
1273        if let Some(standalone_val) = standalone {
1274            buf.push_str("\" standalone=\"");
1275            buf.push_str(standalone_val);
1276        }
1277        buf.push('"');
1278
1279        BytesDecl {
1280            content: BytesStart::from_content(buf, 3),
1281        }
1282    }
1283
1284    /// Creates a `BytesDecl` from a `BytesStart`
1285    pub const fn from_start(start: BytesStart<'i>) -> Self {
1286        Self { content: start }
1287    }
1288
1289    /// Gets xml version, excluding quotes (`'` or `"`).
1290    ///
1291    /// According to the [grammar], the version *must* be the first thing in the declaration.
1292    /// This method tries to extract the first thing in the declaration and return it.
1293    /// In case of multiple attributes value of the first one is returned.
1294    ///
1295    /// If version is missed in the declaration, or the first thing is not a version,
1296    /// [`IllFormedError::MissingDeclVersion`] will be returned.
1297    ///
1298    /// # Examples
1299    ///
1300    /// ```
1301    /// use quick_xml::errors::{Error, IllFormedError};
1302    /// use quick_xml::events::{BytesDecl, BytesStart};
1303    ///
1304    /// // <?xml version='1.1'?>
1305    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1306    /// assert_eq!(decl.version().unwrap(), "1.1");
1307    ///
1308    /// // <?xml version='1.0' version='1.1'?>
1309    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.0' version='1.1'", 0));
1310    /// assert_eq!(decl.version().unwrap(), "1.0");
1311    ///
1312    /// // <?xml encoding='utf-8'?>
1313    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8'", 0));
1314    /// match decl.version() {
1315    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1316    ///     _ => assert!(false),
1317    /// }
1318    ///
1319    /// // <?xml encoding='utf-8' version='1.1'?>
1320    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8' version='1.1'", 0));
1321    /// match decl.version() {
1322    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1323    ///     _ => assert!(false),
1324    /// }
1325    ///
1326    /// // <?xml?>
1327    /// let decl = BytesDecl::from_start(BytesStart::from_content("", 0));
1328    /// match decl.version() {
1329    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))) => {},
1330    ///     _ => assert!(false),
1331    /// }
1332    /// ```
1333    ///
1334    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1335    pub fn version(&self) -> Result<Cow<'_, str>, Error> {
1336        // The version *must* be the first thing in the declaration.
1337        match self.content.attributes().with_checks(false).next() {
1338            Some(Ok(a)) if a.key.as_ref() == "version" => Ok(a.value),
1339            // first attribute was not "version"
1340            Some(Ok(a)) => {
1341                let found = a.key.as_ref().to_string();
1342                Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(
1343                    found,
1344                ))))
1345            }
1346            // error parsing attributes
1347            Some(Err(e)) => Err(e.into()),
1348            // no attributes
1349            None => Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))),
1350        }
1351    }
1352
1353    /// Gets xml encoding, excluding quotes (`'` or `"`).
1354    ///
1355    /// Although according to the [grammar] encoding must appear before `"standalone"`
1356    /// and after `"version"`, this method does not check that. The first occurrence
1357    /// of the attribute will be returned even if there are several. Also, method does
1358    /// not restrict symbols that can forming the encoding, so the returned encoding
1359    /// name may not correspond to the grammar.
1360    ///
1361    /// # Examples
1362    ///
1363    /// ```
1364    /// use std::borrow::Cow;
1365    /// use quick_xml::Error;
1366    /// use quick_xml::events::{BytesDecl, BytesStart};
1367    ///
1368    /// // <?xml version='1.1'?>
1369    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1370    /// assert!(decl.encoding().is_none());
1371    ///
1372    /// // <?xml encoding='utf-8'?>
1373    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8'", 0));
1374    /// match decl.encoding() {
1375    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, "utf-8"),
1376    ///     _ => assert!(false),
1377    /// }
1378    ///
1379    /// // <?xml encoding='something_WRONG' encoding='utf-8'?>
1380    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='something_WRONG' encoding='utf-8'", 0));
1381    /// match decl.encoding() {
1382    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, "something_WRONG"),
1383    ///     _ => assert!(false),
1384    /// }
1385    /// ```
1386    ///
1387    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1388    pub fn encoding(&self) -> Option<Result<Cow<'_, str>, AttrError>> {
1389        self.content
1390            .try_get_attribute("encoding")
1391            .map(|a| a.map(|a| a.value))
1392            .transpose()
1393    }
1394
1395    /// Gets xml standalone, excluding quotes (`'` or `"`).
1396    ///
1397    /// Although according to the [grammar] standalone flag must appear after `"version"`
1398    /// and `"encoding"`, this method does not check that. The first occurrence of the
1399    /// attribute will be returned even if there are several. Also, method does not
1400    /// restrict symbols that can forming the value, so the returned flag name may not
1401    /// correspond to the grammar.
1402    ///
1403    /// # Examples
1404    ///
1405    /// ```
1406    /// use std::borrow::Cow;
1407    /// use quick_xml::Error;
1408    /// use quick_xml::events::{BytesDecl, BytesStart};
1409    ///
1410    /// // <?xml version='1.1'?>
1411    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1412    /// assert!(decl.standalone().is_none());
1413    ///
1414    /// // <?xml standalone='yes'?>
1415    /// let decl = BytesDecl::from_start(BytesStart::from_content(" standalone='yes'", 0));
1416    /// match decl.standalone() {
1417    ///     Some(Ok(Cow::Borrowed(encoding))) => assert_eq!(encoding, "yes"),
1418    ///     _ => assert!(false),
1419    /// }
1420    ///
1421    /// // <?xml standalone='something_WRONG' encoding='utf-8'?>
1422    /// let decl = BytesDecl::from_start(BytesStart::from_content(" standalone='something_WRONG' encoding='utf-8'", 0));
1423    /// match decl.standalone() {
1424    ///     Some(Ok(Cow::Borrowed(flag))) => assert_eq!(flag, "something_WRONG"),
1425    ///     _ => assert!(false),
1426    /// }
1427    /// ```
1428    ///
1429    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1430    pub fn standalone(&self) -> Option<Result<Cow<'_, str>, AttrError>> {
1431        self.content
1432            .try_get_attribute("standalone")
1433            .map(|a| a.map(|a| a.value))
1434            .transpose()
1435    }
1436
1437    /// Gets XML version as typified enumeration.
1438    ///
1439    /// According to the [grammar], the version *must* be the first thing in the declaration.
1440    /// This method tries to extract the first thing in the declaration and return it.
1441    /// In case of multiple attributes value of the first one is returned.
1442    ///
1443    /// If version is missed in the declaration, or the first thing is not a version,
1444    /// [`IllFormedError::MissingDeclVersion`] will be returned.
1445    ///
1446    /// If version is not 1.0 or 1.1, [`IllFormedError::UnknownVersion`] will be returned.
1447    ///
1448    /// # Examples
1449    ///
1450    /// ```
1451    /// use quick_xml::XmlVersion;
1452    /// use quick_xml::errors::{Error, IllFormedError};
1453    /// use quick_xml::events::{BytesDecl, BytesStart};
1454    ///
1455    /// // <?xml version='1.1'?>
1456    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.1'", 0));
1457    /// assert_eq!(decl.xml_version().unwrap(), XmlVersion::Explicit1_1);
1458    ///
1459    /// // <?xml version='1.0' version='1.1'?>
1460    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.0' version='1.1'", 0));
1461    /// assert_eq!(decl.xml_version().unwrap(), XmlVersion::Explicit1_0);
1462    ///
1463    /// // <?xml version='1.2'?>
1464    /// let decl = BytesDecl::from_start(BytesStart::from_content(" version='1.2'", 0));
1465    /// match decl.xml_version() {
1466    ///     Err(Error::IllFormed(IllFormedError::UnknownVersion)) => {},
1467    ///     _ => assert!(false),
1468    /// }
1469    ///
1470    /// // <?xml encoding='utf-8'?>
1471    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8'", 0));
1472    /// match decl.xml_version() {
1473    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1474    ///     _ => assert!(false),
1475    /// }
1476    ///
1477    /// // <?xml encoding='utf-8' version='1.1'?>
1478    /// let decl = BytesDecl::from_start(BytesStart::from_content(" encoding='utf-8' version='1.1'", 0));
1479    /// match decl.xml_version() {
1480    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(Some(key)))) => assert_eq!(key, "encoding"),
1481    ///     _ => assert!(false),
1482    /// }
1483    ///
1484    /// // <?xml?>
1485    /// let decl = BytesDecl::from_start(BytesStart::from_content("", 0));
1486    /// match decl.xml_version() {
1487    ///     Err(Error::IllFormed(IllFormedError::MissingDeclVersion(None))) => {},
1488    ///     _ => assert!(false),
1489    /// }
1490    /// ```
1491    ///
1492    /// [grammar]: https://www.w3.org/TR/xml11/#NT-XMLDecl
1493    pub fn xml_version(&self) -> Result<XmlVersion, Error> {
1494        let v = self.version()?;
1495        match v.as_ref() {
1496            "1.0" => Ok(XmlVersion::Explicit1_0),
1497            "1.1" => Ok(XmlVersion::Explicit1_1),
1498            _ => Err(Error::IllFormed(IllFormedError::UnknownVersion)),
1499        }
1500    }
1501
1502    /// Gets the actual encoding using [_get an encoding_](https://encoding.spec.whatwg.org/#concept-encoding-get)
1503    /// algorithm.
1504    ///
1505    /// If encoding in not known, or `encoding` key was not found, returns `None`.
1506    /// In case of duplicated `encoding` key, encoding, corresponding to the first
1507    /// one, is returned.
1508    #[cfg(feature = "encoding")]
1509    pub fn encoder(&self) -> Option<&'static Encoding> {
1510        self.encoding()
1511            .and_then(|e| e.ok())
1512            .and_then(|e| Encoding::for_label(e.as_bytes()))
1513    }
1514
1515    /// Converts the event into an owned event.
1516    pub fn into_owned(self) -> BytesDecl<'static> {
1517        BytesDecl {
1518            content: self.content.into_owned(),
1519        }
1520    }
1521
1522    /// Converts the event into a borrowed event.
1523    #[inline]
1524    pub fn borrow(&self) -> BytesDecl<'_> {
1525        BytesDecl {
1526            content: self.content.borrow(),
1527        }
1528    }
1529}
1530
1531impl<'i> Deref for BytesDecl<'i> {
1532    type Target = str;
1533
1534    fn deref(&self) -> &str {
1535        &self.content.buf
1536    }
1537}
1538
1539impl AsRef<str> for BytesDecl<'_> {
1540    fn as_ref(&self) -> &str {
1541        self
1542    }
1543}
1544
1545#[cfg(feature = "arbitrary")]
1546impl<'i> arbitrary::Arbitrary<'i> for BytesDecl<'i> {
1547    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
1548        Ok(Self::new(
1549            <&str>::arbitrary(u)?,
1550            Option::<&str>::arbitrary(u)?,
1551            Option::<&str>::arbitrary(u)?,
1552        ))
1553    }
1554
1555    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1556        <&str as arbitrary::Arbitrary>::size_hint(depth)
1557    }
1558}
1559
1560////////////////////////////////////////////////////////////////////////////////////////////////////
1561
1562/// Character or general entity reference (`Event::GeneralRef`): `&ref;` or `&#<number>;`.
1563///
1564/// This event implements `Deref<Target = str>`. The `deref()` implementation
1565/// returns the content of this event between `&` and `;`:
1566///
1567/// ```
1568/// # use quick_xml::events::{BytesRef, Event};
1569/// # use quick_xml::reader::Reader;
1570/// # use pretty_assertions::assert_eq;
1571/// let mut reader = Reader::from_str(r#"&entity;"#);
1572/// let content = "entity";
1573/// let event = BytesRef::new(content);
1574///
1575/// assert_eq!(reader.read_event().unwrap(), Event::GeneralRef(event.borrow()));
1576/// // deref coercion of &BytesRef to &str
1577/// assert_eq!(event.as_ref(), content);
1578/// ```
1579///
1580/// # Lifetime
1581///
1582/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
1583/// In particular, when reader was created from a string, this is lifetime of the string.
1584/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
1585/// If such event need to outlive the single parsing loop iteration, take ownership of the data
1586/// using [`.into_owned()`].
1587///
1588/// [`.into_owned()`]: Self::into_owned
1589#[derive(Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
1590pub struct BytesRef<'i> {
1591    content: Cow<'i, str>,
1592}
1593
1594impl<'i> BytesRef<'i> {
1595    /// Internal constructor, used by `Reader`. Supplies data in reader's encoding
1596    #[inline]
1597    pub(crate) const fn wrap(content: &'i str) -> Self {
1598        Self {
1599            content: Cow::Borrowed(content),
1600        }
1601    }
1602
1603    /// Creates a new `BytesRef` borrowing a slice.
1604    ///
1605    /// # Warning
1606    ///
1607    /// `name` must be a valid name.
1608    #[inline]
1609    pub fn new<C: Into<Cow<'i, str>>>(name: C) -> Self {
1610        Self {
1611            content: name.into(),
1612        }
1613    }
1614
1615    /// Converts the event into an owned event.
1616    pub fn into_owned(self) -> BytesRef<'static> {
1617        BytesRef {
1618            content: Cow::Owned(self.content.into_owned()),
1619        }
1620    }
1621
1622    /// Extracts the inner `Cow` from the `BytesRef` event container.
1623    #[inline]
1624    pub fn into_inner(self) -> Cow<'i, str> {
1625        self.content
1626    }
1627
1628    /// Converts the event into a borrowed event.
1629    #[inline]
1630    pub fn borrow(&self) -> BytesRef<'_> {
1631        BytesRef {
1632            content: Cow::Borrowed(&self.content),
1633        }
1634    }
1635
1636    /// Returns the content of the event as a string.
1637    ///
1638    /// Returns the content of the XML 1.0 or HTML event with EOL normalization applied.
1639    ///
1640    /// This will allocate if EOL normalization is required.
1641    ///
1642    /// Note, that this method should be used only if event represents XML 1.0 or HTML content,
1643    /// because rules for normalizing EOLs for [XML 1.0] / [HTML] and [XML 1.1] differs.
1644    ///
1645    /// This method also can be used to get HTML content, because rules the same.
1646    ///
1647    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
1648    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
1649    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
1650    pub fn xml10_content(&self) -> Cow<'i, str> {
1651        match &self.content {
1652            Cow::Borrowed(s) => normalize_xml10_eols(s),
1653            Cow::Owned(s) => Cow::Owned(normalize_xml10_eols(s).into_owned()),
1654        }
1655    }
1656
1657    /// Returns the content of the XML 1.1 event with EOL normalization applied.
1658    ///
1659    /// This will allocate if EOL normalization is required.
1660    ///
1661    /// Note, that this method should be used only if event represents XML 1.1 content,
1662    /// because rules for normalizing EOLs for [XML 1.0] / [HTML] and [XML 1.1] differs.
1663    ///
1664    /// To get HTML content use [`xml10_content()`](Self::xml10_content).
1665    ///
1666    /// [XML 1.0]: https://www.w3.org/TR/xml/#sec-line-ends
1667    /// [XML 1.1]: https://www.w3.org/TR/xml11/#sec-line-ends
1668    /// [HTML]: https://html.spec.whatwg.org/#normalize-newlines
1669    pub fn xml11_content(&self) -> Cow<'i, str> {
1670        match &self.content {
1671            Cow::Borrowed(s) => normalize_xml11_eols(s),
1672            Cow::Owned(s) => Cow::Owned(normalize_xml11_eols(s).into_owned()),
1673        }
1674    }
1675
1676    /// Returns the content with EOL normalization applied according to the
1677    /// specified version.
1678    ///
1679    /// This will allocate if EOL normalization is required.
1680    #[inline]
1681    pub fn xml_content(&self, version: XmlVersion) -> Cow<'i, str> {
1682        match version {
1683            XmlVersion::Explicit1_1 => self.xml11_content(),
1684            _ => self.xml10_content(),
1685        }
1686    }
1687
1688    /// Alias for [`xml10_content()`](Self::xml10_content).
1689    #[inline]
1690    pub fn html_content(&self) -> Cow<'i, str> {
1691        self.xml10_content()
1692    }
1693
1694    /// Returns `true` if the specified reference represents the character reference
1695    /// (`&#<number>;`).
1696    ///
1697    /// ```
1698    /// # use quick_xml::events::BytesRef;
1699    /// # use pretty_assertions::assert_eq;
1700    /// assert_eq!(BytesRef::new("#x30").is_char_ref(), true);
1701    /// assert_eq!(BytesRef::new("#49" ).is_char_ref(), true);
1702    /// assert_eq!(BytesRef::new("lt"  ).is_char_ref(), false);
1703    /// ```
1704    pub fn is_char_ref(&self) -> bool {
1705        self.content.starts_with('#')
1706    }
1707
1708    /// If this reference represents character reference, then resolves it and
1709    /// returns the character, otherwise returns `None`.
1710    ///
1711    /// This method does not check if character is allowed for XML, in other words,
1712    /// well-formedness constraint [WFC: Legal Char] is not enforced.
1713    /// The character `0x0`, however, will return `EscapeError::InvalidCharRef`.
1714    ///
1715    /// ```
1716    /// # use quick_xml::events::BytesRef;
1717    /// # use pretty_assertions::assert_eq;
1718    /// assert_eq!(BytesRef::new("#x30").resolve_char_ref().unwrap(), Some('0'));
1719    /// assert_eq!(BytesRef::new("#49" ).resolve_char_ref().unwrap(), Some('1'));
1720    /// assert_eq!(BytesRef::new("lt"  ).resolve_char_ref().unwrap(), None);
1721    /// ```
1722    ///
1723    /// [WFC: Legal Char]: https://www.w3.org/TR/xml11/#wf-Legalchar
1724    pub fn resolve_char_ref(&self) -> Result<Option<char>, Error> {
1725        if let Some(num) = self.content.strip_prefix('#') {
1726            let ch = parse_number(num).map_err(EscapeError::InvalidCharRef)?;
1727            return Ok(Some(ch));
1728        }
1729        Ok(None)
1730    }
1731}
1732
1733impl<'i> Debug for BytesRef<'i> {
1734    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1735        write!(f, "BytesRef {{ content: ")?;
1736        write_cow_string(f, &self.content)?;
1737        write!(f, " }}")
1738    }
1739}
1740
1741impl<'i> Deref for BytesRef<'i> {
1742    type Target = str;
1743
1744    fn deref(&self) -> &str {
1745        &self.content
1746    }
1747}
1748
1749impl AsRef<str> for BytesRef<'_> {
1750    fn as_ref(&self) -> &str {
1751        self
1752    }
1753}
1754
1755#[cfg(feature = "arbitrary")]
1756impl<'i> arbitrary::Arbitrary<'i> for BytesRef<'i> {
1757    fn arbitrary(u: &mut arbitrary::Unstructured<'i>) -> arbitrary::Result<Self> {
1758        Ok(Self::new(<&str>::arbitrary(u)?))
1759    }
1760
1761    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1762        <&str as arbitrary::Arbitrary>::size_hint(depth)
1763    }
1764}
1765
1766////////////////////////////////////////////////////////////////////////////////////////////////////
1767
1768/// Event emitted by [`Reader::read_event_into`].
1769///
1770/// # Lifetime
1771///
1772/// `'i` (stands of "input") is a lifetime of the original buffer from which event was parsed.
1773/// In particular, when reader was created from a string, this is lifetime of the string.
1774/// If event come from a buffered reader, this is lifetime of the user-provided buffer.
1775/// If such event need to outlive the single parsing loop iteration, take ownership of the data
1776/// using [`.into_owned()`].
1777///
1778/// [`Reader::read_event_into`]: crate::reader::Reader::read_event_into
1779/// [`.into_owned()`]: Self::into_owned
1780#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
1781#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1782pub enum Event<'i> {
1783    /// Start tag (with attributes) `<tag attr="value">`.
1784    Start(BytesStart<'i>),
1785    /// End tag `</tag>`.
1786    End(BytesEnd<'i>),
1787    /// Empty element tag (with attributes) `<tag attr="value" />`.
1788    Empty(BytesStart<'i>),
1789    /// Escaped character data between tags.
1790    Text(BytesText<'i>),
1791    /// Unescaped character data stored in `<![CDATA[...]]>`.
1792    CData(BytesCData<'i>),
1793    /// Comment `<!-- ... -->`.
1794    Comment(BytesText<'i>),
1795    /// XML declaration `<?xml ...?>`.
1796    Decl(BytesDecl<'i>),
1797    /// Processing instruction `<?...?>`.
1798    PI(BytesPI<'i>),
1799    /// Document type definition data (DTD) stored in `<!DOCTYPE ...>`.
1800    DocType(BytesText<'i>),
1801    /// General reference `&entity;` in the textual data. Can be either an entity
1802    /// reference, or a character reference.
1803    GeneralRef(BytesRef<'i>),
1804    /// End of XML document.
1805    Eof,
1806}
1807
1808impl<'i> Event<'i> {
1809    /// Converts the event to an owned version, untied to the lifetime of
1810    /// buffer used when reading but incurring a new, separate allocation.
1811    pub fn into_owned(self) -> Event<'static> {
1812        match self {
1813            Event::Start(e) => Event::Start(e.into_owned()),
1814            Event::End(e) => Event::End(e.into_owned()),
1815            Event::Empty(e) => Event::Empty(e.into_owned()),
1816            Event::Text(e) => Event::Text(e.into_owned()),
1817            Event::Comment(e) => Event::Comment(e.into_owned()),
1818            Event::CData(e) => Event::CData(e.into_owned()),
1819            Event::Decl(e) => Event::Decl(e.into_owned()),
1820            Event::PI(e) => Event::PI(e.into_owned()),
1821            Event::DocType(e) => Event::DocType(e.into_owned()),
1822            Event::GeneralRef(e) => Event::GeneralRef(e.into_owned()),
1823            Event::Eof => Event::Eof,
1824        }
1825    }
1826
1827    /// Converts the event into a borrowed event.
1828    #[inline]
1829    pub fn borrow(&self) -> Event<'_> {
1830        match self {
1831            Event::Start(e) => Event::Start(e.borrow()),
1832            Event::End(e) => Event::End(e.borrow()),
1833            Event::Empty(e) => Event::Empty(e.borrow()),
1834            Event::Text(e) => Event::Text(e.borrow()),
1835            Event::Comment(e) => Event::Comment(e.borrow()),
1836            Event::CData(e) => Event::CData(e.borrow()),
1837            Event::Decl(e) => Event::Decl(e.borrow()),
1838            Event::PI(e) => Event::PI(e.borrow()),
1839            Event::DocType(e) => Event::DocType(e.borrow()),
1840            Event::GeneralRef(e) => Event::GeneralRef(e.borrow()),
1841            Event::Eof => Event::Eof,
1842        }
1843    }
1844}
1845
1846impl<'i> Deref for Event<'i> {
1847    type Target = str;
1848
1849    fn deref(&self) -> &str {
1850        match *self {
1851            Event::Start(ref e) | Event::Empty(ref e) => e,
1852            Event::End(ref e) => e,
1853            Event::Text(ref e) => e,
1854            Event::Decl(ref e) => e,
1855            Event::PI(ref e) => e,
1856            Event::CData(ref e) => e,
1857            Event::Comment(ref e) => e,
1858            Event::DocType(ref e) => e,
1859            Event::GeneralRef(ref e) => e,
1860            Event::Eof => "",
1861        }
1862    }
1863}
1864
1865impl<'i> AsRef<Event<'i>> for Event<'i> {
1866    fn as_ref(&self) -> &Event<'i> {
1867        self
1868    }
1869}
1870
1871////////////////////////////////////////////////////////////////////////////////////////////////////
1872
1873fn trim_cow<'a, F>(value: Cow<'a, str>, trim: F) -> Cow<'a, str>
1874where
1875    F: for<'s> FnOnce(&'s str) -> &'s str,
1876{
1877    match value {
1878        Cow::Borrowed(s) => Cow::Borrowed(trim(s)),
1879        Cow::Owned(s) => {
1880            let trimmed = trim(&s);
1881            if trimmed.len() != s.len() {
1882                Cow::Owned(trimmed.to_owned())
1883            } else {
1884                Cow::Owned(s)
1885            }
1886        }
1887    }
1888}
1889
1890#[cfg(test)]
1891mod test {
1892    use super::*;
1893    use pretty_assertions::assert_eq;
1894
1895    #[test]
1896    fn bytestart_create() {
1897        let b = BytesStart::new("test");
1898        assert_eq!(b.len(), 4);
1899        assert_eq!(b.name(), QName("test"));
1900    }
1901
1902    #[test]
1903    fn bytestart_set_name() {
1904        let mut b = BytesStart::new("test");
1905        assert_eq!(b.len(), 4);
1906        assert_eq!(b.name(), QName("test"));
1907        assert_eq!(b.attributes_raw(), "");
1908        b.push_attribute(("x", "a"));
1909        assert_eq!(b.len(), 10);
1910        assert_eq!(b.attributes_raw(), " x=\"a\"");
1911        b.set_name("g");
1912        assert_eq!(b.len(), 7);
1913        assert_eq!(b.name(), QName("g"));
1914    }
1915
1916    #[test]
1917    fn bytestart_clear_attributes() {
1918        let mut b = BytesStart::new("test");
1919        b.push_attribute(("x", "y\"z"));
1920        b.push_attribute(("x", "y\"z"));
1921        b.clear_attributes();
1922        assert!(b.attributes().next().is_none());
1923        assert_eq!(b.len(), 4);
1924        assert_eq!(b.name(), QName("test"));
1925    }
1926}