snops_common/format/
impl_strings.rs

1use std::io::{Read, Write};
2
3use lasso::Spur;
4
5use super::{packed_int::PackedUint, DataFormat, DataReadError, DataWriteError};
6use crate::INTERN;
7
8impl DataFormat for String {
9    type Header = ();
10    const LATEST_HEADER: Self::Header = ();
11
12    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
13        let bytes = self.as_bytes();
14        Ok(PackedUint::from(bytes.len()).write_data(writer)? + writer.write(bytes)?)
15    }
16
17    fn read_data<R: Read>(reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
18        let len = usize::from(PackedUint::read_data(reader, &())?);
19        let mut buf = String::with_capacity(len);
20        let read_len = reader.take(len as u64).read_to_string(&mut buf)?;
21        if read_len != len {
22            return Err(DataReadError::Custom(format!(
23                "string expected to read {} bytes, but read {}",
24                len, read_len
25            )));
26        }
27        Ok(buf)
28    }
29}
30
31impl DataFormat for Spur {
32    type Header = ();
33    const LATEST_HEADER: Self::Header = ();
34
35    fn write_data<W: std::io::prelude::Write>(
36        &self,
37        writer: &mut W,
38    ) -> Result<usize, crate::format::DataWriteError> {
39        let s: &str = INTERN.resolve(self);
40        let bytes = s.as_bytes();
41        Ok(PackedUint::from(bytes.len()).write_data(writer)? + writer.write(bytes)?)
42    }
43
44    fn read_data<R: std::io::prelude::Read>(
45        reader: &mut R,
46        _header: &Self::Header,
47    ) -> Result<Self, crate::format::DataReadError> {
48        let data = String::read_data(reader, &())?;
49        Ok(INTERN.get_or_intern(data))
50    }
51}
52
53#[cfg(test)]
54#[rustfmt::skip]
55mod test {
56    use lasso::Spur;
57
58    use crate::{format::DataFormat, INTERN};
59
60    macro_rules! case {
61        ($name:ident, $ty:ty, $a:expr, $b:expr) => {
62            #[test]
63            fn $name() {
64                let mut data = Vec::new();
65                $a.write_data(&mut data).unwrap();
66                assert_eq!(data, $b);
67
68                let mut reader = &data[..];
69                let read_value = <$ty>::read_data(&mut reader, &()).unwrap();
70                assert_eq!(read_value, $a);
71
72            }
73
74        };
75    }
76
77    case!(test_string, String, "hello".to_string(), b"\x01\x05hello");
78    case!(test_spur, Spur, INTERN.get_or_intern("hello"), b"\x01\x05hello");
79    // 0x15 is 21, which is the length of the string
80    case!(test_long_string, String, "This is a long string".to_string(), b"\x01\x15This is a long string");
81    // 0x1A is 26, which is the length of the string
82    case!(test_interned_string, Spur, INTERN.get_or_intern("This is an interned string"), b"\x01\x1AThis is an interned string");
83    case!(test_empty_string, String, "".to_string(), [0]);
84    case!(test_empty_spur, Spur, INTERN.get_or_intern(""), [0]);
85}