added stream byte counter

master
Avril 4 years ago
parent 5ac12414eb
commit e7fff61c95
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -1,4 +1,7 @@
use super::*; use super::*;
use std::{
io::{self, Read, Write},
};
pub trait Tuple2Ext<T,U>: Sized pub trait Tuple2Ext<T,U>: Sized
{ {
@ -11,3 +14,98 @@ impl<T, U> Tuple2Ext<T,U> for (T, U)
(self.1, self.0) (self.1, self.0)
} }
} }
/// A counter for num of bytes read/written from a `Read`/`Write` stream.
#[derive(Debug)]
pub struct IOCounter<T: ?Sized>(usize, T);
impl<R: ?Sized + io::Read> io::Read for IOCounter<R>
{
#[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let w = self.1.read(buf)?;
self.0+=w;
Ok(w)
}
}
impl<W: ?Sized + io::Write> io::Write for IOCounter<W>
{
#[inline] fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let w= self.1.write(buf)?;
self.0+=w;
Ok(w)
}
#[inline(always)] fn flush(&mut self) -> io::Result<()> {
self.1.flush()
}
}
impl<T: ?Sized> IOCounter<T>
{
/// The current counted bytes i/o'd
#[inline] pub fn count(&self) -> usize
{
self.0
}
/// Reference to the inner stream
#[inline] pub fn inner(&self) -> &T
{
&self.1
}
/// Mutable reference to the inner stream
#[inline] pub fn inner_mut(&mut self) -> &mut T
{
&mut self.1
}
/// Mutable reference to the count.
/// Use this to set the count.
#[inline(always)] pub fn count_mut(&mut self) -> &mut usize
{
&mut self.0
}
/// Reset count to 0.
#[inline] pub fn reset(&mut self)
{
*self.count_mut() = 0;
}
}
impl<T> IOCounter<T>
{
/// Create a new i/o counting wrapper.
#[inline(always)] pub fn new(val: T) -> Self
{
Self(0, val)
}
/// Consume into inner stream
#[inline(always)] pub fn into_inner(self) -> T
{
self.1
}
}
pub trait IOCounterReadExt
{
/// Wrap an `IOCounter` over this `Read` stream.
fn with_counter(self) -> IOCounter<Self>;
}
pub trait IOCounterWriteExt
{
/// Wrap an `IOCounter` over this `Write` stream.
fn with_counter(self) -> IOCounter<Self>;
}
impl<W: io::Write> IOCounterWriteExt for W
{
#[inline] fn with_counter(self) -> IOCounter<Self> {
IOCounter::new(self)
}
}
impl<R: io::Read> IOCounterReadExt for R
{
#[inline] fn with_counter(self) -> IOCounter<Self> {
IOCounter::new(self)
}
}

@ -25,7 +25,7 @@ pub struct FormatDirective
pub trait Format pub trait Format
{ {
fn encode<W: io::Write>(cfg: &Config, to: W, obj: &Object) -> Result<usize, Error>; fn encode<W: io::Write>(cfg: &Config, to: W, obj: &Object) -> Result<usize, Error>;
fn decode<R: io::Read>(cfg: &Config, from: R) -> Result<Object, Error>; //TODO: An `io::Read` wrapper that counter num of bytes read internally. That way we can extract `(Object, usize)` from just `Object` here. fn decode<R: io::Read>(cfg: &Config, from: R) -> Result<Object, Error>;
} }
macro_rules! directive { macro_rules! directive {
@ -36,13 +36,12 @@ macro_rules! directive {
}) })
}; };
(for $fmt:path => $($name:literal),+) => { (for $fmt:path => $($name:literal),+) => {
//TODO: $fmt will be a struct implementing `Format`.
// Will perform input conversions to trait methods.
// Will perform input/output conversions for `Format::decode` to extract `(Object, usize)` from `Object` function output and a `io::Read` input wrapper that counts bytes read from the stream.
directive!($($name),+ => |c, w, o| { directive!($($name),+ => |c, w, o| {
<$fmt as Format>::encode(c, w, o) <$fmt as Format>::encode(c, w, o)
}, |c, r| { }, |c, r| {
todo!("We need a io::Read stream wrapper that counts the bytes read `r` to satisfy the return value requirements of this function pointer") let mut r = r.with_counter();
let obj = <$fmt as Format>::decode(c, &mut r)?;
Ok((obj, r.count()))
}) })
} }
} }

Loading…
Cancel
Save