1 use std::io;
2 use std::io::prelude::*;
3 use std::fmt;
4 use std::result;
5 use std::borrow::Cow;
6 use std::error::Error;
7 
8 use common;
9 use name::{Name, OwnedName};
10 use attribute::Attribute;
11 use escape::{escape_str_attribute, escape_str_pcdata};
12 use common::XmlVersion;
13 use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX};
14 
15 use writer::config::EmitterConfig;
16 
17 /// An error which may be returned by `XmlWriter` when writing XML events.
18 #[derive(Debug)]
19 pub enum EmitterError {
20     /// An I/O error occured in the underlying `Write` instance.
21     Io(io::Error),
22 
23     /// Document declaration has already been written to the output stream.
24     DocumentStartAlreadyEmitted,
25 
26     /// The name of the last opening element is not available.
27     LastElementNameNotAvailable,
28 
29     /// The name of the last opening element is not equal to the name of the provided
30     /// closing element.
31     EndElementNameIsNotEqualToLastStartElementName,
32 
33     /// End element name is not specified when it is needed, for example, when automatic
34     /// closing is not enabled in configuration.
35     EndElementNameIsNotSpecified
36 }
37 
38 impl From<io::Error> for EmitterError {
from(err: io::Error) -> EmitterError39     fn from(err: io::Error) -> EmitterError {
40         EmitterError::Io(err)
41     }
42 }
43 
44 impl fmt::Display for EmitterError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result45     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46         use std::error::Error;
47 
48         write!(f, "emitter error: ")?;
49         match *self {
50             EmitterError::Io(ref e) =>
51                 write!(f, "I/O error: {}", e),
52             ref other =>
53                 write!(f, "{}", other.description()),
54         }
55     }
56 }
57 
58 impl Error for EmitterError {
description(&self) -> &str59     fn description(&self) -> &str {
60         match *self {
61             EmitterError::Io(_) =>
62                 "I/O error",
63             EmitterError::DocumentStartAlreadyEmitted =>
64                 "document start event has already been emitted",
65             EmitterError::LastElementNameNotAvailable =>
66                 "last element name is not available",
67             EmitterError::EndElementNameIsNotEqualToLastStartElementName =>
68                 "end element name is not equal to last start element name",
69             EmitterError::EndElementNameIsNotSpecified =>
70                 "end element name is not specified and can't be inferred",
71         }
72     }
73 }
74 
75 /// A result type yielded by `XmlWriter`.
76 pub type Result<T> = result::Result<T, EmitterError>;
77 
78 // TODO: split into a low-level fast writer without any checks and formatting logic and a
79 // high-level indenting validating writer
80 pub struct Emitter {
81     config: EmitterConfig,
82 
83     nst: NamespaceStack,
84 
85     indent_level: usize,
86     indent_stack: Vec<IndentFlags>,
87 
88     element_names: Vec<OwnedName>,
89 
90     start_document_emitted: bool,
91     just_wrote_start_element: bool
92 }
93 
94 impl Emitter {
new(config: EmitterConfig) -> Emitter95     pub fn new(config: EmitterConfig) -> Emitter {
96         Emitter {
97             config,
98 
99             nst: NamespaceStack::empty(),
100 
101             indent_level: 0,
102             indent_stack: vec![IndentFlags::WroteNothing],
103 
104             element_names: Vec::new(),
105 
106             start_document_emitted: false,
107             just_wrote_start_element: false
108         }
109     }
110 }
111 
112 #[derive(Copy, Clone, Eq, PartialEq, Debug)]
113 enum IndentFlags {
114     WroteNothing,
115     WroteMarkup,
116     WroteText,
117 }
118 
119 impl Emitter {
120     /// Returns the current state of namespaces.
121     #[inline]
namespace_stack_mut(&mut self) -> &mut NamespaceStack122     pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
123         &mut self.nst
124     }
125 
126     #[inline]
wrote_text(&self) -> bool127     fn wrote_text(&self) -> bool {
128         *self.indent_stack.last().unwrap() == IndentFlags::WroteText
129     }
130 
131     #[inline]
wrote_markup(&self) -> bool132     fn wrote_markup(&self) -> bool {
133         *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup
134     }
135 
136     #[inline]
set_wrote_text(&mut self)137     fn set_wrote_text(&mut self) {
138         *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText;
139     }
140 
141     #[inline]
set_wrote_markup(&mut self)142     fn set_wrote_markup(&mut self) {
143         *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup;
144     }
145 
146     #[inline]
reset_state(&mut self)147     fn reset_state(&mut self) {
148         *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing;
149     }
150 
write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()>151     fn write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()> {
152         target.write(self.config.line_separator.as_bytes())?;
153         for _ in 0..level {
154             target.write(self.config.indent_string.as_bytes())?;
155         }
156         Ok(())
157     }
158 
before_markup<W: Write>(&mut self, target: &mut W) -> Result<()>159     fn before_markup<W: Write>(&mut self, target: &mut W) -> Result<()> {
160         if self.config.perform_indent && !self.wrote_text() &&
161            (self.indent_level > 0 || self.wrote_markup()) {
162             let indent_level = self.indent_level;
163             self.write_newline(target, indent_level)?;
164             if self.indent_level > 0 && self.config.indent_string.len() > 0 {
165                 self.after_markup();
166             }
167         }
168         Ok(())
169     }
170 
after_markup(&mut self)171     fn after_markup(&mut self) {
172         self.set_wrote_markup();
173     }
174 
before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()>175     fn before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
176         self.before_markup(target)?;
177         self.indent_stack.push(IndentFlags::WroteNothing);
178         Ok(())
179     }
180 
after_start_element(&mut self)181     fn after_start_element(&mut self) {
182         self.after_markup();
183         self.indent_level += 1;
184     }
185 
before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()>186     fn before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
187         if self.config.perform_indent && self.indent_level > 0 && self.wrote_markup() &&
188            !self.wrote_text() {
189             let indent_level = self.indent_level;
190             self.write_newline(target, indent_level - 1)
191         } else {
192             Ok(())
193         }
194     }
195 
after_end_element(&mut self)196     fn after_end_element(&mut self) {
197         if self.indent_level > 0 {
198             self.indent_level -= 1;
199             self.indent_stack.pop();
200         }
201         self.set_wrote_markup();
202     }
203 
after_text(&mut self)204     fn after_text(&mut self) {
205         self.set_wrote_text();
206     }
207 
emit_start_document<W: Write>(&mut self, target: &mut W, version: XmlVersion, encoding: &str, standalone: Option<bool>) -> Result<()>208     pub fn emit_start_document<W: Write>(&mut self, target: &mut W,
209                                          version: XmlVersion,
210                                          encoding: &str,
211                                          standalone: Option<bool>) -> Result<()> {
212         if self.start_document_emitted {
213             return Err(EmitterError::DocumentStartAlreadyEmitted);
214         }
215         self.start_document_emitted = true;
216 
217         self.before_markup(target)?;
218         let result = {
219             let mut write = move || {
220                 write!(target, "<?xml version=\"{}\" encoding=\"{}\"", version, encoding)?;
221 
222                 if let Some(standalone) = standalone {
223                     write!(target, " standalone=\"{}\"", if standalone { "yes" } else { "no" })?;
224                 }
225 
226                 write!(target, "?>")?;
227 
228                 Ok(())
229             };
230             write()
231         };
232         self.after_markup();
233 
234         result
235     }
236 
check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()>237     fn check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()> {
238         if !self.start_document_emitted && self.config.write_document_declaration {
239             self.emit_start_document(target, common::XmlVersion::Version10, "utf-8", None)
240         } else {
241             Ok(())
242         }
243     }
244 
fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()>245     fn fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
246         if self.config.normalize_empty_elements && self.just_wrote_start_element {
247             self.just_wrote_start_element = false;
248             target.write(b">").map(|_| ()).map_err(From::from)
249         } else {
250             Ok(())
251         }
252     }
253 
emit_processing_instruction<W: Write>(&mut self, target: &mut W, name: &str, data: Option<&str>) -> Result<()>254     pub fn emit_processing_instruction<W: Write>(&mut self,
255                                                  target: &mut W,
256                                                  name: &str,
257                                                  data: Option<&str>) -> Result<()> {
258         self.check_document_started(target)?;
259         self.fix_non_empty_element(target)?;
260 
261         self.before_markup(target)?;
262 
263         let result = {
264             let mut write = || {
265                 write!(target, "<?{}", name)?;
266 
267                 if let Some(data) = data {
268                     write!(target, " {}", data)?;
269                 }
270 
271                 write!(target, "?>")?;
272 
273                 Ok(())
274             };
275             write()
276         };
277 
278         self.after_markup();
279 
280         result
281     }
282 
emit_start_element_initial<W>(&mut self, target: &mut W, name: Name, attributes: &[Attribute]) -> Result<()> where W: Write283     fn emit_start_element_initial<W>(&mut self, target: &mut W,
284                                      name: Name,
285                                      attributes: &[Attribute]) -> Result<()>
286         where W: Write
287     {
288         self.check_document_started(target)?;
289         self.fix_non_empty_element(target)?;
290         self.before_start_element(target)?;
291         write!(target, "<{}", name.repr_display())?;
292         self.emit_current_namespace_attributes(target)?;
293         self.emit_attributes(target, attributes)?;
294         self.after_start_element();
295         Ok(())
296     }
297 
emit_start_element<W>(&mut self, target: &mut W, name: Name, attributes: &[Attribute]) -> Result<()> where W: Write298     pub fn emit_start_element<W>(&mut self, target: &mut W,
299                                  name: Name,
300                                  attributes: &[Attribute]) -> Result<()>
301         where W: Write
302     {
303         if self.config.keep_element_names_stack {
304             self.element_names.push(name.to_owned());
305         }
306 
307         self.emit_start_element_initial(target, name, attributes)?;
308         self.just_wrote_start_element = true;
309 
310         if !self.config.normalize_empty_elements {
311             write!(target, ">")?;
312         }
313 
314         Ok(())
315     }
316 
emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()> where W: Write317     pub fn emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()>
318         where W: Write
319     {
320         for (prefix, uri) in self.nst.peek() {
321             match prefix {
322                 // internal namespaces are not emitted
323                 NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
324                 //// there is already a namespace binding with this prefix in scope
325                 //prefix if self.nst.get(prefix) == Some(uri) => Ok(()),
326                 // emit xmlns only if it is overridden
327                 NS_NO_PREFIX => if uri != NS_EMPTY_URI {
328                     write!(target, " xmlns=\"{}\"", uri)
329                 } else { Ok(()) },
330                 // everything else
331                 prefix => write!(target, " xmlns:{}=\"{}\"", prefix, uri)
332             }?;
333         }
334         Ok(())
335     }
336 
emit_attributes<W: Write>(&mut self, target: &mut W, attributes: &[Attribute]) -> Result<()>337     pub fn emit_attributes<W: Write>(&mut self, target: &mut W,
338                                       attributes: &[Attribute]) -> Result<()> {
339         for attr in attributes.iter() {
340             write!(
341                 target, " {}=\"{}\"",
342                 attr.name.repr_display(),
343                 if self.config.perform_escaping { escape_str_attribute(attr.value) } else { Cow::Borrowed(attr.value) }
344             )?
345         }
346         Ok(())
347     }
348 
emit_end_element<W: Write>(&mut self, target: &mut W, name: Option<Name>) -> Result<()>349     pub fn emit_end_element<W: Write>(&mut self, target: &mut W,
350                                       name: Option<Name>) -> Result<()> {
351         let owned_name = if self.config.keep_element_names_stack {
352             Some(self.element_names.pop().ok_or(EmitterError::LastElementNameNotAvailable)?)
353         } else {
354             None
355         };
356 
357         // Check that last started element name equals to the provided name, if there are both
358         if let Some(ref last_name) = owned_name {
359             if let Some(ref name) = name {
360                 if last_name.borrow() != *name {
361                     return Err(EmitterError::EndElementNameIsNotEqualToLastStartElementName);
362                 }
363             }
364         }
365 
366         if let Some(name) = owned_name.as_ref().map(|n| n.borrow()).or(name) {
367             if self.config.normalize_empty_elements && self.just_wrote_start_element {
368                 self.just_wrote_start_element = false;
369                 // TODO: make this space configurable
370                 let result = target.write(b" />").map_err(From::from);
371                 self.after_end_element();
372                 result.map(|_| ())
373             } else {
374                 self.just_wrote_start_element = false;
375 
376                 self.before_end_element(target)?;
377                 let result = write!(target, "</{}>", name.repr_display()).map_err(From::from);
378                 self.after_end_element();
379 
380                 result
381             }
382         } else {
383             Err(EmitterError::EndElementNameIsNotSpecified)
384         }
385     }
386 
emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>387     pub fn emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
388         self.fix_non_empty_element(target)?;
389         if self.config.cdata_to_characters {
390             self.emit_characters(target, content)
391         } else {
392             // TODO: escape ']]>' characters in CDATA as two adjacent CDATA blocks
393             target.write(b"<![CDATA[")?;
394             target.write(content.as_bytes())?;
395             target.write(b"]]>")?;
396 
397             self.after_text();
398 
399             Ok(())
400         }
401     }
402 
emit_characters<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>403     pub fn emit_characters<W: Write>(&mut self, target: &mut W,
404                                       content: &str) -> Result<()> {
405         self.fix_non_empty_element(target)?;
406         target.write(
407             (if self.config.perform_escaping {
408                 escape_str_pcdata(content)
409             } else {
410                 Cow::Borrowed(content)
411             }).as_bytes()
412         )?;
413         self.after_text();
414         Ok(())
415     }
416 
emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()>417     pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
418         self.fix_non_empty_element(target)?;
419 
420         // TODO: add escaping dashes at the end of the comment
421 
422         let autopad_comments = self.config.autopad_comments;
423         let write = |target: &mut W| -> Result<()> {
424             target.write(b"<!--")?;
425 
426             if autopad_comments && !content.starts_with(char::is_whitespace) {
427                 target.write(b" ")?;
428             }
429 
430             target.write(content.as_bytes())?;
431 
432             if autopad_comments && !content.ends_with(char::is_whitespace) {
433                 target.write(b" ")?;
434             }
435 
436             target.write(b"-->")?;
437 
438             Ok(())
439         };
440 
441         self.before_markup(target)?;
442         let result = write(target);
443         self.after_markup();
444 
445         result
446     }
447 }
448