Skip to main content

vecdb/traits/
formattable.rs

1use std::fmt;
2
3/// Fast formatting trait that writes UTF-8 bytes directly into a buffer,
4/// avoiding the `std::fmt` machinery for number types.
5pub trait Formattable {
6    /// Write formatted UTF-8 bytes. Primary method — all others derive from it.
7    fn write_to(&self, buf: &mut Vec<u8>);
8
9    /// Write to a String via write_to.
10    #[inline(always)]
11    fn fmt_into(&self, f: &mut String) {
12        // SAFETY: write_to produces valid UTF-8 (itoa/ryu/Display guarantee this).
13        unsafe {
14            self.write_to(f.as_mut_vec());
15        }
16    }
17
18    /// Write in CSV format. Override for types needing CSV escaping (e.g., quoting commas).
19    #[inline(always)]
20    fn fmt_csv(&self, f: &mut String) -> fmt::Result {
21        self.fmt_into(f);
22        Ok(())
23    }
24
25    /// Write in JSON format. Override for types needing JSON wrapping (e.g., string quotes).
26    #[inline(always)]
27    fn fmt_json(&self, buf: &mut Vec<u8>) {
28        self.write_to(buf);
29    }
30}
31
32macro_rules! impl_formattable_int {
33    ($($t:ty),*) => {
34        $(
35            impl Formattable for $t {
36                #[inline(always)]
37                fn write_to(&self, buf: &mut Vec<u8>) {
38                    let mut b = itoa::Buffer::new();
39                    buf.extend_from_slice(b.format(*self).as_bytes());
40                }
41            }
42        )*
43    };
44}
45
46impl_formattable_int!(
47    u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize
48);
49
50macro_rules! impl_formattable_float {
51    ($($t:ty),*) => {
52        $(
53            impl Formattable for $t {
54                #[inline(always)]
55                fn write_to(&self, buf: &mut Vec<u8>) {
56                    let mut b = ryu::Buffer::new();
57                    buf.extend_from_slice(b.format(*self).as_bytes());
58                }
59            }
60        )*
61    };
62}
63
64impl_formattable_float!(f32, f64);
65
66impl Formattable for bool {
67    #[inline(always)]
68    fn write_to(&self, buf: &mut Vec<u8>) {
69        buf.extend_from_slice(if *self { b"true" } else { b"false" });
70    }
71}
72
73impl<T: Formattable> Formattable for Option<T> {
74    #[inline]
75    fn write_to(&self, buf: &mut Vec<u8>) {
76        if let Some(v) = self {
77            v.write_to(buf);
78        }
79    }
80
81    #[inline]
82    fn fmt_csv(&self, f: &mut String) -> fmt::Result {
83        if let Some(v) = self {
84            v.fmt_csv(f)?;
85        }
86        Ok(())
87    }
88
89    #[inline]
90    fn fmt_json(&self, buf: &mut Vec<u8>) {
91        match self {
92            Some(v) => v.fmt_json(buf),
93            None => buf.extend_from_slice(b"null"),
94        }
95    }
96}