pub trait Source<Unit>: Sized {
fn read(&mut self, unit: &mut Unit) -> bool;
fn is_exhausted(&self) -> bool;
}
#[derive(Debug, Clone)]
pub struct SliceSource<'a, Unit> {
data: &'a [Unit],
pos: usize,
}
impl<'a, Unit: Copy> SliceSource<'a, Unit> {
pub fn new(data: &'a [Unit]) -> Self {
Self { data, pos: 0 }
}
pub fn position(&self) -> usize {
self.pos
}
pub fn remaining(&self) -> usize {
self.data.len().saturating_sub(self.pos)
}
}
impl<'a, Unit: Copy> Source<Unit> for SliceSource<'a, Unit> {
#[inline]
fn read(&mut self, unit: &mut Unit) -> bool {
if self.pos < self.data.len() {
*unit = self.data[self.pos];
self.pos += 1;
true
} else {
false
}
}
#[inline]
fn is_exhausted(&self) -> bool {
self.pos >= self.data.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_slice_source_basic() {
let data = [1u8, 2, 3, 4];
let mut source = SliceSource::new(&data);
let mut unit = 0u8;
assert!(source.read(&mut unit));
assert_eq!(unit, 1);
assert!(source.read(&mut unit));
assert_eq!(unit, 2);
assert!(source.read(&mut unit));
assert_eq!(unit, 3);
assert!(source.read(&mut unit));
assert_eq!(unit, 4);
assert!(!source.read(&mut unit));
assert!(source.is_exhausted());
}
#[test]
fn test_empty_source() {
let data: [u8; 0] = [];
let mut source = SliceSource::new(&data);
let mut unit = 0u8;
assert!(!source.read(&mut unit));
assert!(source.is_exhausted());
}
}