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