Skip to main content

ser_file/
fixed_string.rs

1use binrw::{BinRead, BinResult, BinWrite};
2
3/// A fixed-width array of bytes representing an ASCII string.
4///
5/// The bytes default to all zeros, but this string may not necessarily
6/// terminate with a `'\0'` if all bytes are used.
7pub struct FixedString<const N: usize>([u8; N]);
8
9impl<const N: usize> FixedString<N> {
10    pub fn new(bytes: [u8; N]) -> Self {
11        Self(bytes)
12    }
13}
14
15impl<const N: usize> Default for FixedString<N> {
16    fn default() -> Self {
17        Self([0u8; N])
18    }
19}
20
21impl<const N: usize> std::fmt::Display for FixedString<N> {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        let FixedString(bytes) = self;
24        f.write_str(String::from_utf8_lossy(bytes).as_ref())
25    }
26}
27
28impl<const N: usize> From<FixedString<N>> for String {
29    fn from(FixedString(bytes): FixedString<N>) -> Self {
30        String::from_utf8_lossy(&bytes).to_string()
31    }
32}
33
34impl<const N: usize> From<String> for FixedString<N> {
35    fn from(value: String) -> Self {
36        let mut bytes = [0u8; N];
37        bytes.copy_from_slice(&value.as_bytes()[..N]);
38        FixedString(bytes)
39    }
40}
41
42impl<const N: usize> BinRead for FixedString<N> {
43    type Args<'a> = ();
44
45    fn read_options<R: std::io::Read + std::io::Seek>(
46        reader: &mut R,
47        endian: binrw::Endian,
48        _args: Self::Args<'_>,
49    ) -> BinResult<Self> {
50        Ok(FixedString(<[u8; N]>::read_options(reader, endian, ())?))
51    }
52}
53
54impl<const N: usize> BinWrite for FixedString<N> {
55    type Args<'a> = ();
56
57    fn write_options<W: std::io::Write + std::io::Seek>(
58        &self,
59        writer: &mut W,
60        endian: binrw::Endian,
61        _args: Self::Args<'_>,
62    ) -> BinResult<()> {
63        let FixedString(bytes) = self;
64        bytes.write_options(writer, endian, ())
65    }
66}