1use std::io::Write;
4
5use crate::encoding::UTF8_BOM;
6use crate::errors::Result;
7use crate::events::{attributes::Attribute, BytesCData, BytesStart, BytesText, Event};
8
9#[cfg(feature = "async-tokio")]
10mod async_tokio;
11
12#[cfg(feature = "serialize")]
14use {crate::de::DeError, serde::Serialize};
15
16#[derive(Clone)]
63pub struct Writer<W> {
64 writer: W,
66 indent: Option<Indentation>,
67}
68
69impl<W> Writer<W> {
70 pub fn new(inner: W) -> Writer<W> {
72 Writer {
73 writer: inner,
74 indent: None,
75 }
76 }
77
78 pub fn new_with_indent(inner: W, indent_char: u8, indent_size: usize) -> Writer<W> {
80 Writer {
81 writer: inner,
82 indent: Some(Indentation::new(indent_char, indent_size)),
83 }
84 }
85
86 pub fn into_inner(self) -> W {
88 self.writer
89 }
90
91 pub fn get_mut(&mut self) -> &mut W {
93 &mut self.writer
94 }
95
96 pub fn get_ref(&self) -> &W {
98 &self.writer
99 }
100}
101
102impl<W: Write> Writer<W> {
103 pub fn write_bom(&mut self) -> Result<()> {
134 self.write(UTF8_BOM)
135 }
136
137 pub fn write_event<'a, E: AsRef<Event<'a>>>(&mut self, event: E) -> Result<()> {
139 let mut next_should_line_break = true;
140 let result = match *event.as_ref() {
141 Event::Start(ref e) => {
142 let result = self.write_wrapped(b"<", e, b">");
143 if let Some(i) = self.indent.as_mut() {
144 i.grow();
145 }
146 result
147 }
148 Event::End(ref e) => {
149 if let Some(i) = self.indent.as_mut() {
150 i.shrink();
151 }
152 self.write_wrapped(b"</", e, b">")
153 }
154 Event::Empty(ref e) => self.write_wrapped(b"<", e, b"/>"),
155 Event::Text(ref e) => {
156 next_should_line_break = false;
157 self.write(e)
158 }
159 Event::Comment(ref e) => self.write_wrapped(b"<!--", e, b"-->"),
160 Event::CData(ref e) => {
161 next_should_line_break = false;
162 self.write(b"<![CDATA[")?;
163 self.write(e)?;
164 self.write(b"]]>")
165 }
166 Event::Decl(ref e) => self.write_wrapped(b"<?", e, b"?>"),
167 Event::PI(ref e) => self.write_wrapped(b"<?", e, b"?>"),
168 Event::DocType(ref e) => self.write_wrapped(b"<!DOCTYPE ", e, b">"),
169 Event::Eof => Ok(()),
170 };
171 if let Some(i) = self.indent.as_mut() {
172 i.should_line_break = next_should_line_break;
173 }
174 result
175 }
176
177 #[inline]
179 pub(crate) fn write(&mut self, value: &[u8]) -> Result<()> {
180 self.writer.write_all(value).map_err(Into::into)
181 }
182
183 #[inline]
184 fn write_wrapped(&mut self, before: &[u8], value: &[u8], after: &[u8]) -> Result<()> {
185 if let Some(ref i) = self.indent {
186 if i.should_line_break {
187 self.writer.write_all(b"\n")?;
188 self.writer.write_all(i.current())?;
189 }
190 }
191 self.write(before)?;
192 self.write(value)?;
193 self.write(after)?;
194 Ok(())
195 }
196
197 pub fn write_indent(&mut self) -> Result<()> {
209 if let Some(ref i) = self.indent {
210 self.writer.write_all(b"\n")?;
211 self.writer.write_all(i.current())?;
212 }
213 Ok(())
214 }
215
216 #[must_use]
259 pub fn create_element<'a, N>(&'a mut self, name: &'a N) -> ElementWriter<W>
260 where
261 N: 'a + AsRef<str> + ?Sized,
262 {
263 ElementWriter {
264 writer: self,
265 start_tag: BytesStart::new(name.as_ref()),
266 }
267 }
268
269 #[cfg(feature = "serialize")]
315 pub fn write_serializable<T: Serialize>(
316 &mut self,
317 tag_name: &str,
318 content: &T,
319 ) -> std::result::Result<(), DeError> {
320 use crate::se::{Indent, Serializer};
321
322 self.write_indent()?;
323 let mut fmt = ToFmtWrite(&mut self.writer);
324 let mut serializer = Serializer::with_root(&mut fmt, Some(tag_name))?;
325
326 if let Some(indent) = &mut self.indent {
327 serializer.set_indent(Indent::Borrow(indent));
328 }
329
330 content.serialize(serializer)?;
331
332 Ok(())
333 }
334}
335
336pub struct ElementWriter<'a, W: Write> {
339 writer: &'a mut Writer<W>,
340 start_tag: BytesStart<'a>,
341}
342
343impl<'a, W: Write> ElementWriter<'a, W> {
344 pub fn with_attribute<'b, I>(mut self, attr: I) -> Self
346 where
347 I: Into<Attribute<'b>>,
348 {
349 self.start_tag.push_attribute(attr);
350 self
351 }
352
353 pub fn with_attributes<'b, I>(mut self, attributes: I) -> Self
357 where
358 I: IntoIterator,
359 I::Item: Into<Attribute<'b>>,
360 {
361 self.start_tag.extend_attributes(attributes);
362 self
363 }
364
365 pub fn write_text_content(self, text: BytesText) -> Result<&'a mut Writer<W>> {
367 self.writer
368 .write_event(Event::Start(self.start_tag.borrow()))?;
369 self.writer.write_event(Event::Text(text))?;
370 self.writer
371 .write_event(Event::End(self.start_tag.to_end()))?;
372 Ok(self.writer)
373 }
374
375 pub fn write_cdata_content(self, text: BytesCData) -> Result<&'a mut Writer<W>> {
377 self.writer
378 .write_event(Event::Start(self.start_tag.borrow()))?;
379 self.writer.write_event(Event::CData(text))?;
380 self.writer
381 .write_event(Event::End(self.start_tag.to_end()))?;
382 Ok(self.writer)
383 }
384
385 pub fn write_pi_content(self, text: BytesText) -> Result<&'a mut Writer<W>> {
387 self.writer
388 .write_event(Event::Start(self.start_tag.borrow()))?;
389 self.writer.write_event(Event::PI(text))?;
390 self.writer
391 .write_event(Event::End(self.start_tag.to_end()))?;
392 Ok(self.writer)
393 }
394
395 pub fn write_empty(self) -> Result<&'a mut Writer<W>> {
397 self.writer.write_event(Event::Empty(self.start_tag))?;
398 Ok(self.writer)
399 }
400
401 pub fn write_inner_content<F>(self, closure: F) -> Result<&'a mut Writer<W>>
403 where
404 F: FnOnce(&mut Writer<W>) -> Result<()>,
405 {
406 self.writer
407 .write_event(Event::Start(self.start_tag.borrow()))?;
408 closure(self.writer)?;
409 self.writer
410 .write_event(Event::End(self.start_tag.to_end()))?;
411 Ok(self.writer)
412 }
413}
414#[cfg(feature = "serialize")]
415struct ToFmtWrite<T>(pub T);
416
417#[cfg(feature = "serialize")]
418impl<T> std::fmt::Write for ToFmtWrite<T>
419where
420 T: std::io::Write,
421{
422 fn write_str(&mut self, s: &str) -> std::fmt::Result {
423 self.0.write_all(s.as_bytes()).map_err(|_| std::fmt::Error)
424 }
425}
426
427#[derive(Clone)]
428pub(crate) struct Indentation {
429 should_line_break: bool,
432 indent_char: u8,
434 indent_size: usize,
436 indents: Vec<u8>,
438 current_indent_len: usize,
440}
441
442impl Indentation {
443 pub fn new(indent_char: u8, indent_size: usize) -> Self {
444 Self {
445 should_line_break: false,
446 indent_char,
447 indent_size,
448 indents: vec![indent_char; 128],
449 current_indent_len: 0, }
451 }
452
453 pub fn grow(&mut self) {
455 self.current_indent_len += self.indent_size;
456 if self.current_indent_len > self.indents.len() {
457 self.indents
458 .resize(self.current_indent_len, self.indent_char);
459 }
460 }
461
462 pub fn shrink(&mut self) {
464 self.current_indent_len = self.current_indent_len.saturating_sub(self.indent_size);
465 }
466
467 pub fn current(&self) -> &[u8] {
469 &self.indents[..self.current_indent_len]
470 }
471}
472
473#[cfg(test)]
474mod indentation {
475 use super::*;
476 use crate::events::*;
477 use pretty_assertions::assert_eq;
478
479 #[test]
480 fn self_closed() {
481 let mut buffer = Vec::new();
482 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
483
484 let tag = BytesStart::new("self-closed")
485 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
486 writer
487 .write_event(Event::Empty(tag))
488 .expect("write tag failed");
489
490 assert_eq!(
491 std::str::from_utf8(&buffer).unwrap(),
492 r#"<self-closed attr1="value1" attr2="value2"/>"#
493 );
494 }
495
496 #[test]
497 fn empty_paired() {
498 let mut buffer = Vec::new();
499 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
500
501 let start = BytesStart::new("paired")
502 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
503 let end = start.to_end();
504 writer
505 .write_event(Event::Start(start.clone()))
506 .expect("write start tag failed");
507 writer
508 .write_event(Event::End(end))
509 .expect("write end tag failed");
510
511 assert_eq!(
512 std::str::from_utf8(&buffer).unwrap(),
513 r#"<paired attr1="value1" attr2="value2">
514</paired>"#
515 );
516 }
517
518 #[test]
519 fn paired_with_inner() {
520 let mut buffer = Vec::new();
521 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
522
523 let start = BytesStart::new("paired")
524 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
525 let end = start.to_end();
526 let inner = BytesStart::new("inner");
527
528 writer
529 .write_event(Event::Start(start.clone()))
530 .expect("write start tag failed");
531 writer
532 .write_event(Event::Empty(inner))
533 .expect("write inner tag failed");
534 writer
535 .write_event(Event::End(end))
536 .expect("write end tag failed");
537
538 assert_eq!(
539 std::str::from_utf8(&buffer).unwrap(),
540 r#"<paired attr1="value1" attr2="value2">
541 <inner/>
542</paired>"#
543 );
544 }
545
546 #[test]
547 fn paired_with_text() {
548 let mut buffer = Vec::new();
549 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
550
551 let start = BytesStart::new("paired")
552 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
553 let end = start.to_end();
554 let text = BytesText::new("text");
555
556 writer
557 .write_event(Event::Start(start.clone()))
558 .expect("write start tag failed");
559 writer
560 .write_event(Event::Text(text))
561 .expect("write text failed");
562 writer
563 .write_event(Event::End(end))
564 .expect("write end tag failed");
565
566 assert_eq!(
567 std::str::from_utf8(&buffer).unwrap(),
568 r#"<paired attr1="value1" attr2="value2">text</paired>"#
569 );
570 }
571
572 #[test]
573 fn mixed_content() {
574 let mut buffer = Vec::new();
575 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
576
577 let start = BytesStart::new("paired")
578 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
579 let end = start.to_end();
580 let text = BytesText::new("text");
581 let inner = BytesStart::new("inner");
582
583 writer
584 .write_event(Event::Start(start.clone()))
585 .expect("write start tag failed");
586 writer
587 .write_event(Event::Text(text))
588 .expect("write text failed");
589 writer
590 .write_event(Event::Empty(inner))
591 .expect("write inner tag failed");
592 writer
593 .write_event(Event::End(end))
594 .expect("write end tag failed");
595
596 assert_eq!(
597 std::str::from_utf8(&buffer).unwrap(),
598 r#"<paired attr1="value1" attr2="value2">text<inner/>
599</paired>"#
600 );
601 }
602
603 #[test]
604 fn nested() {
605 let mut buffer = Vec::new();
606 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
607
608 let start = BytesStart::new("paired")
609 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
610 let end = start.to_end();
611 let inner = BytesStart::new("inner");
612
613 writer
614 .write_event(Event::Start(start.clone()))
615 .expect("write start 1 tag failed");
616 writer
617 .write_event(Event::Start(start.clone()))
618 .expect("write start 2 tag failed");
619 writer
620 .write_event(Event::Empty(inner))
621 .expect("write inner tag failed");
622 writer
623 .write_event(Event::End(end.clone()))
624 .expect("write end tag 2 failed");
625 writer
626 .write_event(Event::End(end))
627 .expect("write end tag 1 failed");
628
629 assert_eq!(
630 std::str::from_utf8(&buffer).unwrap(),
631 r#"<paired attr1="value1" attr2="value2">
632 <paired attr1="value1" attr2="value2">
633 <inner/>
634 </paired>
635</paired>"#
636 );
637 }
638
639 #[cfg(feature = "serialize")]
640 #[test]
641 fn serializable() {
642 #[derive(Serialize)]
643 struct Foo {
644 #[serde(rename = "@attribute")]
645 attribute: &'static str,
646
647 element: Bar,
648 list: Vec<&'static str>,
649
650 #[serde(rename = "$text")]
651 text: &'static str,
652
653 val: String,
654 }
655
656 #[derive(Serialize)]
657 struct Bar {
658 baz: usize,
659 bat: usize,
660 }
661
662 let mut buffer = Vec::new();
663 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
664
665 let content = Foo {
666 attribute: "attribute",
667 element: Bar { baz: 42, bat: 43 },
668 list: vec!["first element", "second element"],
669 text: "text",
670 val: "foo".to_owned(),
671 };
672
673 let start = BytesStart::new("paired")
674 .with_attributes(vec![("attr1", "value1"), ("attr2", "value2")].into_iter());
675 let end = start.to_end();
676
677 writer
678 .write_event(Event::Start(start.clone()))
679 .expect("write start tag failed");
680 writer
681 .write_serializable("foo_element", &content)
682 .expect("write serializable inner contents failed");
683 writer
684 .write_event(Event::End(end))
685 .expect("write end tag failed");
686
687 assert_eq!(
688 std::str::from_utf8(&buffer).unwrap(),
689 r#"<paired attr1="value1" attr2="value2">
690 <foo_element attribute="attribute">
691 <element>
692 <baz>42</baz>
693 <bat>43</bat>
694 </element>
695 <list>first element</list>
696 <list>second element</list>
697 text
698 <val>foo</val>
699 </foo_element>
700</paired>"#
701 );
702 }
703
704 #[test]
705 fn element_writer_empty() {
706 let mut buffer = Vec::new();
707 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
708
709 writer
710 .create_element("empty")
711 .with_attribute(("attr1", "value1"))
712 .with_attribute(("attr2", "value2"))
713 .write_empty()
714 .expect("failure");
715
716 assert_eq!(
717 std::str::from_utf8(&buffer).unwrap(),
718 r#"<empty attr1="value1" attr2="value2"/>"#
719 );
720 }
721
722 #[test]
723 fn element_writer_text() {
724 let mut buffer = Vec::new();
725 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
726
727 writer
728 .create_element("paired")
729 .with_attribute(("attr1", "value1"))
730 .with_attribute(("attr2", "value2"))
731 .write_text_content(BytesText::new("text"))
732 .expect("failure");
733
734 assert_eq!(
735 std::str::from_utf8(&buffer).unwrap(),
736 r#"<paired attr1="value1" attr2="value2">text</paired>"#
737 );
738 }
739
740 #[test]
741 fn element_writer_nested() {
742 let mut buffer = Vec::new();
743 let mut writer = Writer::new_with_indent(&mut buffer, b' ', 4);
744
745 writer
746 .create_element("outer")
747 .with_attribute(("attr1", "value1"))
748 .with_attribute(("attr2", "value2"))
749 .write_inner_content(|writer| {
750 let fruits = ["apple", "orange", "banana"];
751 for (quant, item) in fruits.iter().enumerate() {
752 writer
753 .create_element("fruit")
754 .with_attribute(("quantity", quant.to_string().as_str()))
755 .write_text_content(BytesText::new(item))?;
756 }
757 writer
758 .create_element("inner")
759 .write_inner_content(|writer| {
760 writer.create_element("empty").write_empty()?;
761 Ok(())
762 })?;
763
764 Ok(())
765 })
766 .expect("failure");
767
768 assert_eq!(
769 std::str::from_utf8(&buffer).unwrap(),
770 r#"<outer attr1="value1" attr2="value2">
771 <fruit quantity="0">apple</fruit>
772 <fruit quantity="1">orange</fruit>
773 <fruit quantity="2">banana</fruit>
774 <inner>
775 <empty/>
776 </inner>
777</outer>"#
778 );
779 }
780}