quick_xml/reader/slice_reader.rs
1//! This is an implementation of [`Reader`] for reading from a `&[u8]` as
2//! underlying byte stream. This implementation supports not using an
3//! intermediate buffer as the byte slice itself can be used to borrow from.
4
5use std::io;
6
7#[cfg(feature = "encoding")]
8use crate::encoding::DetectedEncoding;
9#[cfg(feature = "encoding")]
10use crate::reader::EncodingRef;
11#[cfg(feature = "encoding")]
12use encoding_rs;
13
14use crate::errors::{Error, Result};
15use crate::events::{BytesText, Event};
16use crate::name::QName;
17use crate::parser::Parser;
18use crate::reader::{BangType, ReadRefResult, ReadTextResult, Reader, Span, XmlSource};
19use crate::utils::is_whitespace;
20
21/// This is an implementation for reading from a `&[u8]` as underlying byte stream.
22/// This implementation supports not using an intermediate buffer as the byte slice
23/// itself can be used to borrow from.
24impl<'a> Reader<&'a [u8]> {
25 /// Creates an XML reader from a string slice.
26 #[allow(clippy::should_implement_trait)]
27 pub fn from_str(s: &'a str) -> Self {
28 // Rust strings are guaranteed to be UTF-8, so lock the encoding
29 #[cfg(feature = "encoding")]
30 {
31 let mut reader = Self::from_reader(s.as_bytes());
32 reader.state.encoding = EncodingRef::Explicit(encoding_rs::UTF_8);
33 reader
34 }
35
36 #[cfg(not(feature = "encoding"))]
37 Self::from_reader(s.as_bytes())
38 }
39
40 /// Read an event that borrows from the input rather than a buffer.
41 ///
42 /// There is no asynchronous `read_event_async()` version of this function,
43 /// because it is not necessary -- the contents are already in memory and no IO
44 /// is needed, therefore there is no potential for blocking.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// # use pretty_assertions::assert_eq;
50 /// use quick_xml::events::Event;
51 /// use quick_xml::reader::Reader;
52 ///
53 /// let mut reader = Reader::from_str(r#"
54 /// <tag1 att1 = "test">
55 /// <tag2><!--Test comment-->Test</tag2>
56 /// <tag2>Test 2</tag2>
57 /// </tag1>
58 /// "#);
59 /// reader.config_mut().trim_text(true);
60 ///
61 /// let mut count = 0;
62 /// let mut txt = Vec::new();
63 /// loop {
64 /// match reader.read_event().unwrap() {
65 /// Event::Start(e) => count += 1,
66 /// Event::Text(e) => txt.push(e.into_inner().into_owned()),
67 /// Event::Eof => break,
68 /// _ => (),
69 /// }
70 /// }
71 /// assert_eq!(count, 3);
72 /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
73 /// ```
74 #[inline]
75 pub fn read_event(&mut self) -> Result<Event<'a>> {
76 self.read_event_impl(())
77 }
78
79 /// Reads until end element is found. This function is supposed to be called
80 /// after you already read a [`Start`] event.
81 ///
82 /// Returns a span that cover content between `>` of an opening tag and `<` of
83 /// a closing tag or an empty slice, if [`expand_empty_elements`] is set and
84 /// this method was called after reading expanded [`Start`] event.
85 ///
86 /// Manages nested cases where parent and child elements have the _literally_
87 /// same name.
88 ///
89 /// If a corresponding [`End`] event is not found, an error of type [`Error::IllFormed`]
90 /// will be returned. In particularly, that error will be returned if you call
91 /// this method without consuming the corresponding [`Start`] event first.
92 ///
93 /// The `end` parameter should contain name of the end element _in the reader
94 /// encoding_. It is good practice to always get that parameter using
95 /// [`BytesStart::to_end()`] method.
96 ///
97 /// The correctness of the skipped events does not checked, if you disabled
98 /// the [`check_end_names`] option.
99 ///
100 /// There is no asynchronous `read_to_end_async()` version of this function,
101 /// because it is not necessary -- the contents are already in memory and no IO
102 /// is needed, therefore there is no potential for blocking.
103 ///
104 /// # Namespaces
105 ///
106 /// While the `Reader` does not support namespace resolution, namespaces
107 /// does not change the algorithm for comparing names. Although the names
108 /// `a:name` and `b:name` where both prefixes `a` and `b` resolves to the
109 /// same namespace, are semantically equivalent, `</b:name>` cannot close
110 /// `<a:name>`, because according to [the specification]
111 ///
112 /// > The end of every element that begins with a **start-tag** MUST be marked
113 /// > by an **end-tag** containing a name that echoes the element's type as
114 /// > given in the **start-tag**
115 ///
116 /// # Examples
117 ///
118 /// This example shows, how you can skip XML content after you read the
119 /// start event.
120 ///
121 /// ```
122 /// # use pretty_assertions::assert_eq;
123 /// use quick_xml::events::{BytesStart, Event};
124 /// use quick_xml::reader::Reader;
125 ///
126 /// let mut reader = Reader::from_str(r#"
127 /// <outer>
128 /// <inner>
129 /// <inner></inner>
130 /// <inner/>
131 /// <outer></outer>
132 /// <outer/>
133 /// </inner>
134 /// </outer>
135 /// "#);
136 /// reader.config_mut().trim_text(true);
137 ///
138 /// let start = BytesStart::new("outer");
139 /// let end = start.to_end().into_owned();
140 ///
141 /// // First, we read a start event...
142 /// assert_eq!(reader.read_event().unwrap(), Event::Start(start));
143 ///
144 /// // ...then, we could skip all events to the corresponding end event.
145 /// // This call will correctly handle nested <outer> elements.
146 /// // Note, however, that this method does not handle namespaces.
147 /// reader.read_to_end(end.name()).unwrap();
148 ///
149 /// // At the end we should get an Eof event, because we ate the whole XML
150 /// assert_eq!(reader.read_event().unwrap(), Event::Eof);
151 /// ```
152 ///
153 /// [`Start`]: Event::Start
154 /// [`End`]: Event::End
155 /// [`BytesStart::to_end()`]: crate::events::BytesStart::to_end
156 /// [`expand_empty_elements`]: crate::reader::Config::expand_empty_elements
157 /// [`check_end_names`]: crate::reader::Config::check_end_names
158 /// [the specification]: https://www.w3.org/TR/xml11/#dt-etag
159 pub fn read_to_end(&mut self, end: QName) -> Result<Span> {
160 Ok(read_to_end!(self, end, (), read_event_impl, {}))
161 }
162
163 /// Reads content between start and end tags, including any markup. This
164 /// function is supposed to be called after you already read a [`Start`] event.
165 ///
166 /// Manages nested cases where parent and child elements have the _literally_
167 /// same name.
168 ///
169 /// This method does not unescape read data, instead it returns content
170 /// "as is" of the XML document. This is because it has no idea what text
171 /// it reads, and if, for example, it contains CDATA section, attempt to
172 /// unescape it content will spoil data.
173 ///
174 /// Actually, this method perform the following code:
175 ///
176 /// ```ignore
177 /// let span = reader.read_to_end(end)?;
178 /// let text = &reader.inner_slice[span];
179 /// ```
180 ///
181 /// # Examples
182 ///
183 /// This example shows, how you can read a HTML content from your XML document.
184 ///
185 /// ```
186 /// # use pretty_assertions::assert_eq;
187 /// # use std::borrow::Cow;
188 /// use quick_xml::events::{BytesStart, Event};
189 /// use quick_xml::reader::Reader;
190 ///
191 /// let mut reader = Reader::from_str("
192 /// <html>
193 /// <title>This is a HTML text</title>
194 /// <p>Usual XML rules does not apply inside it
195 /// <p>For example, elements not needed to be "closed"
196 /// </html>
197 /// ");
198 /// reader.config_mut().trim_text(true);
199 ///
200 /// let start = BytesStart::new("html");
201 /// let end = start.to_end().into_owned();
202 ///
203 /// // First, we read a start event...
204 /// assert_eq!(reader.read_event().unwrap(), Event::Start(start));
205 /// // ...and disable checking of end names because we expect HTML further...
206 /// reader.config_mut().check_end_names = false;
207 ///
208 /// // ...then, we could read text content until close tag.
209 /// // This call will correctly handle nested <html> elements.
210 /// let text = reader.read_text(end.name()).unwrap();
211 /// let text = text.into_inner();
212 /// assert_eq!(text, r#"
213 /// <title>This is a HTML text</title>
214 /// <p>Usual XML rules does not apply inside it
215 /// <p>For example, elements not needed to be "closed"
216 /// "#);
217 /// assert!(matches!(text, Cow::Borrowed(_)));
218 ///
219 /// // Now we can enable checks again
220 /// reader.config_mut().check_end_names = true;
221 ///
222 /// // At the end we should get an Eof event, because we ate the whole XML
223 /// assert_eq!(reader.read_event().unwrap(), Event::Eof);
224 /// ```
225 ///
226 /// [`Start`]: Event::Start
227 pub fn read_text(&mut self, end: QName) -> Result<BytesText<'a>> {
228 // self.reader will be changed, so store original reference
229 let buffer = self.reader;
230 let span = self.read_to_end(end)?;
231
232 let len = span.end - span.start;
233 // SAFETY: `span` can only contain indexes up to usize::MAX because it
234 // was created from offsets from a single &[u8] slice
235 // Could use from_utf8_unchecked: buffer was validated during event parsing
236 let text = std::str::from_utf8(&buffer[0..len as usize])?;
237 Ok(BytesText::wrap(text))
238 }
239}
240
241////////////////////////////////////////////////////////////////////////////////////////////////////
242
243/// Implementation of `XmlSource` for `&[u8]` reader using a `Self` as buffer
244/// that will be borrowed by events. This implementation provides a zero-copy deserialization.
245///
246/// Note: When the reader is created via [`Reader::from_str`], the input is
247/// guaranteed to be valid UTF-8. In that case, the `from_utf8` calls below
248/// could safely use `from_utf8_unchecked`. However, `Reader::from_reader`
249/// also instantiates this impl with arbitrary bytes, so we must validate.
250impl<'a> XmlSource<'a, ()> for &'a [u8] {
251 #[cfg(not(feature = "encoding"))]
252 #[inline]
253 fn remove_utf8_bom(&mut self) -> io::Result<()> {
254 if self.starts_with(crate::encoding::UTF8_BOM) {
255 *self = &self[crate::encoding::UTF8_BOM.len()..];
256 }
257 Ok(())
258 }
259
260 #[cfg(feature = "encoding")]
261 #[inline]
262 fn detect_encoding(&mut self) -> io::Result<Option<DetectedEncoding>> {
263 if let Some(detected) = crate::encoding::detect_encoding(self) {
264 *self = &self[detected.bom_len() as usize..];
265 return Ok(Some(detected));
266 }
267 Ok(None)
268 }
269
270 #[inline]
271 fn read_text(&mut self, _buf: (), position: &mut u64) -> ReadTextResult<'a, ()> {
272 // Search for start of markup or an entity or character reference
273 match memchr::memchr2(b'<', b'&', self) {
274 Some(0) if self[0] == b'<' => ReadTextResult::Markup(()),
275 // Do not consume `&` because it may be lone and we would be need to
276 // return it as part of Text event
277 Some(0) => ReadTextResult::Ref(()),
278
279 Some(i) if self[i] == b'<' => {
280 let (bytes, rest) = self.split_at(i);
281 *self = rest;
282 *position += i as u64;
283 match std::str::from_utf8(bytes) {
284 Ok(s) => ReadTextResult::UpToMarkup(s),
285 Err(e) => ReadTextResult::Err(e.into()),
286 }
287 }
288 Some(i) => {
289 let (bytes, rest) = self.split_at(i);
290 *self = rest;
291 *position += i as u64;
292 match std::str::from_utf8(bytes) {
293 Ok(s) => ReadTextResult::UpToRef(s),
294 Err(e) => ReadTextResult::Err(e.into()),
295 }
296 }
297 None => {
298 let bytes = &self[..];
299 *self = &[];
300 *position += bytes.len() as u64;
301 match std::str::from_utf8(bytes) {
302 Ok(s) => ReadTextResult::UpToEof(s),
303 Err(e) => ReadTextResult::Err(e.into()),
304 }
305 }
306 }
307 }
308
309 #[inline]
310 fn read_ref(&mut self, _buf: (), position: &mut u64) -> ReadRefResult<'a> {
311 debug_assert!(
312 self.starts_with(b"&"),
313 "`read_ref` must be called at `&`:\n{:?}",
314 crate::utils::Bytes(self)
315 );
316 // Search for the end of reference or a start of another reference or a markup
317 match memchr::memchr3(b';', b'&', b'<', &self[1..]) {
318 Some(i) if self[i + 1] == b';' => {
319 // +1 for the start `&`
320 // +1 for the end `;`
321 let end = i + 2;
322 let (bytes, rest) = self.split_at(end);
323 *self = rest;
324 *position += end as u64;
325
326 match std::str::from_utf8(bytes) {
327 Ok(s) => ReadRefResult::Ref(s),
328 Err(e) => ReadRefResult::Err(e.into()),
329 }
330 }
331 // Do not consume `&` because it may be lone and we would be need to
332 // return it as part of Text event
333 Some(i) => {
334 let is_amp = self[i + 1] == b'&';
335 let (bytes, rest) = self.split_at(i + 1);
336 *self = rest;
337 *position += i as u64 + 1;
338
339 match std::str::from_utf8(bytes) {
340 Ok(s) => {
341 if is_amp {
342 ReadRefResult::UpToRef(s)
343 } else {
344 ReadRefResult::UpToMarkup(s)
345 }
346 }
347 Err(e) => ReadRefResult::Err(e.into()),
348 }
349 }
350 None => {
351 let bytes = &self[..];
352 *self = &[];
353 *position += bytes.len() as u64;
354
355 match std::str::from_utf8(bytes) {
356 Ok(s) => ReadRefResult::UpToEof(s),
357 Err(e) => ReadRefResult::Err(e.into()),
358 }
359 }
360 }
361 }
362
363 #[inline]
364 fn read_with<P>(&mut self, mut parser: P, _buf: (), position: &mut u64) -> Result<&'a str>
365 where
366 P: Parser,
367 {
368 if let Some(i) = parser.feed(self) {
369 let used = i + 1; // +1 for `>`
370 *position += used as u64;
371 let (bytes, rest) = self.split_at(used);
372 *self = rest;
373 return Ok(std::str::from_utf8(bytes)?);
374 }
375
376 *position += self.len() as u64;
377 Err(Error::Syntax(parser.eof_error(self)))
378 }
379
380 #[inline]
381 fn read_bang_element(&mut self, _buf: (), position: &mut u64) -> Result<(BangType, &'a str)> {
382 // Peeked one bang ('!') before being called, so it's guaranteed to
383 // start with it.
384 debug_assert!(
385 self.starts_with(b"<!"),
386 "`read_bang_element` must be called at `<!`:\n{:?}",
387 crate::utils::Bytes(self)
388 );
389
390 let mut bang_type = BangType::new(self.get(2).copied())?;
391
392 if let Some(i) = bang_type.feed(&[], self) {
393 let consumed = i + 1; // +1 for `>`
394 *position += consumed as u64;
395 let (bytes, rest) = self.split_at(consumed);
396 *self = rest;
397 return Ok((bang_type, std::str::from_utf8(bytes)?));
398 }
399
400 *position += self.len() as u64;
401 Err(Error::Syntax(bang_type.to_err()))
402 }
403
404 #[inline]
405 fn skip_whitespace(&mut self, position: &mut u64) -> io::Result<()> {
406 let whitespaces = self
407 .iter()
408 .position(|b| !is_whitespace(*b))
409 .unwrap_or(self.len());
410 *position += whitespaces as u64;
411 *self = &self[whitespaces..];
412 Ok(())
413 }
414
415 #[inline]
416 fn peek_one(&mut self) -> io::Result<Option<u8>> {
417 debug_assert!(
418 self.starts_with(b"<"),
419 "markup must start from '<':\n{:?}",
420 crate::utils::Bytes(self)
421 );
422 Ok(self.get(1).copied())
423 }
424}
425
426#[cfg(test)]
427mod test {
428 use crate::reader::XmlSource;
429 use crate::reader::test::check;
430
431 /// Default buffer constructor just pass the byte array from the test
432 fn identity<T>(input: T) -> T {
433 input
434 }
435
436 check!(
437 #[test]
438 read_event_impl,
439 identity,
440 0,
441 ()
442 );
443}