bread_cli/
binary.rs

1use crate::byte_writer::ByteWriter;
2use crate::error::{InError, OutError};
3use crate::util;
4use crate::util::literals::*;
5use std::io::{Bytes, Read, Write};
6
7/// An iterator over Result<u8,[InError]>
8///
9/// Reads bytes from the input stream in binary base format, that is a multiple of 8 characters 0 and 1 are
10/// allowed (and any number of whitespace characters that will be skipped)
11///
12/// [InError]: crate::error::InError
13pub struct Reader<R: Read> {
14    in_bytes: Bytes<R>,
15}
16
17impl<R: Read> Reader<R> {
18    pub fn new(read: R) -> Self {
19        Reader {
20            in_bytes: read.bytes(),
21        }
22    }
23}
24
25impl<R: Read> Iterator for Reader<R> {
26    type Item = Result<u8, InError>;
27    fn next(&mut self) -> Option<Self::Item> {
28        let mut value = 0u8;
29        let mut i = 7i8;
30        while i >= 0 {
31            let in_byte = self.in_bytes.next();
32            match in_byte {
33                None => {
34                    return if i == 7 {
35                        None
36                    } else {
37                        Some(Err(InError::ShortIO {
38                            bytes: 7 - i as usize,
39                            expected: 8,
40                        }))
41                    }
42                }
43                Some(in_byte) => match in_byte {
44                    Ok(in_byte) => {
45                        let in_byte = in_byte as char;
46                        match in_byte {
47                            '0' => {}
48                            '1' => {
49                                value |= 1 << i;
50                            }
51                            _ => {
52                                if in_byte.is_ascii_whitespace() {
53                                    continue;
54                                } else {
55                                    return Some(Err(InError::InvalidByte(in_byte)));
56                                }
57                            }
58                        }
59                    }
60                    Err(e) => {
61                        return Some(Err(InError::StdIO(e)));
62                    }
63                },
64            }
65            i -= 1;
66        }
67        Some(Ok(value))
68    }
69}
70
71/// Writes bytes to the output stream in the binary format
72///
73/// Produced characters are '0' and '1'.
74pub struct Writer<W: Write> {
75    out_bytes: W,
76}
77
78impl<W: Write> Writer<W> {
79    pub fn new(out_bytes: W) -> Self {
80        Writer { out_bytes }
81    }
82}
83
84impl<W: Write> ByteWriter for Writer<W> {
85    fn write(&mut self, byte: u8) -> Result<(), OutError> {
86        let mut bit_string = [_0; 8];
87        for i in (0..8).rev() {
88            if (byte & (1 << i)) != 0 {
89                bit_string[7 - i] = _1;
90            }
91        }
92        util::write(&mut self.out_bytes, bit_string.as_slice(), 8)
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    #[test]
101    fn read() {
102        let input = [
103            _0, _1, _0, _0, _1, _0, _1, _0, _0, _1, _0, _1, _1, _1, _1, _1,
104        ];
105        let mut reader = Reader::new(input.as_slice());
106        assert_eq!(0b01001010u8, reader.next().unwrap().unwrap());
107        assert_eq!(0b01011111u8, reader.next().unwrap().unwrap());
108        assert!(reader.next().is_none());
109    }
110
111    #[test]
112    fn write() {
113        let input = 0b10110100u8;
114        let expected = [_1, _0, _1, _1, _0, _1, _0, _0];
115        let mut output = [0u8; 8];
116        let mut writer = Writer::new(output.as_mut_slice());
117        writer.write(input).unwrap();
118        assert_eq!(expected, output);
119    }
120}
121
122#[cfg(all(test, feature = "benchmark"))]
123mod benchs {
124    extern crate test;
125    use super::*;
126
127    #[bench]
128    fn read(b: &mut test::Bencher) {
129        const N: usize = 1024 * 1024;
130        static INPUT: [u8; N] = [_1; N];
131        b.iter(|| {
132            let reader = Reader::new(INPUT.as_slice());
133            let _ = reader.collect::<Vec<Result<u8, InError>>>();
134        });
135    }
136
137    #[bench]
138    fn write(b: &mut test::Bencher) {
139        const N: usize = 1024 * 1024;
140        static mut OUTPUT: [u8; N] = [_0; N];
141        b.iter(|| unsafe {
142            let mut writer = Writer::new(OUTPUT.as_mut_slice());
143            for _ in 0..N / 8 {
144                writer.write(255u8).unwrap();
145            }
146        });
147    }
148}