Coverage Report

Created: 2025-10-10 06:53

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