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