use super::*; use sha2::{ Sha256, Digest, }; use std::{ fmt, io::{ self, Read, }, }; pub const SHA256_SIZE: usize = 32; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Sha256Hash([u8; SHA256_SIZE]); impl Sha256Hash { pub fn new(from: [u8; SHA256_SIZE]) -> Self { Self(from) } pub fn from_slice(from: T) -> Self where T: AsRef<[u8]> { let mut out = [0u8; SHA256_SIZE]; bytes::copy_slice(&mut out, from.as_ref()); Self(out) } } impl fmt::Display for Sha256Hash { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Sha256hash (")?; for b in self.0.iter() { write!(f,"{:02x}", *b)?; } write!(f, ")") } } impl Default for Sha256Hash { fn default() -> Self { Self([0u8; SHA256_SIZE]) } } impl From for Sha256Hash { fn from(hash: Sha256) -> Sha256Hash { let mut out = [0u8; SHA256_SIZE]; assert_eq!(bytes::copy_slice(&mut out, hash.finalize()), SHA256_SIZE); Self(out) } } impl AsRef<[u8]> for Sha256Hash { fn as_ref(&self) -> &[u8] { &self.0[..] } } /// Compute SHA256 hash from a stream. pub fn compute(stream: &mut R, result: &mut Sha256Hash) -> io::Result { let mut buffer = [0u8; BUFFER_SIZE]; let mut read; let mut done=0; let mut digest = Sha256::new(); while {read = stream.read(&mut buffer[..])?; read!=0} { digest.update(&buffer[..read]); done+=read; } *result = digest.into(); Ok(done) } /// Compute SHA256 hash from a stream. #[cfg(feature="threads")] pub async fn compute_async(stream: &mut R, result: &mut Sha256Hash) -> io::Result where R: tokio::io::AsyncRead + std::marker::Send + std::marker::Sync + std::marker::Unpin { use tokio::prelude::*; let mut buffer = [0u8; BUFFER_SIZE]; let mut read; let mut done=0; let mut digest = Sha256::new(); while {read = stream.read(&mut buffer[..]).await?; read!=0} { digest.update(&buffer[..read]); done+=read; } *result = digest.into(); Ok(done) }