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 "closed"
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 "closed"
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 "closed"
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 "closed"
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}