use core::fmt;
use core::marker::PhantomData;
#[derive(Debug)]
pub struct PrettyIndent {
prefix: &'static str,
level: usize
}
impl PrettyIndent {
pub fn new(prefix: &'static str) -> PrettyIndent {
PrettyIndent { prefix: prefix, level: 0 }
}
pub fn increase(&mut self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "\n")?;
self.level += 1;
Ok(())
}
}
impl fmt::Display for PrettyIndent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.level == 0 {
write!(f, "{}", self.prefix)
} else {
write!(f, "{0:1$}{0:2$}\\ ", "", self.prefix.len(), self.level - 1)
}
}
}
pub trait PrettyPrint {
fn pretty_print(buffer: &[u8], fmt: &mut fmt::Formatter,
indent: &mut PrettyIndent) -> fmt::Result;
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Formatter<T: PrettyPrint + ?Sized> {
_inner: PhantomData<T>,
}
pub struct PrettyPrinter<'a, T: PrettyPrint + ?Sized> {
prefix: &'static str,
buffer: &'a [u8],
phantom: PhantomData<T>
}
impl<'a, T: PrettyPrint + ?Sized> PrettyPrinter<'a, T> {
pub fn new(prefix: &'static str, buffer: &'a (impl AsRef<[u8]> + ?Sized)) -> PrettyPrinter<'a, T> {
PrettyPrinter {
prefix: prefix,
buffer: buffer.as_ref(),
phantom: PhantomData
}
}
}
impl<'a, T: PrettyPrint + AsRef<[u8]> + ?Sized> PrettyPrinter<'a, T> {
pub fn print(printable: &'a T) -> PrettyPrinter<'a, T> {
PrettyPrinter {
prefix: "",
buffer: printable.as_ref(),
phantom: PhantomData,
}
}
}
impl<'a, T: PrettyPrint + ?Sized> fmt::Display for PrettyPrinter<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
T::pretty_print(&self.buffer, f, &mut PrettyIndent::new(self.prefix))
}
}
impl<T: PrettyPrint + ?Sized> Clone for Formatter<T> {
fn clone(&self) -> Self {
Formatter { ..*self }
}
}
impl<T: PrettyPrint + ?Sized> Copy for Formatter<T> { }
impl<T: PrettyPrint + ?Sized> Default for Formatter<T> {
fn default() -> Self {
Formatter { _inner: PhantomData::default() }
}
}