use std::collections::BTreeMap;
pub(crate) fn btree_merge<K: Ord + Clone, V: Clone, F: Fn(&V, &V) -> Option<V>>(
left: &BTreeMap<K, V>,
right: &BTreeMap<K, V>,
merge_func: F,
) -> BTreeMap<K, V> {
let mut res = BTreeMap::new();
let mut a = left.iter().peekable();
let mut b = right.iter().peekable();
loop {
match (a.peek().cloned(), b.peek().cloned()) {
(Some((akey, _)), Some((bkey, bval))) if akey > bkey => {
res.insert(bkey.clone(), bval.clone());
b.next();
}
(Some((akey, aval)), Some((bkey, _))) if akey < bkey => {
res.insert(akey.clone(), aval.clone());
a.next();
}
(Some((akey, aval)), Some((bkey, bval))) => {
assert!(akey == bkey);
if let Some(v) = merge_func(aval, bval) {
res.insert(akey.clone(), v);
}
a.next();
b.next();
}
(None, Some((bkey, bval))) => {
res.insert(bkey.clone(), bval.clone());
b.next();
}
(Some((akey, aval)), None) => {
res.insert(akey.clone(), aval.clone());
a.next();
}
(None, None) => break,
}
}
res
}