Skip to main content

frame_protocol/
lib.rs

1use std::io::Read;
2
3pub fn write_frame<W: std::io::Write>(writer: &mut W, message: &str) -> std::io::Result<usize> {
4    let size = u16::try_from(message.len());
5    if let Ok(size) = size {
6        let _ = writer.write(&size.to_le_bytes())?;
7        writer.write(message.as_bytes())
8    } else {
9        Err(std::io::Error::new(
10            std::io::ErrorKind::FileTooLarge,
11            "frame-protocol supports a maximum frame size of 65536",
12        ))
13    }
14}
15
16pub struct FrameReader<R> {
17    reader: R,
18}
19
20impl<R> FrameReader<R> {
21    pub fn new(reader: R) -> Self {
22        Self { reader }
23    }
24}
25
26impl<R: Read> Iterator for FrameReader<R> {
27    type Item = std::io::Result<String>;
28
29    fn next(&mut self) -> Option<Self::Item> {
30        let mut marker_buf = [0u8; 2];
31        let result = self.reader.read_exact(&mut marker_buf);
32        if let Err(err) = result {
33            return if let std::io::ErrorKind::UnexpectedEof = err.kind() {
34                None
35            } else {
36                Some(Err(err))
37            };
38        };
39
40        let size = u16::from_le_bytes(marker_buf);
41        let mut buf = String::with_capacity(size.into());
42        let result = self
43            .reader
44            .by_ref()
45            .take(size.into())
46            .read_to_string(&mut buf);
47
48        match result {
49            Ok(_) => Some(Ok(buf)),
50            Err(err) => Some(Err(err)),
51        }
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn read_write() {
61        let mut buffer: Vec<u8> = Vec::new();
62
63        write_frame(&mut buffer, "Hello World").unwrap();
64        write_frame(&mut buffer, "Test").unwrap();
65
66        let out: Result<Vec<String>, _> = FrameReader::new(buffer.as_slice()).collect();
67        let out: Vec<String> = out.unwrap();
68
69        assert_eq!(out, &["Hello World".to_string(), "Test".to_string()]);
70    }
71}