1use std::future::Future;
2use std::result::Result as StdResult;
3
4use tokio::io::{AsyncWrite, AsyncWriteExt};
5
6use crate::errors::{Error, Result};
7use crate::events::{BytesCData, BytesPI, BytesText, Event};
8use crate::{ElementWriter, Writer};
9
10impl<W: AsyncWrite + Unpin> Writer<W> {
11 pub async fn write_event_async<'a, E: Into<Event<'a>>>(&mut self, event: E) -> Result<()> {
13 let mut next_should_line_break = true;
14 let result = match event.into() {
15 Event::Start(e) => {
16 let result = self.write_wrapped_async("<", &e, ">").await;
17 if let Some(i) = self.indent.as_mut() {
18 i.grow();
19 }
20 result
21 }
22 Event::End(e) => {
23 if let Some(i) = self.indent.as_mut() {
24 i.shrink();
25 }
26 self.write_wrapped_async("</", &e, ">").await
27 }
28 Event::Empty(e) => self.write_wrapped_async("<", &e, "/>").await,
29 Event::Text(e) => {
30 next_should_line_break = false;
31 self.write_async(e.as_bytes()).await
32 }
33 Event::Comment(e) => self.write_wrapped_async("<!--", &e, "-->").await,
34 Event::CData(e) => {
35 next_should_line_break = false;
36 self.write_async(b"<![CDATA[").await?;
37 self.write_async(e.as_bytes()).await?;
38 self.write_async(b"]]>").await
39 }
40 Event::Decl(e) => self.write_wrapped_async("<?", &e, "?>").await,
41 Event::PI(e) => self.write_wrapped_async("<?", &e, "?>").await,
42 Event::DocType(e) => self.write_wrapped_async("<!DOCTYPE ", &e, ">").await,
43 Event::GeneralRef(e) => self.write_wrapped_async("&", &e, ";").await,
44 Event::Eof => Ok(()),
45 };
46 if let Some(i) = self.indent.as_mut() {
47 i.should_line_break = next_should_line_break;
48 }
49 result
50 }
51
52 pub async fn write_indent_async(&mut self) -> Result<()> {
57 if let Some(ref i) = self.indent {
58 self.writer.write_all(b"\n").await?;
59 self.writer.write_all(i.current().as_bytes()).await?;
60 }
61 Ok(())
62 }
63
64 #[inline]
65 async fn write_async(&mut self, value: &[u8]) -> Result<()> {
66 self.writer.write_all(value).await.map_err(Into::into)
67 }
68
69 #[inline]
70 async fn write_wrapped_async(&mut self, before: &str, value: &str, after: &str) -> Result<()> {
71 if let Some(ref i) = self.indent {
72 if i.should_line_break {
73 self.writer.write_all(b"\n").await?;
74 self.writer.write_all(i.current().as_bytes()).await?;
75 }
76 }
77 self.write_async(before.as_bytes()).await?;
78 self.write_async(value.as_bytes()).await?;
79 self.write_async(after.as_bytes()).await?;
80 Ok(())
81 }
82}
83
84impl<'a, W: AsyncWrite + Unpin> ElementWriter<'a, W> {
85 pub async fn write_text_content_async(self, text: BytesText<'_>) -> Result<&'a mut Writer<W>> {
114 self.writer
115 .write_event_async(Event::Start(self.start_tag.borrow()))
116 .await?;
117 self.writer.write_event_async(Event::Text(text)).await?;
118 self.writer
119 .write_event_async(Event::End(self.start_tag.to_end()))
120 .await?;
121 Ok(self.writer)
122 }
123
124 pub async fn write_cdata_content_async(
153 self,
154 text: BytesCData<'_>,
155 ) -> Result<&'a mut Writer<W>> {
156 self.writer
157 .write_event_async(Event::Start(self.start_tag.borrow()))
158 .await?;
159 self.writer.write_event_async(Event::CData(text)).await?;
160 self.writer
161 .write_event_async(Event::End(self.start_tag.to_end()))
162 .await?;
163 Ok(self.writer)
164 }
165
166 pub async fn write_pi_content_async(self, text: BytesPI<'_>) -> Result<&'a mut Writer<W>> {
197 self.writer
198 .write_event_async(Event::Start(self.start_tag.borrow()))
199 .await?;
200 self.writer.write_event_async(Event::PI(text)).await?;
201 self.writer
202 .write_event_async(Event::End(self.start_tag.to_end()))
203 .await?;
204 Ok(self.writer)
205 }
206
207 pub async fn write_empty_async(self) -> Result<&'a mut Writer<W>> {
236 self.writer
237 .write_event_async(Event::Empty(self.start_tag))
238 .await?;
239 Ok(self.writer)
240 }
241
242 pub async fn write_inner_content_async<F, Fut, E>(
296 mut self,
297 closure: F,
298 ) -> StdResult<&'a mut Writer<W>, E>
299 where
300 F: FnOnce(&'a mut Writer<W>) -> Fut,
301 Fut: Future<Output = StdResult<&'a mut Writer<W>, E>>,
302 E: From<Error>,
303 {
304 self.writer
305 .write_event_async(Event::Start(self.start_tag.borrow()))
306 .await?;
307 self.writer = closure(self.writer).await?;
308 self.writer
309 .write_event_async(Event::End(self.start_tag.to_end()))
310 .await?;
311 Ok(self.writer)
312 }
313}
314
315#[cfg(test)]
316mod tests {
317 use super::*;
318 use crate::events::*;
319 use pretty_assertions::assert_eq;
320
321 macro_rules! test {
322 ($name: ident, $event: expr, $expected: expr) => {
323 #[tokio::test]
324 async fn $name() {
325 let mut buffer = Vec::new();
326 let mut writer = Writer::new(&mut buffer);
327
328 writer
329 .write_event_async($event)
330 .await
331 .expect("write event failed");
332
333 assert_eq!(std::str::from_utf8(&buffer).unwrap(), $expected,);
334 }
335 };
336 }
337
338 test!(
339 xml_header,
340 Event::Decl(BytesDecl::new("1.0", Some("UTF-8"), Some("no"))),
341 r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>"#
342 );
343
344 test!(empty_tag, Event::Empty(BytesStart::new("tag")), r#"<tag/>"#);
345
346 test!(
347 comment,
348 Event::Comment(BytesText::new("this is a comment")),
349 r#"<!--this is a comment-->"#
350 );
351
352 test!(
353 cdata,
354 Event::CData(BytesCData::new("this is a cdata")),
355 r#"<![CDATA[this is a cdata]]>"#
356 );
357
358 test!(
359 pi,
360 Event::PI(BytesPI::new("this is a processing instruction")),
361 r#"<?this is a processing instruction?>"#
362 );
363
364 test!(
365 doctype,
366 Event::DocType(BytesText::new("this is a doctype")),
367 r#"<!DOCTYPE this is a doctype>"#
368 );
369
370 #[tokio::test]
371 async fn full_tag() {
372 let mut buffer = Vec::new();
373 let mut writer = Writer::new(&mut buffer);
374
375 let start = Event::Start(BytesStart::new("tag"));
376 let text = Event::Text(BytesText::new("inner text"));
377 let end = Event::End(BytesEnd::new("tag"));
378 for i in [start, text, end] {
379 writer.write_event_async(i).await.expect("write tag failed");
380 }
381
382 assert_eq!(
383 std::str::from_utf8(&buffer).unwrap(),
384 r#"<tag>inner text</tag>"#
385 );
386 }
387}
388
389#[cfg(test)]
390mod indentation_async {
391 use super::*;
392 use crate::events::*;
393 use pretty_assertions::assert_eq;
394
395 #[tokio::test]
396 async fn self_closed() {
397 let mut buffer = Vec::new();
398 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
399
400 let tag = BytesStart::new("self-closed")
401 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
402 writer
403 .write_event_async(Event::Empty(tag))
404 .await
405 .expect("write tag failed");
406
407 assert_eq!(
408 std::str::from_utf8(&buffer).unwrap(),
409 r#"<self-closed attr1="value1" attr2="value2"/>"#
410 );
411 }
412
413 #[tokio::test]
414 async fn empty_paired() {
415 let mut buffer = Vec::new();
416 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
417
418 let start = BytesStart::new("paired")
419 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
420 let end = start.to_end();
421 writer
422 .write_event_async(Event::Start(start.clone()))
423 .await
424 .expect("write start tag failed");
425 writer
426 .write_event_async(Event::End(end))
427 .await
428 .expect("write end tag failed");
429
430 assert_eq!(
431 std::str::from_utf8(&buffer).unwrap(),
432 r#"<paired attr1="value1" attr2="value2">
433</paired>"#
434 );
435 }
436
437 #[tokio::test]
438 async fn paired_with_inner() {
439 let mut buffer = Vec::new();
440 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
441
442 let start = BytesStart::new("paired")
443 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
444 let end = start.to_end();
445 let inner = BytesStart::new("inner");
446
447 writer
448 .write_event_async(Event::Start(start.clone()))
449 .await
450 .expect("write start tag failed");
451 writer
452 .write_event_async(Event::Empty(inner))
453 .await
454 .expect("write inner tag failed");
455 writer
456 .write_event_async(Event::End(end))
457 .await
458 .expect("write end tag failed");
459
460 assert_eq!(
461 std::str::from_utf8(&buffer).unwrap(),
462 r#"<paired attr1="value1" attr2="value2">
463 <inner/>
464</paired>"#
465 );
466 }
467
468 #[tokio::test]
469 async fn paired_with_text() {
470 let mut buffer = Vec::new();
471 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
472
473 let start = BytesStart::new("paired")
474 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
475 let end = start.to_end();
476 let text = BytesText::new("text");
477
478 writer
479 .write_event_async(Event::Start(start.clone()))
480 .await
481 .expect("write start tag failed");
482 writer
483 .write_event_async(Event::Text(text))
484 .await
485 .expect("write text failed");
486 writer
487 .write_event_async(Event::End(end))
488 .await
489 .expect("write end tag failed");
490
491 assert_eq!(
492 std::str::from_utf8(&buffer).unwrap(),
493 r#"<paired attr1="value1" attr2="value2">text</paired>"#
494 );
495 }
496
497 #[tokio::test]
498 async fn mixed_content() {
499 let mut buffer = Vec::new();
500 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
501
502 let start = BytesStart::new("paired")
503 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
504 let end = start.to_end();
505 let text = BytesText::new("text");
506 let inner = BytesStart::new("inner");
507
508 writer
509 .write_event_async(Event::Start(start.clone()))
510 .await
511 .expect("write start tag failed");
512 writer
513 .write_event_async(Event::Text(text))
514 .await
515 .expect("write text failed");
516 writer
517 .write_event_async(Event::Empty(inner))
518 .await
519 .expect("write inner tag failed");
520 writer
521 .write_event_async(Event::End(end))
522 .await
523 .expect("write end tag failed");
524
525 assert_eq!(
526 std::str::from_utf8(&buffer).unwrap(),
527 r#"<paired attr1="value1" attr2="value2">text<inner/>
528</paired>"#
529 );
530 }
531
532 #[tokio::test]
533 async fn nested() {
534 let mut buffer = Vec::new();
535 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
536
537 let start = BytesStart::new("paired")
538 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
539 let end = start.to_end();
540 let inner = BytesStart::new("inner");
541
542 writer
543 .write_event_async(Event::Start(start.clone()))
544 .await
545 .expect("write start 1 tag failed");
546 writer
547 .write_event_async(Event::Start(start.clone()))
548 .await
549 .expect("write start 2 tag failed");
550 writer
551 .write_event_async(Event::Empty(inner))
552 .await
553 .expect("write inner tag failed");
554 writer
555 .write_event_async(Event::End(end.clone()))
556 .await
557 .expect("write end tag 2 failed");
558 writer
559 .write_event_async(Event::End(end))
560 .await
561 .expect("write end tag 1 failed");
562
563 assert_eq!(
564 std::str::from_utf8(&buffer).unwrap(),
565 r#"<paired attr1="value1" attr2="value2">
566 <paired attr1="value1" attr2="value2">
567 <inner/>
568 </paired>
569</paired>"#
570 );
571 }
572}