use super::*;
mod leaf_hash;
pub use leaf_hash::*;
mod path_hash;
pub use path_hash::*;
#[derive(Clone, Debug)]
pub struct BooleanHash<E: Environment, const VARIANT: usize>(pub [Boolean<E>; VARIANT]);
impl<E: Environment, const VARIANT: usize> Default for BooleanHash<E, VARIANT> {
fn default() -> Self {
Self::new(Mode::Constant, console::kary_merkle_tree::BooleanHash::new())
}
}
#[cfg(console)]
impl<E: Environment, const VARIANT: usize> Inject for BooleanHash<E, VARIANT> {
type Primitive = console::kary_merkle_tree::BooleanHash<VARIANT>;
fn new(mode: Mode, hash: Self::Primitive) -> Self {
let hash = hash.iter().map(|b| Boolean::new(mode, *b)).collect::<Vec<_>>();
match hash.len() == VARIANT {
true => Self(hash.try_into().unwrap()),
false => E::halt("Boolean hash is not the correct length"),
}
}
}
#[cfg(console)]
impl<E: Environment, const VARIANT: usize> Eject for BooleanHash<E, VARIANT> {
type Primitive = console::kary_merkle_tree::BooleanHash<VARIANT>;
fn eject_mode(&self) -> Mode {
self.0.eject_mode()
}
fn eject_value(&self) -> Self::Primitive {
console::kary_merkle_tree::BooleanHash::<VARIANT>(self.0.eject_value().try_into().unwrap())
}
}
impl<E: Environment, const VARIANT: usize> Equal<Self> for BooleanHash<E, VARIANT> {
type Output = Boolean<E>;
fn is_equal(&self, other: &Self) -> Self::Output {
self.iter().zip_eq(other.iter()).map(|(a, b)| a.is_equal(b)).fold(Boolean::constant(true), Boolean::bitand)
}
fn is_not_equal(&self, other: &Self) -> Self::Output {
!self.is_equal(other)
}
}
impl<E: Environment, const VARIANT: usize> Ternary for BooleanHash<E, VARIANT> {
type Boolean = Boolean<E>;
type Output = Self;
fn ternary(condition: &Self::Boolean, first: &Self, second: &Self) -> Self::Output {
let mut result = Vec::with_capacity(VARIANT);
for (a, b) in first.iter().zip_eq(second.iter()) {
result.push(Self::Boolean::ternary(condition, a, b));
}
Self(result.try_into().unwrap())
}
}
impl<E: Environment, const VARIANT: usize> Deref for BooleanHash<E, VARIANT> {
type Target = [Boolean<E>; VARIANT];
fn deref(&self) -> &Self::Target {
&self.0
}
}