Skip to main content

quick_xml/reader/
async_tokio.rs

1//! This is an implementation of [`Reader`] for reading from a [`AsyncBufRead`]
2//! as underlying byte stream. This reader fully implements async/await so reading
3//! can use non-blocking I/O.
4
5use std::pin::Pin;
6use std::task::{Context, Poll};
7
8use tokio::io::{self, AsyncBufRead, AsyncBufReadExt, AsyncRead, ReadBuf};
9
10use crate::encoding;
11use crate::errors::{Error, IllFormedError, Result, SyntaxError};
12use crate::events::{BytesRef, BytesText, Event};
13use crate::name::{QName, ResolveResult};
14use crate::parser::{ElementParser, Parser, PiParser};
15use crate::reader::buffered_reader::impl_buffered_source;
16use crate::reader::{
17    BangType, BinaryStream, NsReader, ParseState, ReadRefResult, ReadTextResult, Reader, Span,
18};
19use crate::utils::is_whitespace;
20
21/// A struct for read XML asynchronously from an [`AsyncBufRead`].
22///
23/// Having own struct allows us to implement anything without risk of name conflicts
24/// and does not suffer from the impossibility of having `async` in traits.
25struct TokioAdapter<'a, R>(&'a mut R);
26
27impl<'a, R: AsyncBufRead + Unpin> TokioAdapter<'a, R> {
28    impl_buffered_source!('b, 0, async, await);
29}
30
31////////////////////////////////////////////////////////////////////////////////////////////////////
32
33impl<'r, R> AsyncRead for BinaryStream<'r, R>
34where
35    R: AsyncRead + Unpin,
36{
37    fn poll_read(
38        self: Pin<&mut Self>,
39        cx: &mut Context<'_>,
40        buf: &mut ReadBuf<'_>,
41    ) -> Poll<io::Result<()>> {
42        let start = buf.remaining();
43        let this = self.get_mut();
44        let poll = Pin::new(&mut *this.inner).poll_read(cx, buf);
45
46        // If something was read, update offset
47        if let Poll::Ready(Ok(_)) = poll {
48            let amt = start - buf.remaining();
49            *this.offset += amt as u64;
50        }
51        poll
52    }
53}
54
55impl<'r, R> AsyncBufRead for BinaryStream<'r, R>
56where
57    R: AsyncBufRead + Unpin,
58{
59    #[inline]
60    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
61        Pin::new(&mut *self.get_mut().inner).poll_fill_buf(cx)
62    }
63
64    #[inline]
65    fn consume(self: Pin<&mut Self>, amt: usize) {
66        let this = self.get_mut();
67        this.inner.consume(amt);
68        *this.offset += amt as u64;
69    }
70}
71
72////////////////////////////////////////////////////////////////////////////////////////////////////
73
74impl<R: AsyncBufRead + Unpin> Reader<R> {
75    /// An asynchronous version of [`read_event_into()`]. Reads the next event into
76    /// given buffer.
77    ///
78    /// This is the main entry point for reading XML `Event`s when using an async reader.
79    ///
80    /// See the documentation of [`read_event_into()`] for more information.
81    ///
82    /// # Examples
83    ///
84    /// ```
85    /// # tokio_test::block_on(async {
86    /// # use pretty_assertions::assert_eq;
87    /// use quick_xml::events::Event;
88    /// use quick_xml::reader::Reader;
89    ///
90    /// // This explicitly uses `from_reader("...".as_bytes())` to use a buffered
91    /// // reader instead of relying on the zero-copy optimizations for reading
92    /// // from byte slices, which provides the sync interface anyway.
93    /// let mut reader = Reader::from_reader(r#"
94    ///     <tag1 att1 = "test">
95    ///        <tag2><!--Test comment-->Test</tag2>
96    ///        <tag2>Test 2</tag2>
97    ///     </tag1>
98    /// "#.as_bytes());
99    /// reader.config_mut().trim_text(true);
100    ///
101    /// let mut count = 0;
102    /// let mut buf = Vec::new();
103    /// let mut txt = Vec::new();
104    /// loop {
105    ///     match reader.read_event_into_async(&mut buf).await {
106    ///         Ok(Event::Start(_)) => count += 1,
107    ///         Ok(Event::Text(e)) => txt.push(e.into_inner().into_owned()),
108    ///         Err(e) => panic!("Error at position {}: {:?}", reader.error_position(), e),
109    ///         Ok(Event::Eof) => break,
110    ///         _ => (),
111    ///     }
112    ///     buf.clear();
113    /// }
114    /// assert_eq!(count, 3);
115    /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
116    /// # }) // tokio_test::block_on
117    /// ```
118    ///
119    /// [`read_event_into()`]: Reader::read_event_into
120    pub async fn read_event_into_async<'b>(
121        &mut self,
122        mut buf: &'b mut Vec<u8>,
123    ) -> Result<Event<'b>> {
124        read_event_impl!(
125            self,
126            buf,
127            TokioAdapter(&mut self.reader),
128            read_until_close_async,
129            await
130        )
131    }
132
133    /// An asynchronous version of [`read_to_end_into()`].
134    /// Reads asynchronously until end element is found using provided buffer as
135    /// intermediate storage for events content. This function is supposed to be
136    /// called after you already read a [`Start`] event.
137    ///
138    /// See the documentation of [`read_to_end_into()`] for more information.
139    ///
140    /// # Examples
141    ///
142    /// This example shows, how you can skip XML content after you read the
143    /// start event.
144    ///
145    /// ```
146    /// # tokio_test::block_on(async {
147    /// # use pretty_assertions::assert_eq;
148    /// use quick_xml::events::{BytesStart, Event};
149    /// use quick_xml::reader::Reader;
150    ///
151    /// let mut reader = Reader::from_reader(r#"
152    ///     <outer>
153    ///         <inner>
154    ///             <inner></inner>
155    ///             <inner/>
156    ///             <outer></outer>
157    ///             <outer/>
158    ///         </inner>
159    ///     </outer>
160    /// "#.as_bytes());
161    /// reader.config_mut().trim_text(true);
162    /// let mut buf = Vec::new();
163    ///
164    /// let start = BytesStart::new("outer");
165    /// let end   = start.to_end().into_owned();
166    ///
167    /// // First, we read a start event...
168    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Start(start));
169    ///
170    /// // ...then, we could skip all events to the corresponding end event.
171    /// // This call will correctly handle nested <outer> elements.
172    /// // Note, however, that this method does not handle namespaces.
173    /// reader.read_to_end_into_async(end.name(), &mut buf).await.unwrap();
174    ///
175    /// // At the end we should get an Eof event, because we ate the whole XML
176    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Eof);
177    /// # }) // tokio_test::block_on
178    /// ```
179    ///
180    /// [`read_to_end_into()`]: Self::read_to_end_into
181    /// [`Start`]: Event::Start
182    pub async fn read_to_end_into_async<'n>(
183        &mut self,
184        // We should name that lifetime due to https://github.com/rust-lang/rust/issues/63033
185        end: QName<'n>,
186        buf: &mut Vec<u8>,
187    ) -> Result<Span> {
188        Ok(read_to_end!(
189            self,
190            end,
191            buf,
192            read_event_into_async,
193            {
194                buf.clear();
195            },
196            await
197        ))
198    }
199
200    /// An asynchronous version of [`read_text_into()`].
201    /// Reads asynchronously until end element is found using provided buffer as
202    /// intermediate storage for events content. This function is supposed to be
203    /// called after you already read a [`Start`] event.
204    ///
205    /// See the documentation of [`read_text_into()`] for more information.
206    ///
207    /// # Examples
208    ///
209    /// This example shows, how you can read a HTML content from your XML document.
210    ///
211    /// ```
212    /// # tokio_test::block_on(async {
213    /// # use pretty_assertions::assert_eq;
214    /// # use std::borrow::Cow;
215    /// use quick_xml::events::{BytesStart, Event};
216    /// use quick_xml::reader::Reader;
217    ///
218    /// let mut reader = Reader::from_reader("
219    ///     <html>
220    ///         <title>This is a HTML text</title>
221    ///         <p>Usual XML rules does not apply inside it
222    ///         <p>For example, elements not needed to be &quot;closed&quot;
223    ///     </html>
224    /// ".as_bytes());
225    /// reader.config_mut().trim_text(true);
226    ///
227    /// let start = BytesStart::new("html");
228    /// let end   = start.to_end().into_owned();
229    ///
230    /// let mut buf = Vec::new();
231    ///
232    /// // First, we read a start event...
233    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Start(start));
234    /// // ...and disable checking of end names because we expect HTML further...
235    /// reader.config_mut().check_end_names = false;
236    ///
237    /// // ...then, we could read text content until close tag.
238    /// // This call will correctly handle nested <html> elements.
239    /// let text = reader.read_text_into_async(end.name(), &mut buf).await.unwrap();
240    /// let text = text.into_inner();
241    /// assert_eq!(text, r#"
242    ///         <title>This is a HTML text</title>
243    ///         <p>Usual XML rules does not apply inside it
244    ///         <p>For example, elements not needed to be &quot;closed&quot;
245    ///     "#);
246    /// assert!(matches!(text, Cow::Borrowed(_)));
247    ///
248    /// // Now we can enable checks again
249    /// reader.config_mut().check_end_names = true;
250    ///
251    /// // At the end we should get an Eof event, because we ate the whole XML
252    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Eof);
253    /// # }) // tokio_test::block_on
254    /// ```
255    ///
256    /// [`read_text_into()`]: Self::read_text_into
257    /// [`Start`]: Event::Start
258    pub async fn read_text_into_async<'n, 'b>(
259        &mut self,
260        // We should name that lifetime due to https://github.com/rust-lang/rust/issues/63033
261        end: QName<'n>,
262        buf: &'b mut Vec<u8>,
263    ) -> Result<BytesText<'b>> {
264        let start = buf.len();
265        let span = read_to_end!(self, end, buf, read_event_into_async, {}, await);
266
267        let len = span.end - span.start;
268        // SAFETY: `buf` may contain not more than isize::MAX bytes and because it is
269        // not cleared when reading event, length of the returned span should fit into
270        // usize (because otherwise we panic at appending to the buffer before that point)
271        let end = start + len as usize;
272
273        let text = std::str::from_utf8(&buf[start..end])?;
274        Ok(BytesText::wrap(text))
275    }
276
277    /// Private function to read until `>` is found. This function expects that
278    /// it was called just after encounter a `<` symbol.
279    async fn read_until_close_async<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>> {
280        read_until_close!(self, buf, TokioAdapter(&mut self.reader), await)
281    }
282}
283
284////////////////////////////////////////////////////////////////////////////////////////////////////
285
286impl<R: AsyncBufRead + Unpin> NsReader<R> {
287    /// An asynchronous version of [`read_event_into()`]. Reads the next event into
288    /// given buffer.
289    ///
290    /// This method manages namespaces but doesn't resolve them automatically.
291    /// You should call [`resolver().resolve_element()`] if you want to get a namespace.
292    ///
293    /// You also can use [`read_resolved_event_into_async()`] instead if you want
294    /// to resolve namespace as soon as you get an event.
295    ///
296    /// # Examples
297    ///
298    /// ```
299    /// # tokio_test::block_on(async {
300    /// # use pretty_assertions::assert_eq;
301    /// use quick_xml::events::Event;
302    /// use quick_xml::name::{Namespace, ResolveResult::*};
303    /// use quick_xml::reader::NsReader;
304    ///
305    /// let mut reader = NsReader::from_reader(r#"
306    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
307    ///        <y:tag2><!--Test comment-->Test</y:tag2>
308    ///        <y:tag2>Test 2</y:tag2>
309    ///     </x:tag1>
310    /// "#.as_bytes());
311    /// reader.config_mut().trim_text(true);
312    ///
313    /// let mut count = 0;
314    /// let mut buf = Vec::new();
315    /// let mut txt = Vec::new();
316    /// loop {
317    ///     match reader.read_event_into_async(&mut buf).await.unwrap() {
318    ///         Event::Start(e) => {
319    ///             count += 1;
320    ///             let (ns, local) = reader.resolver().resolve_element(e.name());
321    ///             match local.as_ref() {
322    ///                 "tag1" => assert_eq!(ns, Bound(Namespace("www.xxxx"))),
323    ///                 "tag2" => assert_eq!(ns, Bound(Namespace("www.yyyy"))),
324    ///                 _ => unreachable!(),
325    ///             }
326    ///         }
327    ///         Event::Text(e) => {
328    ///             txt.push(e.into_inner().into_owned())
329    ///         }
330    ///         Event::Eof => break,
331    ///         _ => (),
332    ///     }
333    ///     buf.clear();
334    /// }
335    /// assert_eq!(count, 3);
336    /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
337    /// # }) // tokio_test::block_on
338    /// ```
339    ///
340    /// [`read_event_into()`]: NsReader::read_event_into
341    /// [`resolver().resolve_element()`]: crate::name::NamespaceResolver::resolve_element
342    /// [`read_resolved_event_into_async()`]: Self::read_resolved_event_into_async
343    pub async fn read_event_into_async<'b>(&mut self, buf: &'b mut Vec<u8>) -> Result<Event<'b>> {
344        self.pop();
345        let event = self.reader.read_event_into_async(buf).await;
346        self.process_event(event)
347    }
348
349    /// An asynchronous version of [`read_to_end_into()`].
350    /// Reads asynchronously until end element is found using provided buffer as
351    /// intermediate storage for events content. This function is supposed to be
352    /// called after you already read a [`Start`] event.
353    ///
354    /// See the documentation of [`read_to_end_into()`] for more information.
355    ///
356    /// # Examples
357    ///
358    /// This example shows, how you can skip XML content after you read the
359    /// start event.
360    ///
361    /// ```
362    /// # tokio_test::block_on(async {
363    /// # use pretty_assertions::assert_eq;
364    /// use quick_xml::name::{Namespace, ResolveResult};
365    /// use quick_xml::events::{BytesStart, Event};
366    /// use quick_xml::reader::NsReader;
367    ///
368    /// let mut reader = NsReader::from_reader(r#"
369    ///     <outer xmlns="namespace 1">
370    ///         <inner xmlns="namespace 2">
371    ///             <outer></outer>
372    ///         </inner>
373    ///         <inner>
374    ///             <inner></inner>
375    ///             <inner/>
376    ///             <outer></outer>
377    ///             <p:outer xmlns:p="ns"></p:outer>
378    ///             <outer/>
379    ///         </inner>
380    ///     </outer>
381    /// "#.as_bytes());
382    /// reader.config_mut().trim_text(true);
383    /// let mut buf = Vec::new();
384    ///
385    /// let ns = Namespace("namespace 1");
386    /// let start = BytesStart::from_content(r#"outer xmlns="namespace 1""#, 5);
387    /// let end   = start.to_end().into_owned();
388    ///
389    /// // First, we read a start event...
390    /// assert_eq!(
391    ///     reader.read_resolved_event_into_async(&mut buf).await.unwrap(),
392    ///     (ResolveResult::Bound(ns), Event::Start(start))
393    /// );
394    ///
395    /// // ...then, we could skip all events to the corresponding end event.
396    /// // This call will correctly handle nested <outer> elements.
397    /// // Note, however, that this method does not handle namespaces.
398    /// reader.read_to_end_into_async(end.name(), &mut buf).await.unwrap();
399    ///
400    /// // At the end we should get an Eof event, because we ate the whole XML
401    /// assert_eq!(
402    ///     reader.read_resolved_event_into_async(&mut buf).await.unwrap(),
403    ///     (ResolveResult::Unbound, Event::Eof)
404    /// );
405    /// # }) // tokio_test::block_on
406    /// ```
407    ///
408    /// [`read_to_end_into()`]: Self::read_to_end_into
409    /// [`Start`]: Event::Start
410    pub async fn read_to_end_into_async<'n>(
411        &mut self,
412        // We should name that lifetime due to https://github.com/rust-lang/rust/issues/63033`
413        end: QName<'n>,
414        buf: &mut Vec<u8>,
415    ) -> Result<Span> {
416        // According to the https://www.w3.org/TR/xml11/#dt-etag, end name should
417        // match literally the start name. See `Config::check_end_names` documentation
418        let result = self.reader.read_to_end_into_async(end, buf).await?;
419        // read_to_end_into_async will consume closing tag. Because nobody can access to its
420        // content anymore, we directly pop namespace of the opening tag
421        self.ns_resolver.pop();
422        Ok(result)
423    }
424
425    /// An asynchronous version of [`read_text_into()`].
426    /// Reads asynchronously until end element is found using provided buffer as
427    /// intermediate storage for events content. This function is supposed to be
428    /// called after you already read a [`Start`] event.
429    ///
430    /// See the documentation of [`read_text_into()`] for more information.
431    ///
432    /// # Examples
433    ///
434    /// This example shows, how you can read a HTML content from your XML document.
435    ///
436    /// ```
437    /// # tokio_test::block_on(async {
438    /// # use pretty_assertions::assert_eq;
439    /// # use std::borrow::Cow;
440    /// use quick_xml::events::{BytesStart, Event};
441    /// use quick_xml::reader::NsReader;
442    ///
443    /// let mut reader = NsReader::from_reader("
444    ///     <html>
445    ///         <title>This is a HTML text</title>
446    ///         <p>Usual XML rules does not apply inside it
447    ///         <p>For example, elements not needed to be &quot;closed&quot;
448    ///     </html>
449    /// ".as_bytes());
450    /// reader.config_mut().trim_text(true);
451    ///
452    /// let start = BytesStart::new("html");
453    /// let end   = start.to_end().into_owned();
454    ///
455    /// let mut buf = Vec::new();
456    ///
457    /// // First, we read a start event...
458    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Start(start));
459    /// // ...and disable checking of end names because we expect HTML further...
460    /// reader.config_mut().check_end_names = false;
461    ///
462    /// // ...then, we could read text content until close tag.
463    /// // This call will correctly handle nested <html> elements.
464    /// let text = reader.read_text_into_async(end.name(), &mut buf).await.unwrap();
465    /// let text = text.into_inner();
466    /// assert_eq!(text, r#"
467    ///         <title>This is a HTML text</title>
468    ///         <p>Usual XML rules does not apply inside it
469    ///         <p>For example, elements not needed to be &quot;closed&quot;
470    ///     "#);
471    /// assert!(matches!(text, Cow::Borrowed(_)));
472    ///
473    /// // Now we can enable checks again
474    /// reader.config_mut().check_end_names = true;
475    ///
476    /// // At the end we should get an Eof event, because we ate the whole XML
477    /// assert_eq!(reader.read_event_into_async(&mut buf).await.unwrap(), Event::Eof);
478    /// # }) // tokio_test::block_on
479    /// ```
480    ///
481    /// [`read_text_into()`]: Self::read_text_into
482    /// [`Start`]: Event::Start
483    pub async fn read_text_into_async<'n, 'b>(
484        &mut self,
485        // We should name that lifetime due to https://github.com/rust-lang/rust/issues/63033
486        end: QName<'n>,
487        buf: &'b mut Vec<u8>,
488    ) -> Result<BytesText<'b>> {
489        // According to the https://www.w3.org/TR/xml11/#dt-etag, end name should
490        // match literally the start name. See `Config::check_end_names` documentation
491        let result = self.reader.read_text_into_async(end, buf).await?;
492        // read_text_into_async will consume closing tag. Because nobody can access to its
493        // content anymore, we directly pop namespace of the opening tag
494        self.ns_resolver.pop();
495        Ok(result)
496    }
497
498    /// An asynchronous version of [`read_resolved_event_into()`]. Reads the next
499    /// event into given buffer asynchronously and resolves its namespace (if applicable).
500    ///
501    /// Namespace is resolved only for [`Start`], [`Empty`] and [`End`] events.
502    /// For all other events the concept of namespace is not defined, so
503    /// a [`ResolveResult::Unbound`] is returned.
504    ///
505    /// If you are not interested in namespaces, you can use [`read_event_into_async()`]
506    /// which will not automatically resolve namespaces for you.
507    ///
508    /// # Examples
509    ///
510    /// ```
511    /// # tokio_test::block_on(async {
512    /// # use pretty_assertions::assert_eq;
513    /// use quick_xml::events::Event;
514    /// use quick_xml::name::{Namespace, QName, ResolveResult::*};
515    /// use quick_xml::reader::NsReader;
516    ///
517    /// let mut reader = NsReader::from_reader(r#"
518    ///     <x:tag1 xmlns:x="www.xxxx" xmlns:y="www.yyyy" att1 = "test">
519    ///        <y:tag2><!--Test comment-->Test</y:tag2>
520    ///        <y:tag2>Test 2</y:tag2>
521    ///     </x:tag1>
522    /// "#.as_bytes());
523    /// reader.config_mut().trim_text(true);
524    ///
525    /// let mut count = 0;
526    /// let mut buf = Vec::new();
527    /// let mut txt = Vec::new();
528    /// loop {
529    ///     match reader.read_resolved_event_into_async(&mut buf).await.unwrap() {
530    ///         (Bound(Namespace("www.xxxx")), Event::Start(e)) => {
531    ///             count += 1;
532    ///             assert_eq!(e.local_name(), QName("tag1").into());
533    ///         }
534    ///         (Bound(Namespace("www.yyyy")), Event::Start(e)) => {
535    ///             count += 1;
536    ///             assert_eq!(e.local_name(), QName("tag2").into());
537    ///         }
538    ///         (_, Event::Start(_)) => unreachable!(),
539    ///
540    ///         (_, Event::Text(e)) => {
541    ///             txt.push(e.into_inner().into_owned())
542    ///         }
543    ///         (_, Event::Eof) => break,
544    ///         _ => (),
545    ///     }
546    ///     buf.clear();
547    /// }
548    /// assert_eq!(count, 3);
549    /// assert_eq!(txt, vec!["Test".to_string(), "Test 2".to_string()]);
550    /// # }) // tokio_test::block_on
551    /// ```
552    ///
553    /// [`read_resolved_event_into()`]: NsReader::read_resolved_event_into
554    /// [`Start`]: Event::Start
555    /// [`Empty`]: Event::Empty
556    /// [`End`]: Event::End
557    /// [`read_event_into_async()`]: Self::read_event_into_async
558    pub async fn read_resolved_event_into_async<'ns, 'b>(
559        // Name 'ns lifetime, because otherwise we get an error
560        // "implicit elided lifetime not allowed here" on ResolveResult
561        &'ns mut self,
562        buf: &'b mut Vec<u8>,
563    ) -> Result<(ResolveResult<'ns>, Event<'b>)> {
564        let event = self.read_event_into_async(buf).await?;
565        Ok(self.resolver().resolve_event(event))
566    }
567}
568
569#[cfg(test)]
570mod test {
571    use super::TokioAdapter;
572    use crate::reader::test::check;
573
574    check!(
575        #[tokio::test]
576        read_event_into_async,
577        TokioAdapter,
578        1,
579        &mut Vec::<u8>::new(),
580        async,
581        await
582    );
583
584    #[test]
585    fn test_future_is_send() {
586        // This test should just compile, no actual runtime checks are performed here.
587        use super::*;
588        use tokio::io::BufReader;
589        fn check_send<T: Send>(_: T) {}
590
591        let input = vec![];
592        let mut reading_buf = vec![];
593        let mut reader = Reader::from_reader(BufReader::new(input.as_slice()));
594
595        check_send(reader.read_event_into_async(&mut reading_buf));
596    }
597}