use std::io;
use lexe_byte_array::ByteArray;
use ref_cast::RefCast;
pub const HASH_LEN: usize = 32;
#[derive(Copy, Clone, Default, Eq, Hash, PartialEq, RefCast)]
#[repr(transparent)]
pub struct Hash([u8; 32]);
#[derive(Clone)]
pub struct Context(ring::digest::Context);
pub fn digest(input: &[u8]) -> Hash {
digest_many(&[input])
}
pub fn digest_many(inputs: &[&[u8]]) -> Hash {
let mut ctx = Context::new();
for input in inputs {
ctx.update(input);
}
ctx.finish()
}
impl Hash {
pub const fn new(value: [u8; 32]) -> Self {
Self(value)
}
fn from_ring(output: ring::digest::Digest) -> Self {
Self::new(<[u8; 32]>::try_from(output.as_ref()).unwrap())
}
}
lexe_byte_array::impl_byte_array!(Hash, 32);
lexe_byte_array::impl_fromstr_fromhex!(Hash, 32);
lexe_byte_array::impl_debug_display_as_hex!(Hash);
impl Context {
pub fn new() -> Self {
Self(ring::digest::Context::new(&ring::digest::SHA256))
}
pub fn update(&mut self, input: &[u8]) {
self.0.update(input);
}
pub fn finish(self) -> Hash {
Hash::from_ring(self.0.finish())
}
}
impl Default for Context {
fn default() -> Self {
Self::new()
}
}
impl io::Write for Context {
fn write(&mut self, input: &[u8]) -> io::Result<usize> {
self.update(input);
Ok(input.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
#[cfg(test)]
mod test {
use lexe_hex::hex;
use crate::sha256;
#[test]
fn test_sha256() {
let actual = hex::encode(sha256::digest(b"").as_ref());
let expected =
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
assert_eq!(&actual, expected);
}
}