2019-06-04 05:15:12 -07:00
|
|
|
use blake2b_simd::State;
|
2018-08-01 17:28:13 -07:00
|
|
|
use std::io::{self, Read};
|
|
|
|
|
|
|
|
/// Abstraction over a reader which hashes the data being read.
|
|
|
|
pub struct HashReader<R: Read> {
|
|
|
|
reader: R,
|
2019-06-04 05:15:12 -07:00
|
|
|
hasher: State,
|
2018-08-01 17:28:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<R: Read> HashReader<R> {
|
|
|
|
/// Construct a new `HashReader` given an existing `reader` by value.
|
|
|
|
pub fn new(reader: R) -> Self {
|
|
|
|
HashReader {
|
2019-08-02 03:40:10 -07:00
|
|
|
reader,
|
2019-06-04 05:15:12 -07:00
|
|
|
hasher: State::new(),
|
2018-08-01 17:28:13 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Destroy this reader and return the hash of what was read.
|
|
|
|
pub fn into_hash(self) -> String {
|
|
|
|
let hash = self.hasher.finalize();
|
|
|
|
|
|
|
|
let mut s = String::new();
|
|
|
|
for c in hash.as_bytes().iter() {
|
|
|
|
s += &format!("{:02x}", c);
|
|
|
|
}
|
|
|
|
|
|
|
|
s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<R: Read> Read for HashReader<R> {
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
|
|
let bytes = self.reader.read(buf)?;
|
|
|
|
|
|
|
|
if bytes > 0 {
|
|
|
|
self.hasher.update(&buf[0..bytes]);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(bytes)
|
|
|
|
}
|
|
|
|
}
|