flams_utils/
binary.rs

1use std::io::{BufRead, BufWriter, Write};
2
3#[allow(clippy::missing_errors_doc)]
4pub trait BinaryWriter:Write {
5    fn write_string(&mut self, s: &str) -> std::io::Result<()>;
6    fn write_u16(&mut self, u: u16) -> std::io::Result<()>;
7}
8
9#[allow(clippy::missing_errors_doc)]
10pub trait BinaryReader: BufRead {
11    fn read_string<R>(&mut self, f: impl FnOnce(&str) -> R) -> Result<R, DecodeError>;
12    fn read_u16(&mut self) -> Result<u16, DecodeError>;
13    fn pop(&mut self) -> Result<u8, DecodeError>;
14}
15
16impl<W: Write> BinaryWriter for BufWriter<W> {
17    #[inline]
18    fn write_string(&mut self, s: &str) -> std::io::Result<()> {
19        self.write_all(s.as_bytes())?;
20        self.write_all(&[0])
21    }
22
23    #[inline]
24    fn write_u16(&mut self, u: u16) -> std::io::Result<()> {
25        self.write_all(&u.to_le_bytes())
26    }
27}
28
29impl<B: BufRead> BinaryReader for B {
30    fn read_string<R>(&mut self, f: impl FnOnce(&str) -> R) -> Result<R, DecodeError> {
31        let mut buf = Vec::new();
32        self.read_until(0, &mut buf)?;
33        buf.pop();
34        let s = std::str::from_utf8(buf.as_slice())?;
35        Ok(f(s))
36    }
37    fn read_u16(&mut self) -> Result<u16, DecodeError> {
38        let mut buf = [0u8, 0u8];
39        self.read_exact(&mut buf)?;
40        Ok(u16::from_le_bytes(buf))
41    }
42    fn pop(&mut self) -> Result<u8, DecodeError> {
43        let mut buf = [0];
44        self.read_exact(&mut buf)?;
45        Ok(buf[0])
46    }
47}
48
49#[cfg(feature = "tokio")]
50pub trait AsyncBinaryReader: tokio::io::AsyncBufReadExt + Unpin + Send {
51    fn read_string<R>(
52        &mut self,
53        f: impl (FnOnce(&str) -> R) + Send,
54    ) -> impl std::future::Future<Output = Result<R, DecodeError>> + Send;
55}
56
57#[cfg(feature = "tokio")]
58impl<B: tokio::io::AsyncBufReadExt + Unpin + Send> AsyncBinaryReader for B {
59    async fn read_string<R>(
60        &mut self,
61        f: impl (FnOnce(&str) -> R) + Send,
62    ) -> Result<R, DecodeError> {
63        let mut buf = Vec::new();
64        self.read_until(0, &mut buf).await?;
65        buf.pop();
66        let s = std::str::from_utf8(buf.as_slice())?;
67        Ok(f(s))
68    }
69}
70
71pub enum DecodeError {
72    Io(std::io::Error),
73    Utf8(std::str::Utf8Error),
74}
75impl From<std::io::Error> for DecodeError {
76    #[inline]
77    fn from(value: std::io::Error) -> Self {
78        Self::Io(value)
79    }
80}
81impl From<std::str::Utf8Error> for DecodeError {
82    #[inline]
83    fn from(value: std::str::Utf8Error) -> Self {
84        Self::Utf8(value)
85    }
86}