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);
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());
}
}
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);
}
}