use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use crate::Pczt;
pub struct Combiner {
pczts: Vec<Pczt>,
}
impl Combiner {
pub fn new(pczts: Vec<Pczt>) -> Self {
Self { pczts }
}
pub fn combine(self) -> Result<Pczt, Error> {
self.pczts
.into_iter()
.try_fold(None, |acc, pczt| match acc {
None => Ok(Some(pczt)),
Some(acc) => merge(acc, pczt).map(Some),
})
.transpose()
.unwrap_or(Err(Error::NoPczts))
}
}
fn merge(lhs: Pczt, rhs: Pczt) -> Result<Pczt, Error> {
let transparent = lhs
.transparent
.merge(rhs.transparent, &lhs.global, &rhs.global)
.ok_or(Error::DataMismatch)?;
let sapling = lhs
.sapling
.merge(rhs.sapling, &lhs.global, &rhs.global)
.ok_or(Error::DataMismatch)?;
let orchard = lhs
.orchard
.merge(rhs.orchard, &lhs.global, &rhs.global)
.ok_or(Error::DataMismatch)?;
let global = lhs.global.merge(rhs.global).ok_or(Error::DataMismatch)?;
Ok(Pczt {
global,
transparent,
sapling,
orchard,
})
}
pub(crate) fn merge_optional<T: PartialEq>(lhs: &mut Option<T>, rhs: Option<T>) -> bool {
match (&lhs, rhs) {
(_, None) => (),
(None, Some(rhs)) => *lhs = Some(rhs),
(Some(lhs), Some(rhs)) if lhs == &rhs => (),
(Some(_), Some(_)) => return false,
}
true
}
pub(crate) fn merge_map<K: Ord, V: PartialEq>(
lhs: &mut BTreeMap<K, V>,
rhs: BTreeMap<K, V>,
) -> bool {
for (key, rhs_value) in rhs.into_iter() {
if let Some(lhs_value) = lhs.get_mut(&key) {
if lhs_value != &rhs_value {
return false;
}
} else {
lhs.insert(key, rhs_value);
}
}
true
}
#[derive(Debug)]
pub enum Error {
NoPczts,
DataMismatch,
}