use crate::base::read::io::poll_result_ok;
use std::pin::Pin;
use std::task::{ready, Context, Poll};
use crc32fast::Hasher;
use futures_lite::io::AsyncRead;
use pin_project::pin_project;
#[pin_project]
pub(crate) struct HashedReader<R> {
#[pin]
pub(crate) reader: R,
pub(crate) hasher: Hasher,
}
impl<R> HashedReader<R>
where
R: AsyncRead + Unpin,
{
pub(crate) fn new(reader: R) -> Self {
Self { reader, hasher: Hasher::default() }
}
pub(crate) fn swap_and_compute_hash(&mut self) -> u32 {
std::mem::take(&mut self.hasher).finalize()
}
pub(crate) fn into_inner(self) -> R {
self.reader
}
}
impl<R> AsyncRead for HashedReader<R>
where
R: AsyncRead + Unpin,
{
fn poll_read(self: Pin<&mut Self>, c: &mut Context<'_>, b: &mut [u8]) -> Poll<std::io::Result<usize>> {
let project = self.project();
let written = poll_result_ok!(ready!(project.reader.poll_read(c, b)));
project.hasher.update(&b[..written]);
Poll::Ready(Ok(written))
}
}