r_extcap/controls/synchronous/
util.rs

1//! Random assortment of utility methods.
2
3use std::io::Read;
4
5/// Extension trait for [`Read`].
6pub trait ReadExt: Read {
7    /// Reads the exact number of bytes, like `read_exact`, but returns `None` if it gets EOF at
8    /// the start of the read. In other words, this is the "all or nothing" version of `read`.
9    fn try_read_exact<const N: usize>(&mut self) -> std::io::Result<Option<[u8; N]>> {
10        let mut buf = [0_u8; N];
11        let mut count = 0_usize;
12        while count < N {
13            let read_bytes = self.read(&mut buf[count..])?;
14            if read_bytes == 0 {
15                if count == 0 {
16                    return Ok(None);
17                } else {
18                    return Err(std::io::Error::from(std::io::ErrorKind::UnexpectedEof));
19                }
20            }
21            count += read_bytes;
22        }
23        Ok(Some(buf))
24    }
25}
26
27impl<R: ?Sized + Read> ReadExt for R {}
28
29#[cfg(test)]
30mod test {
31    use super::ReadExt;
32
33    #[test]
34    fn try_read_exact_success() {
35        let bytes = b"test";
36        let read_bytes = (&mut &bytes[..]).try_read_exact::<4>().unwrap();
37        assert_eq!(Some(bytes), read_bytes.as_ref());
38    }
39
40    #[test]
41    fn try_read_exact_long_success() {
42        let bytes = b"testing long string";
43        let mut slice = &bytes[..];
44        assert_eq!(
45            Some(b"test"),
46            (&mut slice).try_read_exact::<4>().unwrap().as_ref()
47        );
48        assert_eq!(
49            Some(b"ing "),
50            (&mut slice).try_read_exact::<4>().unwrap().as_ref()
51        );
52    }
53
54    #[test]
55    fn try_read_exact_none() {
56        let bytes = b"";
57        let read_bytes = (&mut &bytes[..]).try_read_exact::<4>().unwrap();
58        assert_eq!(None, read_bytes);
59    }
60
61    #[test]
62    fn try_read_exact_unexpected_eof() {
63        let bytes = b"tt";
64        let read_bytes = (&mut &bytes[..]).try_read_exact::<4>();
65        assert_eq!(
66            read_bytes.unwrap_err().kind(),
67            std::io::ErrorKind::UnexpectedEof
68        );
69    }
70}