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