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 /// | `<` | `<`
742 /// | `>` | `>`
743 /// | `&` | `&`
744 /// | `'` | `'`
745 /// | `"` | `"`
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 /// | `<` | `<`
769 /// | `>` | `>`
770 /// | `&` | `&`
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 /// | `<` | `<`
792 /// | `&` | `&`
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}