use std::io;
pub trait Counter {
fn count(&self) -> usize;
}
pub struct ReadCounter<'a, T: 'a + io::Read> {
reader: &'a mut T,
count: usize,
}
impl<'a, T: 'a + io::Read> From<&'a mut T> for ReadCounter<'a, T> {
fn from(value: &'a mut T) -> ReadCounter<'a, T> {
ReadCounter {
reader: value,
count: 0,
}
}
}
impl<'a, T: 'a + io::Read> Counter for ReadCounter<'a, T> {
fn count(&self) -> usize {
self.count
}
}
impl<'a, T: 'a + io::Read> io::Read for ReadCounter<'a, T> {
fn read(&mut self, buffer: &mut [u8]) -> Result<usize, io::Error> {
let size = self.reader.read(buffer)?;
self.count += size;
Ok(size)
}
}
pub struct WriteCounter<'a, T: 'a + io::Write> {
writer: &'a mut T,
count: usize,
}
impl<'a, T: 'a + io::Write> From<&'a mut T> for WriteCounter<'a, T> {
fn from(value: &'a mut T) -> WriteCounter<'a, T> {
WriteCounter {
writer: value,
count: 0,
}
}
}
impl<'a, T: 'a + io::Write> Counter for WriteCounter<'a, T> {
fn count(&self) -> usize {
self.count
}
}
impl<'a, T: 'a + io::Write> io::Write for WriteCounter<'a, T> {
fn write(&mut self, buffer: &[u8]) -> Result<usize, io::Error> {
let size = self.writer.write(buffer)?;
self.count += size;
Ok(size)
}
fn flush(&mut self) -> Result<(), io::Error> {
self.writer.flush()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::{Read, Write};
const DATA: &'static [u8] = &[1u8, 2u8, 3u8];
#[test]
fn read() {
let mut d = DATA;
let mut r = ReadCounter::from(&mut d);
for (i, v) in DATA.iter().enumerate() {
let mut b = [0u8];
assert_eq!(r.read(&mut b).unwrap(), 1);
assert_eq!(r.count(), i + 1);
assert_eq!(b[0], *v);
}
}
#[test]
fn write() {
let mut b: Vec<u8> = Vec::new();
{
let mut w = WriteCounter::from(&mut b);
for (i, v) in DATA.iter().enumerate() {
assert_eq!(w.write(&[*v]).unwrap(), 1);
assert_eq!(w.count(), i + 1);
}
}
assert_eq!(&b[..], DATA);
}
}