Last active
October 1, 2020 04:29
-
-
Save Lucretiel/1fe436b0f498acca6d84789c2e30cc44 to your computer and use it in GitHub Desktop.
A wrapper async reader that hashes the content that's read through it
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
hash::Hasher, | |
io, | |
pin::Pin, | |
task::{Context, Poll}, | |
}; | |
use futures::AsyncRead; | |
use pin_project::pin_project; | |
#[pin_project] | |
#[derive(Debug, Clone)] | |
pub struct AsyncReadHash<H, R> { | |
#[pin] | |
reader: R, | |
hasher: H, | |
} | |
impl<H: Hasher, R: AsyncRead> AsyncReadHash<H, R> { | |
pub fn with_hasher(reader: R, hasher: H) -> Self { | |
Self { reader, hasher } | |
} | |
} | |
impl<H: Hasher, R> AsyncReadHash<H, R> { | |
pub fn current_hash(&self) -> u64 { | |
self.hasher.finish() | |
} | |
} | |
impl<H: Hasher + Default, R: AsyncRead> AsyncReadHash<H, R> { | |
pub fn new(reader: R) -> Self { | |
Self::with_hasher(reader, H::default()) | |
} | |
} | |
impl<H: Hasher, R: AsyncRead> AsyncRead for AsyncReadHash<H, R> { | |
fn poll_read( | |
self: Pin<&mut Self>, | |
cx: &mut Context, | |
buf: &mut [u8], | |
) -> Poll<io::Result<usize>> { | |
let this = self.project(); | |
// Note: instead of using pin_project, we could do it manually, like | |
// so: | |
// | |
// let reader = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().reader) }; | |
// let hasher = unsafe { &mut self.get_unchecked_mut().hasher }; | |
match this.reader.poll_read(cx, buf) { | |
Poll::Ready(Ok(amount_read)) => { | |
this.hasher.write(&buf[..amount_read]); | |
Poll::Ready(Ok(amount_read)) | |
} | |
result => result, | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment