use core::marker::PhantomData;
use crate::error::{Incomplete, TrailingBytes};
pub trait Decode<'a>: Sized {
type Error: From<Incomplete> + From<TrailingBytes>;
fn decode(buf: &'a [u8]) -> Result<(Self, &'a [u8]), Self::Error>;
fn decode_exact(buf: &'a [u8]) -> Result<Self, Self::Error> {
let (value, rest) = Self::decode(buf)?;
if rest.is_empty() {
Ok(value)
} else {
Err(TrailingBytes(rest.len()).into())
}
}
}
pub trait DecodeIter<'a>: Sized {
type Error: From<Incomplete>;
fn decode_next(buf: &'a [u8]) -> Result<Option<(Self, &'a [u8])>, Self::Error>;
#[must_use]
fn iter(buf: &'a [u8]) -> DecodeIterator<'a, Self> {
DecodeIterator::new(buf)
}
}
pub struct DecodeIterator<'a, T> {
buf: &'a [u8],
done: bool,
_marker: PhantomData<fn() -> T>,
}
impl<'a, T> DecodeIterator<'a, T> {
fn new(buf: &'a [u8]) -> Self {
Self {
buf,
done: false,
_marker: PhantomData,
}
}
}
impl<'a, T: DecodeIter<'a>> Iterator for DecodeIterator<'a, T> {
type Item = Result<T, T::Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
}
match T::decode_next(self.buf) {
Ok(Some((value, rest))) => {
self.buf = rest;
Some(Ok(value))
}
Ok(None) => {
self.done = true;
None
}
Err(e) => {
self.done = true;
Some(Err(e))
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::{Incomplete, TrailingBytes};
use crate::read::read_u8;
#[derive(Debug, PartialEq)]
enum TestErr {
Incomplete(Incomplete),
Trailing(TrailingBytes),
}
impl From<Incomplete> for TestErr {
fn from(e: Incomplete) -> Self {
TestErr::Incomplete(e)
}
}
impl From<TrailingBytes> for TestErr {
fn from(e: TrailingBytes) -> Self {
TestErr::Trailing(e)
}
}
#[derive(Debug, PartialEq)]
struct One(u8);
impl<'a> Decode<'a> for One {
type Error = TestErr;
fn decode(buf: &'a [u8]) -> Result<(Self, &'a [u8]), TestErr> {
let (b, rest) = read_u8(buf)?;
Ok((One(b), rest))
}
}
#[test]
fn decode_exact_consumes_whole_buffer() {
assert_eq!(One::decode_exact(&[7]).unwrap(), One(7));
}
#[test]
fn decode_exact_reports_trailing_bytes() {
let err = One::decode_exact(&[1, 2]).unwrap_err();
assert_eq!(err, TestErr::Trailing(TrailingBytes(1)));
}
#[derive(Debug, PartialEq)]
struct Elem(u8);
impl<'a> DecodeIter<'a> for Elem {
type Error = TestErr;
fn decode_next(buf: &'a [u8]) -> Result<Option<(Self, &'a [u8])>, TestErr> {
match buf.first() {
None => Ok(None),
Some(&0xFF) => Err(Incomplete {
needed: 2,
available: 1,
}
.into()),
Some(&b) => Ok(Some((Elem(b), &buf[1..]))),
}
}
}
#[test]
fn iter_yields_all_then_none() {
let mut it = Elem::iter(&[1, 2, 3]);
assert!(matches!(it.next(), Some(Ok(Elem(1)))));
assert!(matches!(it.next(), Some(Ok(Elem(2)))));
assert!(matches!(it.next(), Some(Ok(Elem(3)))));
assert!(it.next().is_none());
}
#[test]
fn iter_stops_after_first_error() {
let mut it = Elem::iter(&[1, 0xFF, 3]);
assert!(matches!(it.next(), Some(Ok(Elem(1)))));
assert!(matches!(it.next(), Some(Err(TestErr::Incomplete(_)))));
assert!(it.next().is_none());
}
}