encode/encoders/
size.rs

1use core::fmt::Write;
2
3use crate::BaseEncoder;
4use crate::ByteEncoder;
5
6/// An encoder that counts the size of the encoded data.
7///
8/// This encoder is useful for calculating the size of the encoded data without
9/// actually encoding it, allowing you to pre-allocate a buffer of the correct
10/// size before encoding the data.
11///
12/// Note that this encoder runs all the same encoding logic as any other
13/// encoder, so it will trigger the same side effects that other encoders would
14/// trigger (e.g Allocations). See the [`Encodable`] trait for more information
15/// on idempotent encodes.
16///
17/// # Example
18///
19/// ```
20/// use encode::Encodable;
21/// use encode::encoders::SizeEncoder;
22///
23/// let encodable = c"hello, world!";
24/// let mut encoder = SizeEncoder::new();
25/// encodable.encode(&mut encoder).unwrap();
26/// assert_eq!(encoder.size(), 14, "13 bytes from the ASCII string and 1 byte for the null terminator");
27/// ```
28///
29/// [`Encodable`]: crate::Encodable
30#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
31#[repr(transparent)]
32pub struct SizeEncoder {
33    size: usize,
34}
35
36impl SizeEncoder {
37    /// Creates a new [`SizeEncoder`].
38    #[inline]
39    #[must_use]
40    pub fn new() -> Self {
41        Self::default()
42    }
43
44    /// Returns the size of the encoded data.
45    #[inline]
46    #[must_use]
47    pub fn size(&self) -> usize {
48        (*self).into()
49    }
50}
51
52impl From<SizeEncoder> for usize {
53    #[inline]
54    fn from(encoder: SizeEncoder) -> usize {
55        encoder.size
56    }
57}
58
59impl Write for SizeEncoder {
60    #[inline]
61    fn write_str(&mut self, s: &str) -> core::fmt::Result {
62        self.size += s.len();
63        Ok(())
64    }
65}
66
67impl BaseEncoder for SizeEncoder {
68    type Error = core::convert::Infallible;
69}
70
71impl ByteEncoder for SizeEncoder {
72    #[inline]
73    fn put_slice(&mut self, slice: &[u8]) -> Result<(), Self::Error> {
74        self.size += slice.len();
75        Ok(())
76    }
77
78    #[inline]
79    fn put_byte(&mut self, _byte: u8) -> Result<(), Self::Error> {
80        self.size += 1;
81        Ok(())
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    #[test]
89    fn assert_that_size_encoder_can_be_used_with_format_strings() {
90        let mut size_encoder = SizeEncoder::new();
91        let s = "hello world";
92        write!(size_encoder, "{s}").unwrap();
93        assert_eq!(size_encoder.size(), s.len());
94    }
95}