#![doc = include_str!("../README.md")]
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use std::io::{Read, Write};
pub trait Check {
type Output;
fn update(&mut self, buf: &[u8]);
fn output(&self) -> Self::Output;
}
impl<H: Hasher> Check for H {
type Output = u64;
fn update(&mut self, buf: &[u8]) {
self.write(buf)
}
fn output(&self) -> Self::Output {
self.finish()
}
}
pub struct Checker<C: Check, T> {
checker: C,
inner: T,
}
impl<C: Check, T> Checker<C, T> {
pub fn new(checker: C, inner: T) -> Self {
Self { checker, inner }
}
pub fn replace_checker(&mut self, new: C) -> C {
std::mem::replace(&mut self.checker, new)
}
pub fn replace_inner(&mut self, inner: T) -> T {
std::mem::replace(&mut self.inner, inner)
}
pub fn rebuild_with_checker<C2: Check>(self, hasher: C2) -> (Checker<C2, T>, C) {
let (h1, r) = self.into_parts();
(Checker::new(hasher, r), h1)
}
pub fn rebuild_with_inner<T2>(self, inner: T2) -> (Checker<C, T2>, T) {
let (h, inner1) = self.into_parts();
(Checker::new(h, inner), inner1)
}
pub fn into_parts(self) -> (C, T) {
(self.checker, self.inner)
}
pub fn output(&self) -> C::Output {
self.checker.output()
}
}
impl<T> Checker<DefaultHasher, T> {
pub fn new_default_hasher(inner: T) -> Self {
Self {
checker: DefaultHasher::default(),
inner,
}
}
pub fn reset_hasher(&mut self) -> DefaultHasher {
std::mem::take(&mut self.checker)
}
}
impl<C: Default + Check, T> Checker<C, T> {
pub fn new_default(inner: T) -> Self {
Self {
checker: Default::default(),
inner,
}
}
}
impl<C: Check, R: Read> Read for Checker<C, R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let out = self.inner.read(buf)?;
self.checker.update(&buf[..out]);
Ok(out)
}
}
impl<C: Check, W: Write> Write for Checker<C, W> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let out = self.inner.write(buf)?;
self.checker.update(&buf[..out]);
Ok(out)
}
fn flush(&mut self) -> std::io::Result<()> {
self.inner.flush()
}
}
#[derive(Debug, Default)]
pub struct InnerCounter(usize);
impl Check for InnerCounter {
type Output = usize;
fn update(&mut self, buf: &[u8]) {
self.0 += buf.len();
}
fn output(&self) -> Self::Output {
self.0
}
}
pub type Counter<T> = Checker<InnerCounter, T>;