use super::*;
fn atom(v: &Value) -> Result<Value, RelationError> {
match v {
Value::Pair(..) => Err(RelationError::Unsupported("node: limb must be an atom")),
v => Ok(v.clone()),
}
}
fn halves(v: &Value) -> Result<(&Value, &Value), RelationError> {
match v {
Value::Pair(a, b) => Ok((a, b)),
_ => Err(RelationError::Unsupported("node: subject is [[L R] flags]")),
}
}
fn limbs(digest: &Value) -> Result<[Value; 4], RelationError> {
let (ab, cd) = halves(digest)?;
let (a, b) = halves(ab)?;
let (c, d) = halves(cd)?;
Ok([atom(a)?, atom(b)?, atom(c)?, atom(d)?])
}
impl Builder {
pub(super) fn node(&mut self, subject: &Value) -> Result<Value, RelationError> {
let (children, flags) = halves(subject)?;
let (left, right) = halves(children)?;
let mut state: [Value; 16] = core::array::from_fn(|_| Value::Constant(F::ZERO));
state[..4].clone_from_slice(&limbs(left)?);
state[4..8].clone_from_slice(&limbs(right)?);
state[9] = atom(flags)?;
let out = self.hash_permute(state)?;
Ok(Value::Pair(
Box::new(Value::Pair(
Box::new(out[0].clone()),
Box::new(out[1].clone()),
)),
Box::new(Value::Pair(
Box::new(out[2].clone()),
Box::new(out[3].clone()),
)),
))
}
}