1use std::io;
2use std::io::prelude::*;
3use std::fmt;
4use std::result;
5use std::borrow::Cow;
6use std::error::Error;
7
8use common;
9use name::{Name, OwnedName};
10use attribute::Attribute;
11use escape::{escape_str_attribute, escape_str_pcdata};
12use common::XmlVersion;
13use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX};
14
15use writer::config::EmitterConfig;
16
17#[derive(Debug)]
19pub enum EmitterError {
20 Io(io::Error),
22
23 DocumentStartAlreadyEmitted,
25
26 LastElementNameNotAvailable,
28
29 EndElementNameIsNotEqualToLastStartElementName,
32
33 EndElementNameIsNotSpecified
36}
37
38impl From<io::Error> for EmitterError {
39 fn from(err: io::Error) -> EmitterError {
40 EmitterError::Io(err)
41 }
42}
43
44impl fmt::Display for EmitterError {
45 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
58impl Error for EmitterError {
59 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
75pub type Result<T> = result::Result<T, EmitterError>;
77
78pub 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
94impl Emitter {
95 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)]
113enum IndentFlags {
114 WroteNothing,
115 WroteMarkup,
116 WroteText,
117}
118
119impl Emitter {
120 #[inline]
122 pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
123 &mut self.nst
124 }
125
126 #[inline]
127 fn wrote_text(&self) -> bool {
128 *self.indent_stack.last().unwrap() == IndentFlags::WroteText
129 }
130
131 #[inline]
132 fn wrote_markup(&self) -> bool {
133 *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup
134 }
135
136 #[inline]
137 fn set_wrote_text(&mut self) {
138 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText;
139 }
140
141 #[inline]
142 fn set_wrote_markup(&mut self) {
143 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup;
144 }
145
146 #[inline]
147 fn reset_state(&mut self) {
148 *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing;
149 }
150
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
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
171 fn after_markup(&mut self) {
172 self.set_wrote_markup();
173 }
174
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
181 fn after_start_element(&mut self) {
182 self.after_markup();
183 self.indent_level += 1;
184 }
185
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
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
204 fn after_text(&mut self) {
205 self.set_wrote_text();
206 }
207
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
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
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
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
283 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
298 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
317 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 NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
324 NS_NO_PREFIX => if uri != NS_EMPTY_URI {
328 write!(target, " xmlns=\"{}\"", uri)
329 } else { Ok(()) },
330 prefix => write!(target, " xmlns:{}=\"{}\"", prefix, uri)
332 }?;
333 }
334 Ok(())
335 }
336
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
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 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 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
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 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
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
417 pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
418 self.fix_non_empty_element(target)?;
419
420 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}