hypo 0.1.0

tiny crate that renders html through macros
Documentation
/// what can be rendered to html
pub trait Render {
    fn render(&self, to: &mut String);
}

impl Render for char {
    fn render(&self, to: &mut String) {
        crate::escape::char(*self, to);
    }
}

impl Render for &str {
    fn render(&self, to: &mut String) {
        crate::escape::str(self, to);
    }
}

impl Render for String {
    fn render(&self, to: &mut String) {
        crate::escape::str(self, to);
    }
}

macro_rules! impl_for_numbers {
    ($($number:ty)+) => {$(
        impl Render for $number {
            fn render(&self, to: &mut String) {
                #[cfg(feature = "perf")]
                itoap::write_to_string(to, *self);
                #[cfg(not(feature = "perf"))]
                to.push_str(&self.to_string());
            }
        }
    )*};
}

impl_for_numbers!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);

impl<R: Render> Render for Option<R> {
    fn render(&self, to: &mut String) {
        if let Some(r) = self {
            r.render(to);
        }
    }
}

impl<R1: Render, R2: Render> Render for Result<R1, R2> {
    fn render(&self, to: &mut String) {
        match self {
            Ok(r) => r.render(to),
            Err(r) => r.render(to),
        }
    }
}

impl<R: Render> Render for &[R] {
    fn render(&self, to: &mut String) {
        for r in *self {
            r.render(to);
        }
    }
}

impl<const N: usize, R: Render> Render for [R; N] {
    fn render(&self, to: &mut String) {
        for r in self {
            r.render(to);
        }
    }
}

impl<R: Render> Render for Vec<R> {
    fn render(&self, to: &mut String) {
        for r in self {
            r.render(to);
        }
    }
}

macro_rules! impl_for_tuples {
    ($head:ident) => {
        impl Render for () {
            fn render(&self, _: &mut String) {}
        }
    };
    ($head:ident $($tail:ident)+) => {
        impl <$($tail: Render),*> Render for ($($tail),*,) {
            fn render(&self, to: &mut String) {
                #[allow(non_snake_case, reason = "macro")]
                let ($($tail),*,) = self;
                ($($tail.render(to)),*);
            }
        }

        impl_for_tuples!($($tail)*);
    };
}

impl_for_tuples!(I H G F E D C B A);

/// renders directly without any escaping
pub struct Raw<T>(pub T);
impl<T: AsRef<str>> Render for Raw<T> {
    fn render(&self, to: &mut String) {
        to.push_str(self.0.as_ref());
    }
}

/// renders lazily delegating to a function
pub struct Fn<F>(pub F);
impl<F: std::ops::Fn(&mut String)> Render for Fn<F> {
    fn render(&self, to: &mut String) {
        self.0(to);
    }
}