1use core::iter::FusedIterator;
6use core::str;
7#[cfg(feature = "std")]
8use std::io;
9
10#[cfg(all(feature = "core2", not(feature = "std")))]
11use core2::io;
12
13use crate::parse::HexToBytesError;
14
15pub struct HexToBytesIter<'a> {
17 iter: str::Bytes<'a>,
25}
26
27impl<'a> HexToBytesIter<'a> {
28 pub fn new(s: &'a str) -> Result<HexToBytesIter<'a>, HexToBytesError> {
34 if s.len() % 2 != 0 {
35 Err(HexToBytesError::OddLengthString(s.len()))
36 } else {
37 Ok(HexToBytesIter { iter: s.bytes() })
38 }
39 }
40}
41
42impl<'a> Iterator for HexToBytesIter<'a> {
43 type Item = Result<u8, HexToBytesError>;
44
45 fn next(&mut self) -> Option<Result<u8, HexToBytesError>> {
46 let hi = self.iter.next()?;
47 let lo = self.iter.next().expect("iter length invariant violated, this is a bug");
48 Some(hex_chars_to_byte(hi, lo))
49 }
50
51 fn size_hint(&self) -> (usize, Option<usize>) {
52 let (min, max) = self.iter.size_hint();
53 (min / 2, max.map(|x| x / 2))
54 }
55}
56
57impl<'a> DoubleEndedIterator for HexToBytesIter<'a> {
58 fn next_back(&mut self) -> Option<Result<u8, HexToBytesError>> {
59 let lo = self.iter.next_back()?;
60 let hi = self.iter.next_back().expect("iter length invariant violated, this is a bug");
61 Some(hex_chars_to_byte(hi, lo))
62 }
63}
64
65impl<'a> ExactSizeIterator for HexToBytesIter<'a> {
66 fn len(&self) -> usize { self.iter.len() / 2 }
67}
68
69impl<'a> FusedIterator for HexToBytesIter<'a> {}
70
71#[cfg(any(feature = "std", feature = "core2"))]
72impl<'a> io::Read for HexToBytesIter<'a> {
73 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
74 let mut bytes_read = 0usize;
75 for dst in buf {
76 match self.next() {
77 Some(Ok(src)) => {
78 *dst = src;
79 bytes_read += 1;
80 }
81 _ => break,
82 }
83 }
84 Ok(bytes_read)
85 }
86}
87
88fn hex_chars_to_byte(hi: u8, lo: u8) -> Result<u8, HexToBytesError> {
90 let hih = (hi as char).to_digit(16).ok_or(HexToBytesError::InvalidChar(hi))?;
91 let loh = (lo as char).to_digit(16).ok_or(HexToBytesError::InvalidChar(lo))?;
92
93 let ret = (hih << 4) + loh;
94 Ok(ret as u8)
95}
96
97pub struct BytesToHexIter<I: Iterator<Item = u8>> {
99 iter: I,
101 low: Option<char>,
103}
104
105impl<I> BytesToHexIter<I>
106where
107 I: Iterator<Item = u8>,
108{
109 pub fn new(iter: I) -> BytesToHexIter<I> { Self { iter, low: None } }
111}
112
113impl<I> Iterator for BytesToHexIter<I>
114where
115 I: Iterator<Item = u8>,
116{
117 type Item = char;
118
119 fn next(&mut self) -> Option<char> {
120 match self.low {
121 Some(c) => {
122 self.low = None;
123 Some(c)
124 }
125 None => self.iter.next().map(|b| {
126 let (high, low) = byte_to_hex_chars(b);
127 self.low = Some(low);
128 high
129 }),
130 }
131 }
132
133 fn size_hint(&self) -> (usize, Option<usize>) {
134 let (min, max) = self.iter.size_hint();
135 match self.low {
136 Some(_) => (min * 2 + 1, max.map(|max| max * 2 + 1)),
137 None => (min * 2, max.map(|max| max * 2)),
138 }
139 }
140}
141
142impl<I> DoubleEndedIterator for BytesToHexIter<I>
143where
144 I: DoubleEndedIterator + Iterator<Item = u8>,
145{
146 fn next_back(&mut self) -> Option<char> {
147 match self.low {
148 Some(c) => {
149 self.low = None;
150 Some(c)
151 }
152 None => self.iter.next_back().map(|b| {
153 let (high, low) = byte_to_hex_chars(b);
154 self.low = Some(low);
155 high
156 }),
157 }
158 }
159}
160
161impl<I> ExactSizeIterator for BytesToHexIter<I>
162where
163 I: ExactSizeIterator + Iterator<Item = u8>,
164{
165 fn len(&self) -> usize { self.iter.len() * 2 }
166}
167
168impl<I> FusedIterator for BytesToHexIter<I> where I: FusedIterator + Iterator<Item = u8> {}
169
170fn byte_to_hex_chars(b: u8) -> (char, char) {
172 const HEX_TABLE: [u8; 16] = *b"0123456789abcdef";
173
174 let high = HEX_TABLE[usize::from(b >> 4)];
175 let low = HEX_TABLE[usize::from(b & 0b00001111)];
176
177 (char::from(high), char::from(low))
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn encode_byte() {
186 let tcs =
187 vec![(0x00, ('0', '0')), (0x0a, ('0', 'a')), (0xad, ('a', 'd')), (0xff, ('f', 'f'))];
188 for (b, (high, low)) in tcs {
189 assert_eq!(byte_to_hex_chars(b), (high, low));
190 }
191 assert_eq!(byte_to_hex_chars(0x00), ('0', '0'));
192 assert_eq!(byte_to_hex_chars(0x0a), ('0', 'a'));
193 assert_eq!(byte_to_hex_chars(0xad), ('a', 'd'));
194 assert_eq!(byte_to_hex_chars(0xff), ('f', 'f'));
195 }
196
197 #[test]
198 fn decode_iter_forward() {
199 let hex = "deadbeef";
200 let v = vec![0xde, 0xad, 0xbe, 0xef];
201
202 for (i, b) in HexToBytesIter::new(hex).unwrap().enumerate() {
203 assert_eq!(b.unwrap(), v[i]);
204 }
205 }
206
207 #[test]
208 fn decode_iter_backward() {
209 let hex = "deadbeef";
210 let v = vec![0xef, 0xbe, 0xad, 0xde];
211
212 for (i, b) in HexToBytesIter::new(hex).unwrap().rev().enumerate() {
213 assert_eq!(b.unwrap(), v[i]);
214 }
215 }
216
217 #[test]
218 fn encode_iter() {
219 let v = vec![0xde, 0xad, 0xbe, 0xef];
220 let hex = "deadbeef";
221
222 for (i, c) in BytesToHexIter::new(v.iter().cloned()).enumerate() {
223 assert_eq!(c, hex.chars().nth(i).unwrap());
224 }
225 }
226
227 #[test]
228 fn encode_iter_backwards() {
229 let v = vec![0xde, 0xad, 0xbe, 0xef];
230 let hex = "efbeadde";
231
232 for (i, c) in BytesToHexIter::new(v.iter().cloned()).rev().enumerate() {
233 assert_eq!(c, hex.chars().nth(i).unwrap());
234 }
235 }
236
237 #[test]
238 fn roundtrip_forward() {
239 let hex = "deadbeefcafebabe";
240 let bytes_iter = HexToBytesIter::new(hex).unwrap().map(|res| res.unwrap());
241 let got = BytesToHexIter::new(bytes_iter).collect::<String>();
242 assert_eq!(got, hex);
243 }
244
245 #[test]
246 fn roundtrip_backward() {
247 let hex = "deadbeefcafebabe";
248 let bytes_iter = HexToBytesIter::new(hex).unwrap().rev().map(|res| res.unwrap());
249 let got = BytesToHexIter::new(bytes_iter).rev().collect::<String>();
250 assert_eq!(got, hex);
251 }
252}