use std::fmt::{self, Write};
pub(super) struct EscapeGuard<T> {
pub(super) value: T,
pub(super) sanitize: bool,
}
impl<T> EscapeGuard<T> {
pub(super) fn new(value: T, sanitize: bool) -> Self {
Self { value, sanitize }
}
}
struct EscapingWriter<'a, 'b> {
inner: &'a mut fmt::Formatter<'b>,
}
impl<'a, 'b> fmt::Write for EscapingWriter<'a, 'b> {
fn write_str(&mut self, s: &str) -> fmt::Result {
for ch in s.chars() {
match ch {
'\x1b' => self.inner.write_str("\\x1b")?, '\x07' => self.inner.write_str("\\x07")?, '\x08' => self.inner.write_str("\\x08")?, '\x0c' => self.inner.write_str("\\x0c")?, '\x7f' => self.inner.write_str("\\x7f")?,
ch if ch as u32 >= 0x80 && ch as u32 <= 0x9f => {
write!(self.inner, "\\u{{{:x}}}", ch as u32)?
}
_ => self.inner.write_char(ch)?,
}
}
Ok(())
}
}
impl<T: fmt::Debug> fmt::Debug for EscapeGuard<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.sanitize {
let mut escaping_writer = EscapingWriter { inner: f };
write!(escaping_writer, "{:?}", self.value)
} else {
write!(f, "{:?}", self.value)
}
}
}
impl<T: fmt::Display> fmt::Display for EscapeGuard<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.sanitize {
let mut escaping_writer = EscapingWriter { inner: f };
write!(escaping_writer, "{}", self.value)
} else {
write!(f, "{}", self.value)
}
}
}