r_extcap/controls/synchronous/
util.rs1use std::io::Read;
4
5pub trait ReadExt: Read {
7 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}