1use crate::byte_writer::ByteWriter;
2use crate::error::{InError, OutError};
3use crate::util;
4use std::io::{Bytes, Read, Write};
5
6pub struct Reader<R: Read> {
12 in_bytes: Bytes<R>,
13}
14
15impl<R: Read> Reader<R> {
16 pub fn new(read: R) -> Self {
17 Reader {
18 in_bytes: read.bytes(),
19 }
20 }
21 fn valid(n: char) -> Option<u8> {
22 if ('0'..='9').contains(&n) {
23 Some(n as u8 - b'0')
24 } else if ('a'..='f').contains(&n) {
25 Some(10u8 + (n as u8 - b'a'))
26 } else if ('A'..='F').contains(&n) {
27 Some(10u8 + (n as u8 - b'A'))
28 } else {
29 None
30 }
31 }
32 fn next_non_whitespace(&mut self) -> Option<<Bytes<R> as Iterator>::Item> {
33 loop {
34 let c = self.in_bytes.next()?;
35 match c {
36 Ok(c) => {
37 if c.is_ascii_whitespace() {
38 continue;
39 } else {
40 return Some(Ok(c));
41 }
42 }
43 Err(e) => {
44 return Some(Err(e));
45 }
46 }
47 }
48 }
49}
50
51impl<R: Read> Iterator for Reader<R> {
52 type Item = Result<u8, InError>;
53 fn next(&mut self) -> Option<Self::Item> {
54 let msn = self.next_non_whitespace()?;
55 match msn {
56 Ok(msn) => {
57 if let Some(msn) = Self::valid(msn as char) {
58 if let Some(lsn) = self.next_non_whitespace() {
59 match lsn {
60 Ok(lsn) => {
61 if let Some(lsn) = Self::valid(lsn as char) {
62 Some(Ok((msn << 4) | lsn))
63 } else {
64 Some(Err(InError::InvalidByte(lsn as char)))
65 }
66 }
67 Err(e) => Some(Err(InError::StdIO(e))),
68 }
69 } else {
70 Some(Err(InError::ShortIO {
71 bytes: 1usize,
72 expected: 2,
73 }))
74 }
75 } else {
76 Some(Err(InError::InvalidByte(msn as char)))
77 }
78 }
79 Err(e) => Some(Err(InError::StdIO(e))),
80 }
81 }
82}
83
84pub struct Writer<W: Write> {
88 out_bytes: W,
89}
90
91impl<W: Write> Writer<W> {
92 pub fn new(out_bytes: W) -> Self {
93 Writer { out_bytes }
94 }
95}
96
97impl<W: Write> ByteWriter for Writer<W> {
98 fn write(&mut self, byte: u8) -> Result<(), OutError> {
99 let msn = char::from_digit(((byte & 0xf0) >> 4) as u32, 16).unwrap() as u8;
100 let lsn = char::from_digit((byte & 0x0f) as u32, 16).unwrap() as u8;
101 util::write(&mut self.out_bytes, &[msn, lsn], 2)
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use crate::util::literals::*;
109
110 #[test]
111 fn read() {
112 let input = [_A, _4, _1, _B.to_ascii_uppercase()];
113 let mut reader = Reader::new(input.as_slice());
114 assert_eq!(0xa4u8, reader.next().unwrap().unwrap());
115 assert_eq!(0x1bu8, reader.next().unwrap().unwrap());
116 assert!(reader.next().is_none());
117 }
118
119 #[test]
120 fn write() {
121 let input = 0xf4;
122 let expected = [_F, _4];
123 let mut output = [0u8; 2];
124 let mut writer = Writer::new(output.as_mut_slice());
125 writer.write(input).unwrap();
126 assert_eq!(expected, output);
127 }
128}
129
130#[cfg(all(test, feature = "benchmark"))]
131mod benchs {
132 extern crate test;
133 use super::*;
134 use crate::util::literals::*;
135
136 #[bench]
137 fn read(b: &mut test::Bencher) {
138 const N: usize = 1024 * 1024;
139 static INPUT: [u8; N] = [_F; N];
140 b.iter(|| {
141 let reader = Reader::new(INPUT.as_slice());
142 let _ = reader.collect::<Vec<Result<u8, InError>>>();
143 });
144 }
145
146 #[bench]
147 fn write(b: &mut test::Bencher) {
148 const N: usize = 1024 * 1024;
149 static mut OUTPUT: [u8; N] = [_0; N];
150 b.iter(|| unsafe {
151 let mut writer = Writer::new(OUTPUT.as_mut_slice());
152 for _ in 0..N / 2 {
153 writer.write(255u8).unwrap();
154 }
155 });
156 }
157}