xml_no_std/
writer.rs

1//! Contains high-level interface for an events-based XML emitter.
2//!
3//! The most important type in this module is `EventWriter` which allows writing an XML document
4//! to some output stream.
5extern crate alloc;
6
7pub use self::config::EmitterConfig;
8pub use self::emitter::EmitterError as Error;
9pub use self::emitter::Result;
10pub use self::events::XmlEvent;
11
12use self::emitter::Emitter;
13
14mod config;
15mod emitter;
16pub mod events;
17
18/// A wrapper around a String which emits XML document according to provided
19/// events.
20pub struct EventWriter {
21    sink: alloc::string::String,
22    emitter: Emitter,
23}
24
25impl EventWriter {
26    /// Creates a new `EventWriter` using the default
27    /// configuration.
28    #[inline]
29    pub fn new() -> EventWriter {
30        EventWriter::new_with_config(EmitterConfig::new())
31    }
32
33    /// Creates a new `EventWriter` using the provided
34    /// configuration.
35    #[inline]
36    pub fn new_with_config(config: EmitterConfig) -> EventWriter {
37        EventWriter {
38            sink: alloc::string::String::new(),
39            emitter: Emitter::new(config),
40        }
41    }
42
43    /// Writes the next piece of XML document according to the provided event.
44    ///
45    /// Note that output data may not exactly correspond to the written event because
46    /// of various configuration options. For example, `XmlEvent::EndElement` may
47    /// correspond to a separate closing element or it may cause writing an empty element.
48    /// Another example is that `XmlEvent::CData` may be represented as characters in
49    /// the output stream.
50    pub fn write<'a, E>(&mut self, event: E) -> Result<()> where E: Into<XmlEvent<'a>> {
51        match event.into() {
52            XmlEvent::StartDocument { version, encoding, standalone } =>
53                self.emitter.emit_start_document(&mut self.sink, version, encoding.unwrap_or("UTF-8"), standalone),
54            XmlEvent::ProcessingInstruction { name, data } =>
55                self.emitter.emit_processing_instruction(&mut self.sink, name, data),
56            XmlEvent::StartElement { name, attributes, namespace } => {
57                self.emitter.namespace_stack_mut().push_empty().checked_target().extend(namespace.as_ref());
58                self.emitter.emit_start_element(&mut self.sink, name, &attributes)
59            }
60            XmlEvent::EndElement { name } => {
61                let r = self.emitter.emit_end_element(&mut self.sink, name);
62                self.emitter.namespace_stack_mut().try_pop();
63                r
64            }
65            XmlEvent::Comment(content) => self.emitter.emit_comment(&mut self.sink, content),
66            XmlEvent::CData(content) => Ok(self.emitter.emit_cdata(&mut self.sink, content)),
67            XmlEvent::Characters(content) => Ok(self.emitter.emit_characters(&mut self.sink, content)),
68        }
69    }
70
71    /// Returns a mutable reference to the underlying String.
72    pub fn inner_mut(&mut self) -> &mut alloc::string::String {
73        &mut self.sink
74    }
75
76    /// Unwraps this `EventWriter`, returning the String the writer has written to.
77    /// This is the primary method for retrieving the output of the `no-std` writer.
78    pub fn into_inner(self) -> alloc::string::String {
79        self.sink
80    }
81}