use prism::crypto::{Blake3Hasher, Keccak256Hasher, Sha256Hasher, Sha3_256Hasher, Sha512Hasher};
use prism::operation::TermValue;
use prism::vocabulary::Hasher;
pub const MAX_DIGEST_BYTES: usize = 64;
#[must_use]
pub const fn label_bytes(prefix: &str, digest_bytes: usize) -> usize {
prefix.len() + 1 + 2 * digest_bytes
}
pub const MAX_LABEL_BYTES: usize = label_bytes("sha512", MAX_DIGEST_BYTES);
pub trait AddrHash {
const LABEL_PREFIX: &'static str;
const OUTPUT_BYTES: usize;
const LABEL_BYTES: usize = label_bytes(Self::LABEL_PREFIX, Self::OUTPUT_BYTES);
fn digest_carrier<const N: usize>(input: &TermValue<'_, N>) -> [u8; MAX_DIGEST_BYTES];
}
fn stream<const N: usize, const FP: usize, H: Hasher<FP>>(input: &TermValue<'_, N>) -> [u8; FP] {
let mut h = H::initial();
input.for_each_chunk(&mut |chunk| {
let cur = core::mem::replace(&mut h, H::initial());
h = cur.fold_bytes(chunk);
});
h.finalize()
}
macro_rules! impl_addr_hash {
($hasher:ty, $prefix:literal, $fp:literal) => {
impl AddrHash for $hasher {
const LABEL_PREFIX: &'static str = $prefix;
const OUTPUT_BYTES: usize = $fp;
fn digest_carrier<const N: usize>(input: &TermValue<'_, N>) -> [u8; MAX_DIGEST_BYTES] {
let digest = stream::<N, $fp, $hasher>(input);
let mut out = [0u8; MAX_DIGEST_BYTES];
out[..$fp].copy_from_slice(&digest);
out
}
}
};
}
impl_addr_hash!(Sha256Hasher, "sha256", 32);
impl_addr_hash!(Blake3Hasher, "blake3", 32);
impl_addr_hash!(Sha3_256Hasher, "sha3-256", 32);
impl_addr_hash!(Keccak256Hasher, "keccak256", 32);
impl_addr_hash!(Sha512Hasher, "sha512", 64);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn label_widths_match_the_specification() {
assert_eq!(Sha256Hasher::LABEL_BYTES, 71);
assert_eq!(Blake3Hasher::LABEL_BYTES, 71);
assert_eq!(Sha3_256Hasher::LABEL_BYTES, 73);
assert_eq!(Keccak256Hasher::LABEL_BYTES, 74);
assert_eq!(Sha512Hasher::LABEL_BYTES, 135);
assert_eq!(MAX_LABEL_BYTES, 135);
assert_eq!(MAX_DIGEST_BYTES, 64);
}
#[test]
fn output_widths_match_the_axis() {
assert_eq!(<Sha256Hasher as AddrHash>::OUTPUT_BYTES, 32);
assert_eq!(<Sha512Hasher as AddrHash>::OUTPUT_BYTES, 64);
}
}