#[derive(Debug)]
pub(crate) struct Reader<C> {
rest: usize,
data: C,
}
impl<C> Reader<C> {
pub fn fill(self) -> Reader<Skippable<C>> {
Reader {
rest: self.rest,
data: Skippable::Fill(self.data),
}
}
pub fn read_from(&mut self, input: &mut &[u8]) -> Option<&mut C>
where
C: Consume,
{
let n = usize::min(self.rest, input.len());
let (left, right) = input.split_at(n);
*input = right;
self.data.consume(self.rest, left);
self.rest -= n;
if self.rest == 0 {
Some(&mut self.data)
} else {
None
}
}
}
impl<C> Reader<Skippable<C>> {
pub fn skip(rest: usize) -> Self {
let data = Skippable::Skip;
Self { rest, data }
}
}
impl Reader<Box<[u8]>> {
pub fn alloc(rest: usize) -> Self {
let data = Box::from(vec![0; rest]);
Self { rest, data }
}
}
impl<C> Default for Reader<C>
where
C: Default + AsMut<[u8]>,
{
#[inline]
fn default() -> Self {
let mut data = C::default();
let rest = data.as_mut().len();
Self { rest, data }
}
}
pub(crate) trait Consume {
fn consume(&mut self, rest: usize, input: &[u8]);
}
impl<C> Consume for C
where
C: AsMut<[u8]>,
{
fn consume(&mut self, rest: usize, input: &[u8]) {
let inner = self.as_mut();
let step = inner.len() - rest;
inner[step..step + input.len()].copy_from_slice(input);
}
}
#[derive(Debug, PartialEq, Eq)]
pub(crate) enum Skippable<C> {
Fill(C),
Skip,
}
impl<C> Consume for Skippable<C>
where
C: Consume,
{
fn consume(&mut self, rest: usize, input: &[u8]) {
match self {
Self::Fill(c) => c.consume(rest, input),
Self::Skip => {}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn read() {
let mut b: Reader<[u8; 4]> = Reader::default();
assert_eq!(b.rest, 4);
let mut input = [0, 1].as_slice();
assert!(b.read_from(&mut input).is_none());
assert_eq!(b.rest, 2);
assert!(input.is_empty());
let mut input = [2, 3].as_slice();
assert_eq!(b.read_from(&mut input), Some(&mut [0, 1, 2, 3]));
assert_eq!(b.rest, 0);
assert!(input.is_empty());
let mut input = [4, 5].as_slice();
assert_eq!(b.read_from(&mut input), Some(&mut [0, 1, 2, 3]));
assert_eq!(b.rest, 0);
assert_eq!(input, [4, 5]);
}
#[test]
fn read_more_input() {
let mut b: Reader<[u8; 4]> = Reader::default();
assert_eq!(b.rest, 4);
let mut input = [0, 1, 2, 3, 4, 5].as_slice();
assert_eq!(b.read_from(&mut input), Some(&mut [0, 1, 2, 3]));
assert_eq!(b.rest, 0);
assert_eq!(input, [4, 5]);
}
#[test]
fn read_skip() {
let mut b: Reader<Skippable<[u8; 0]>> = Reader::skip(4);
assert_eq!(b.rest, 4);
let mut input = [0, 1].as_slice();
assert!(b.read_from(&mut input).is_none());
assert_eq!(b.rest, 2);
assert!(input.is_empty());
let mut input = [2, 3].as_slice();
assert_eq!(b.read_from(&mut input), Some(&mut Skippable::Skip));
assert_eq!(b.rest, 0);
assert!(input.is_empty());
}
}