use std::fmt;
use std::io;
pub trait Render {
fn render(&self, &mut fmt::Write) -> fmt::Result;
}
impl<T: fmt::Display + ?Sized> Render for T {
fn render(&self, w: &mut fmt::Write) -> fmt::Result {
use std::fmt::Write;
write!(Escaper::new(w), "{}", self)
}
}
#[derive(Debug)]
pub struct PreEscaped<T>(pub T);
impl<T: fmt::Display> Render for PreEscaped<T> {
fn render(&self, w: &mut fmt::Write) -> fmt::Result {
use std::fmt::Write;
write!(w, "{}", self.0)
}
}
pub struct Escaper<W: fmt::Write> {
inner: W,
}
impl<W: fmt::Write> Escaper<W> {
pub fn new(inner: W) -> Escaper<W> {
Escaper { inner: inner }
}
pub fn into_inner(self) -> W {
self.inner
}
}
impl<W: fmt::Write> fmt::Write for Escaper<W> {
fn write_str(&mut self, s: &str) -> fmt::Result {
for c in s.chars() {
try!(match c {
'&' => self.inner.write_str("&"),
'<' => self.inner.write_str("<"),
'>' => self.inner.write_str(">"),
'"' => self.inner.write_str("""),
'\'' => self.inner.write_str("'"),
_ => self.inner.write_char(c),
});
}
Ok(())
}
}
pub struct Utf8Writer<W: io::Write> {
inner: W,
result: io::Result<()>,
}
impl<W: io::Write> Utf8Writer<W> {
pub fn new(inner: W) -> Utf8Writer<W> {
Utf8Writer {
inner: inner,
result: Ok(()),
}
}
pub fn into_inner(self) -> (W, io::Result<()>) {
let Utf8Writer { inner, result } = self;
(inner, result)
}
pub fn into_result(self) -> io::Result<()> {
self.result
}
}
impl<W: io::Write> fmt::Write for Utf8Writer<W> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match io::Write::write_all(&mut self.inner, s.as_bytes()) {
Ok(()) => Ok(()),
Err(e) => {
self.result = Err(e);
Err(fmt::Error)
}
}
}
fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
match io::Write::write_fmt(&mut self.inner, args) {
Ok(()) => Ok(()),
Err(e) => {
self.result = Err(e);
Err(fmt::Error)
}
}
}
}