use std::fmt;
pub trait Formattable {
fn write_to(&self, buf: &mut Vec<u8>);
#[inline(always)]
fn fmt_into(&self, f: &mut String) {
unsafe { self.write_to(f.as_mut_vec()); }
}
#[inline(always)]
fn fmt_csv(&self, f: &mut String) -> fmt::Result {
self.fmt_into(f);
Ok(())
}
#[inline(always)]
fn fmt_json(&self, buf: &mut Vec<u8>) {
self.write_to(buf);
}
}
macro_rules! impl_formattable_int {
($($t:ty),*) => {
$(
impl Formattable for $t {
#[inline(always)]
fn write_to(&self, buf: &mut Vec<u8>) {
let mut b = itoa::Buffer::new();
buf.extend_from_slice(b.format(*self).as_bytes());
}
}
)*
};
}
impl_formattable_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
macro_rules! impl_formattable_float {
($($t:ty),*) => {
$(
impl Formattable for $t {
#[inline(always)]
fn write_to(&self, buf: &mut Vec<u8>) {
let mut b = ryu::Buffer::new();
buf.extend_from_slice(b.format(*self).as_bytes());
}
}
)*
};
}
impl_formattable_float!(f32, f64);
impl Formattable for bool {
#[inline(always)]
fn write_to(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(if *self { b"true" } else { b"false" });
}
}
impl<T: Formattable> Formattable for Option<T> {
#[inline]
fn write_to(&self, buf: &mut Vec<u8>) {
if let Some(v) = self {
v.write_to(buf);
}
}
#[inline]
fn fmt_csv(&self, f: &mut String) -> fmt::Result {
if let Some(v) = self {
v.fmt_csv(f)?;
}
Ok(())
}
#[inline]
fn fmt_json(&self, buf: &mut Vec<u8>) {
match self {
Some(v) => v.fmt_json(buf),
None => buf.extend_from_slice(b"null"),
}
}
}