mod merkle;
use std::fmt::Display;
use std::ops::{Index, IndexMut};
pub use merkle::MerkleTree;
use blake2b_simd::{Params, State};
pub const HASH_SIZE: usize = 28;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Digest([u8; HASH_SIZE]);
impl Digest {
pub const fn new(bytes: [u8; HASH_SIZE]) -> Self {
Self(bytes)
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl Display for Digest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for byte in &self.0 {
write!(f, "{:02x}", byte)?;
}
Ok(())
}
}
impl From<[u8; HASH_SIZE]> for Digest {
fn from(value: [u8; HASH_SIZE]) -> Self {
Self(value)
}
}
impl Index<usize> for Digest {
type Output = u8;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IndexMut<usize> for Digest {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}
#[derive(Debug)]
pub struct Blake2b(State);
impl Blake2b {
pub fn new_raw() -> Self {
let state = Params::new().hash_length(HASH_SIZE).to_state();
Self(state)
}
pub fn new_leaf() -> Self {
let Self(mut state) = Self::new_raw();
state.update(&[merkle::LEAF_PREFIX]);
Self(state)
}
pub fn new_node() -> Self {
let Self(mut state) = Self::new_raw();
state.update(&[merkle::NODE_PREFIX]);
Self(state)
}
pub fn update(&mut self, data: &[u8]) -> &mut Self {
self.0.update(data);
self
}
pub fn as_digest(&self) -> Digest {
let hash = self.0.finalize();
let bytes: [u8; HASH_SIZE] = hash.as_bytes().try_into().unwrap();
Digest::new(bytes)
}
}