use fallible_iterator::FallibleIterator;
use super::{FromHexError, FromHexErrorKind};
pub struct HexDecodeIterator<I> {
iterator: I,
}
pub struct HexDecodeAsciiIterator<I> {
iterator: I,
last_position: usize,
}
impl<I: FallibleIterator<Item = (usize, char), Error = FromHexError>> HexDecodeIterator<I> {
pub fn new(iterator: I) -> Self {
Self { iterator }
}
}
impl<I: FallibleIterator<Item = (usize, u8), Error = FromHexError>> HexDecodeAsciiIterator<I> {
pub fn new(iterator: I) -> Self {
Self {
iterator,
last_position: 0,
}
}
pub(crate) fn last_position(&self) -> usize {
self.last_position
}
}
impl<I> fallible_iterator::FallibleIterator for HexDecodeIterator<I>
where
I: FallibleIterator<Item = (usize, char), Error = FromHexError>,
{
type Item = u8;
type Error = FromHexError;
fn next(&mut self) -> Result<Option<u8>, FromHexError> {
let (position, c) = match self.iterator.next() {
Ok(Some(tup)) => tup,
Ok(None) => return Ok(None),
Err(e) => return Err(e),
};
let Some(v1) = c.to_digit(16) else {
return Err(FromHexError {
position,
kind: FromHexErrorKind::UnexpectedCharacter(c),
});
};
let (position, c) = match self.iterator.next() {
Ok(Some(tup)) => tup,
Ok(None) => {
return Err(FromHexError {
position,
kind: FromHexErrorKind::Eof,
})
}
Err(e) => return Err(e),
};
let Some(v2) = c.to_digit(16) else {
return Err(FromHexError {
position,
kind: FromHexErrorKind::UnexpectedCharacter(c),
});
};
Ok(Some((v1 * 16 + v2) as u8))
}
}
impl<I> fallible_iterator::FallibleIterator for HexDecodeAsciiIterator<I>
where
I: FallibleIterator<Item = (usize, u8), Error = FromHexError>,
{
type Item = u8;
type Error = FromHexError;
fn next(&mut self) -> Result<Option<u8>, FromHexError> {
let (position, c) = match self.iterator.next() {
Ok(Some(tup)) => tup,
Ok(None) => return Ok(None),
Err(e) => return Err(e),
};
let Some(v1) = (c as char).to_digit(16) else {
return Err(FromHexError {
position,
kind: FromHexErrorKind::UnexpectedByte(c),
});
};
let (position, c) = match self.iterator.next() {
Ok(Some(tup)) => tup,
Ok(None) => {
return Err(FromHexError {
position,
kind: FromHexErrorKind::Eof,
})
}
Err(e) => return Err(e),
};
let Some(v2) = (c as char).to_digit(16) else {
return Err(FromHexError {
position,
kind: FromHexErrorKind::UnexpectedByte(c),
});
};
self.last_position = position;
Ok(Some((v1 * 16 + v2) as u8))
}
}