1use std::error::Error;
2use std::io::prelude::*;
3use std::{fmt, io, result};
4
5use crate::attribute::Attribute;
6use crate::common::XmlVersion;
7use crate::escape::{AttributeEscapes, Escaped, PcDataEscapes};
8use crate::name::{Name, OwnedName};
9use crate::namespace::{NamespaceStack, NS_EMPTY_URI, NS_NO_PREFIX, NS_XMLNS_PREFIX, NS_XML_PREFIX};
10
11use crate::writer::config::EmitterConfig;
12
13#[derive(Debug)]
15#[non_exhaustive]
16pub enum EmitterError {
17 Io(io::Error),
19
20 DocumentStartAlreadyEmitted,
22
23 LastElementNameNotAvailable,
25
26 EndElementNameIsNotEqualToLastStartElementName,
29
30 EndElementNameIsNotSpecified,
33}
34
35impl Clone for EmitterError {
36 #[cold]
37 fn clone(&self) -> Self {
38 match self {
39 Self::Io(io_error) => Self::Io(io::Error::new(io_error.kind(), io_error.to_string())),
40 Self::DocumentStartAlreadyEmitted => Self::DocumentStartAlreadyEmitted,
41 Self::LastElementNameNotAvailable => Self::LastElementNameNotAvailable,
42 Self::EndElementNameIsNotEqualToLastStartElementName => Self::EndElementNameIsNotEqualToLastStartElementName,
43 Self::EndElementNameIsNotSpecified => Self::EndElementNameIsNotSpecified,
44 }
45 }
46}
47
48impl From<io::Error> for EmitterError {
49 #[cold]
50 fn from(err: io::Error) -> Self {
51 Self::Io(err)
52 }
53}
54
55impl fmt::Display for EmitterError {
56 #[cold]
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 f.write_str("emitter error: ")?;
59 match self {
60 Self::Io(e) => write!(f, "I/O error: {e}"),
61 Self::DocumentStartAlreadyEmitted => f.write_str("document start event has already been emitted"),
62 Self::LastElementNameNotAvailable => f.write_str("last element name is not available"),
63 Self::EndElementNameIsNotEqualToLastStartElementName => f.write_str("end element name is not equal to last start element name"),
64 Self::EndElementNameIsNotSpecified => f.write_str("end element name is not specified and can't be inferred"),
65 }
66 }
67}
68
69impl Error for EmitterError {
70 fn source(&self) -> Option<&(dyn Error + 'static)> {
71 match self {
72 Self::Io(e) => e.source(),
73 _ => None,
74 }
75 }
76}
77
78pub type Result<T, E = EmitterError> = result::Result<T, E>;
80
81pub struct Emitter {
84 config: EmitterConfig,
85
86 nst: NamespaceStack,
87
88 indent_level: usize,
89 indent_stack: Vec<IndentFlags>,
90
91 element_names: Vec<OwnedName>,
92
93 start_document_emitted: bool,
94 just_wrote_start_element: bool,
95}
96
97impl Emitter {
98 pub fn new(config: EmitterConfig) -> Self {
99 let mut indent_stack = Vec::with_capacity(16);
100 indent_stack.push(IndentFlags::WroteNothing);
101
102 Self {
103 config,
104
105 nst: NamespaceStack::empty(),
106
107 indent_level: 0,
108 indent_stack,
109
110 element_names: Vec::new(),
111
112 start_document_emitted: false,
113 just_wrote_start_element: false,
114 }
115 }
116}
117
118#[derive(Copy, Clone, Eq, PartialEq, Debug)]
119enum IndentFlags {
120 WroteNothing,
121 WroteMarkup,
122 WroteText,
123}
124
125impl Emitter {
126 #[inline]
128 pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
129 &mut self.nst
130 }
131
132 #[inline]
133 fn wrote_text(&self) -> bool {
134 self.indent_stack.last().is_some_and(|&e| e == IndentFlags::WroteText)
135 }
136
137 #[inline]
138 fn wrote_markup(&self) -> bool {
139 self.indent_stack.last().is_some_and(|&e| e == IndentFlags::WroteMarkup)
140 }
141
142 #[inline]
143 fn set_wrote_text(&mut self) {
144 if let Some(e) = self.indent_stack.last_mut() {
145 *e = IndentFlags::WroteText;
146 }
147 }
148
149 #[inline]
150 fn set_wrote_markup(&mut self) {
151 if let Some(e) = self.indent_stack.last_mut() {
152 *e = IndentFlags::WroteMarkup;
153 }
154 }
155
156 fn write_newline<W: Write>(&self, target: &mut W, level: usize) -> Result<()> {
157 target.write_all(self.config.line_separator.as_bytes())?;
158 for _ in 0..level {
159 target.write_all(self.config.indent_string.as_bytes())?;
160 }
161 Ok(())
162 }
163
164 fn before_markup<W: Write>(&mut self, target: &mut W) -> Result<()> {
165 if self.config.perform_indent && !self.wrote_text() &&
166 (self.indent_level > 0 || self.wrote_markup()) {
167 let indent_level = self.indent_level;
168 self.write_newline(target, indent_level)?;
169 if self.indent_level > 0 && !self.config.indent_string.is_empty() {
170 self.after_markup();
171 }
172 }
173 Ok(())
174 }
175
176 fn after_markup(&mut self) {
177 self.set_wrote_markup();
178 }
179
180 fn before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
181 self.before_markup(target)?;
182 self.indent_stack.push(IndentFlags::WroteNothing);
183 Ok(())
184 }
185
186 fn after_start_element(&mut self) {
187 self.after_markup();
188 self.indent_level += 1;
189 }
190
191 fn before_end_element<W: Write>(&self, target: &mut W) -> Result<()> {
192 if self.config.perform_indent && self.indent_level > 0 && self.wrote_markup() &&
193 !self.wrote_text() {
194 let indent_level = self.indent_level;
195 self.write_newline(target, indent_level - 1)
196 } else {
197 Ok(())
198 }
199 }
200
201 fn after_end_element(&mut self) {
202 if self.indent_level > 0 {
203 self.indent_level -= 1;
204 self.indent_stack.pop();
205 }
206 self.set_wrote_markup();
207 }
208
209 fn after_text(&mut self) {
210 self.set_wrote_text();
211 }
212
213 pub fn emit_start_document<W: Write>(&mut self, target: &mut W,
214 version: XmlVersion,
215 encoding: &str,
216 standalone: Option<bool>) -> Result<()> {
217 if self.start_document_emitted {
218 return Err(EmitterError::DocumentStartAlreadyEmitted);
219 }
220 self.start_document_emitted = true;
221
222 self.before_markup(target)?;
223 let result = {
224 let mut write = move || {
225 write!(target, "<?xml version=\"{version}\" encoding=\"{encoding}\"")?;
226
227 if let Some(standalone) = standalone {
228 write!(target, " standalone=\"{}\"", if standalone { "yes" } else { "no" })?;
229 }
230
231 write!(target, "?>")?;
232
233 Ok(())
234 };
235 write()
236 };
237 self.after_markup();
238
239 result
240 }
241
242 fn check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()> {
243 if !self.start_document_emitted && self.config.write_document_declaration {
244 self.emit_start_document(target, XmlVersion::Version10, "UTF-8", None)
245 } else {
246 Ok(())
247 }
248 }
249
250 fn fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
251 if self.config.normalize_empty_elements && self.just_wrote_start_element {
252 self.just_wrote_start_element = false;
253 target.write_all(b">").map_err(From::from)
254 } else {
255 Ok(())
256 }
257 }
258
259 pub fn emit_processing_instruction<W: Write>(&mut self,
260 target: &mut W,
261 name: &str,
262 data: Option<&str>) -> Result<()> {
263 self.check_document_started(target)?;
264 self.fix_non_empty_element(target)?;
265
266 self.before_markup(target)?;
267
268 let result = {
269 let mut write = move || {
270 write!(target, "<?{name}")?;
271
272 if let Some(data) = data {
273 write!(target, " {data}")?;
274 }
275
276 write!(target, "?>")?;
277
278 Ok(())
279 };
280 write()
281 };
282
283 self.after_markup();
284
285 result
286 }
287
288 #[track_caller]
289 fn emit_start_element_initial<W>(&mut self, target: &mut W,
290 name: Name<'_>,
291 attributes: &[Attribute<'_>]) -> Result<()>
292 where W: Write
293 {
294 self.check_document_started(target)?;
295 self.fix_non_empty_element(target)?;
296 self.before_start_element(target)?;
297 write!(target, "<{}", name.repr_display())?;
298 self.emit_current_namespace_attributes(target)?;
299 self.emit_attributes(target, attributes)?;
300 self.after_start_element();
301 Ok(())
302 }
303
304 #[track_caller]
305 pub fn emit_start_element<W>(&mut self, target: &mut W,
306 name: Name<'_>,
307 attributes: &[Attribute<'_>]) -> Result<()>
308 where W: Write
309 {
310 if self.config.keep_element_names_stack {
311 self.element_names.push(name.to_owned());
312 }
313
314 self.emit_start_element_initial(target, name, attributes)?;
315 self.just_wrote_start_element = true;
316
317 if !self.config.normalize_empty_elements {
318 write!(target, ">")?;
319 }
320
321 Ok(())
322 }
323
324 #[track_caller]
325 pub fn emit_current_namespace_attributes<W>(&self, target: &mut W) -> Result<()>
326 where W: Write
327 {
328 for (prefix, uri) in self.nst.peek() {
329 match prefix {
330 NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
332 NS_NO_PREFIX => if uri == NS_EMPTY_URI {
336 Ok(())
337 } else {
338 write!(target, " xmlns=\"{uri}\"")
339 },
340 prefix => write!(target, " xmlns:{prefix}=\"{uri}\""),
342 }?;
343 }
344 Ok(())
345 }
346
347 pub fn emit_attributes<W: Write>(&self, target: &mut W, attributes: &[Attribute<'_>]) -> Result<()> {
348 for attr in attributes {
349 write!(target, " {}=\"", attr.name.repr_display())?;
350 if self.config.perform_escaping {
351 write!(target, "{}", Escaped::<AttributeEscapes>::new(attr.value))?;
352 } else {
353 write!(target, "{}", attr.value)?;
354 }
355 write!(target, "\"")?;
356 }
357 Ok(())
358 }
359
360 pub fn emit_end_element<W: Write>(&mut self, target: &mut W, name: Option<Name<'_>>) -> Result<()> {
361 let owned_name = if self.config.keep_element_names_stack {
362 Some(self.element_names.pop().ok_or(EmitterError::LastElementNameNotAvailable)?)
363 } else {
364 None
365 };
366
367 if let Some(ref last_name) = owned_name {
369 if let Some(ref name) = name {
370 if last_name.borrow() != *name {
371 return Err(EmitterError::EndElementNameIsNotEqualToLastStartElementName);
372 }
373 }
374 }
375
376 if let Some(name) = owned_name.as_ref().map(|n| n.borrow()).or(name) {
377 if self.config.normalize_empty_elements && self.just_wrote_start_element {
378 self.just_wrote_start_element = false;
379 let termination = if self.config.pad_self_closing { " />" } else { "/>" };
380 let result = target.write_all(termination.as_bytes()).map_err(From::from);
381 self.after_end_element();
382 result
383 } else {
384 self.just_wrote_start_element = false;
385
386 self.before_end_element(target)?;
387 let result = write!(target, "</{}>", name.repr_display()).map_err(From::from);
388 self.after_end_element();
389
390 result
391 }
392 } else {
393 Err(EmitterError::EndElementNameIsNotSpecified)
394 }
395 }
396
397 pub fn emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
398 self.fix_non_empty_element(target)?;
399 if self.config.cdata_to_characters {
400 self.emit_characters(target, content)
401 } else {
402 target.write_all(b"<![CDATA[")?;
403
404 for chunk in content.split_inclusive("]]>") {
405 let chunk_safe = chunk.strip_suffix("]]>");
406 let emit_escaped = chunk_safe.is_some();
407
408 target.write_all(chunk_safe.unwrap_or(chunk).as_bytes())?;
409 if emit_escaped {
410 target.write_all(b"]]]]><![CDATA[>")?;
411 }
412 }
413
414 target.write_all(b"]]>")?;
415 self.after_text();
416
417 Ok(())
418 }
419 }
420
421 pub fn emit_characters<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
422 self.check_document_started(target)?;
423 self.fix_non_empty_element(target)?;
424
425 if self.config.perform_escaping {
426 write!(target, "{}", Escaped::<PcDataEscapes>::new(content))?;
427 } else {
428 target.write_all(content.as_bytes())?;
429 }
430
431 self.after_text();
432 Ok(())
433 }
434
435 pub fn emit_raw_characters<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
436 self.check_document_started(target)?;
437 self.fix_non_empty_element(target)?;
438
439 target.write_all(content.as_bytes())?;
440
441 self.after_text();
442 Ok(())
443 }
444
445 pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
446 self.fix_non_empty_element(target)?;
447
448 let autopad_comments = self.config.autopad_comments;
451 let write = move |target: &mut W| -> Result<()> {
452 target.write_all(b"<!--")?;
453
454 if autopad_comments && !content.starts_with(char::is_whitespace) {
455 target.write_all(b" ")?;
456 }
457
458 for chunk in content.split_inclusive("--") {
459 let chunk_safe = chunk.strip_suffix("--");
460 let emit_escaped = chunk_safe.is_some();
461
462 target.write_all(chunk_safe.unwrap_or(chunk).as_bytes())?;
463 if emit_escaped {
464 target.write_all(b"- ")?;
465 }
466 }
467
468 if autopad_comments && !content.ends_with(char::is_whitespace) {
469 target.write_all(b" ")?;
470 }
471
472 target.write_all(b"-->")?;
473
474 Ok(())
475 };
476
477 self.before_markup(target)?;
478 let result = write(target);
479 self.after_markup();
480
481 result
482 }
483}