#![no_std]
#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
#![forbid(unsafe_code)]
#![allow(unused_attributes)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(meta_variable_misuse)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(non_ascii_idents)]
#![warn(noop_method_call)]
#![warn(single_use_lifetimes)]
#![warn(trivial_casts)]
#![warn(unreachable_pub)]
#![warn(unused_crate_dependencies)]
#![warn(unused_extern_crates)]
#![warn(unused_lifetimes)]
#![warn(unused_results)]
#![no_implicit_prelude]
#![cfg_attr(feature = "docsrs", doc = ::document_features::document_features!())]
#[doc(hidden)]
pub mod details;
mod raw_marker;
use details::alloc;
use details::std::fmt::{self, Arguments, Write as _};
use details::std::prelude::v1::*;
use details::std::write;
pub use raw_marker::{EscapeTag, RawMarker, RawTag};
#[doc(hidden)]
pub trait WriteAny {
fn write_fmt(&mut self, fmt: Arguments<'_>) -> fmt::Result;
}
pub trait RenderInto {
#[doc(hidden)]
fn render_into(&self, output: impl WriteAny) -> fmt::Result;
#[inline]
fn render_fmt(&self, output: impl fmt::Write) -> fmt::Result {
self.render_into(details::WriteFmt(output))
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
fn render_io(&self, output: impl alloc::io::Write) -> fmt::Result {
self.render_into(details::WriteIo(output))
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(any(feature = "alloc", feature = "std"))))]
fn render_string(&self) -> Result<alloc::string::String, fmt::Error> {
let mut result = String::new();
self.render_fmt(&mut result)?;
Ok(result)
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(any(feature = "alloc", feature = "std"))))]
fn render_bytes(&self) -> Result<alloc::vec::Vec<u8>, fmt::Error> {
let mut result = Vec::new();
self.render_io(&mut result)?;
Ok(result)
}
}
pub struct XmlEscape<T: ?Sized>(pub T);
impl<T: ?Sized + fmt::Display> fmt::Display for XmlEscape<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(XmlEscapeWriter(f), "{}", &self.0)
}
}
impl<T: ?Sized + fmt::Debug> fmt::Debug for XmlEscape<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(XmlEscapeWriter(f), "{:?}", &self.0)
}
}
struct XmlEscapeWriter<'a, 'b>(&'a mut fmt::Formatter<'b>);
impl fmt::Write for XmlEscapeWriter<'_, '_> {
fn write_str(&mut self, mut s: &str) -> fmt::Result {
loop {
let mut done = true;
for (i, c) in s.as_bytes().iter().enumerate() {
let c = match c {
b'"' => """,
b'&' => "&",
b'\'' => "'",
b'<' => "<",
b'>' => ">",
_ => continue,
};
write!(self.0, "{}{}", &s[..i], c)?;
s = &s[i + 1..];
done = false;
break;
}
if done {
if !s.is_empty() {
self.0.write_str(s)?;
}
break Ok(());
}
}
}
fn write_char(&mut self, c: char) -> fmt::Result {
self.0.write_str(match c {
'"' => """,
'&' => "&",
'\'' => "'",
'<' => "<",
'>' => ">",
c => return self.0.write_char(c),
})
}
}