use crate::basic::persistent_btree::{NodeId, PersistentBTree};
pub fn three_way_merge(
tree: &mut PersistentBTree,
ancestor_root: NodeId,
source_root: NodeId,
target_root: NodeId,
) -> NodeId {
if ancestor_root == source_root {
return target_root;
}
if ancestor_root == target_root {
return source_root;
}
if source_root == target_root {
return source_root;
}
let mut iter_a = tree.iter(ancestor_root).peekable();
let mut iter_s = tree.iter(source_root).peekable();
let mut iter_t = tree.iter(target_root).peekable();
let mut merged: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
loop {
let ka = iter_a.peek().map(|(k, _)| k.as_slice());
let ks = iter_s.peek().map(|(k, _)| k.as_slice());
let kt = iter_t.peek().map(|(k, _)| k.as_slice());
if ka.is_none() && ks.is_none() && kt.is_none() {
break;
}
let min_key = [ka, ks, kt].into_iter().flatten().min().unwrap().to_vec();
let a_val = if ka == Some(min_key.as_slice()) {
let (_, v) = iter_a.next().unwrap();
Some(v)
} else {
None
};
let s_val = if ks == Some(min_key.as_slice()) {
let (_, v) = iter_s.next().unwrap();
Some(v)
} else {
None
};
let t_val = if kt == Some(min_key.as_slice()) {
let (_, v) = iter_t.next().unwrap();
Some(v)
} else {
None
};
let result = match (a_val.as_deref(), s_val.as_deref(), t_val.as_deref()) {
(Some(a), Some(s), Some(t)) if a == s && a == t => Some(a),
(Some(a), Some(s), Some(t)) if a == t => Some(s),
(Some(a), Some(s), Some(t)) if a == s => Some(t),
(Some(_), Some(s), Some(t)) if s == t => Some(s),
(Some(_), Some(s), Some(_)) => Some(s),
(Some(a), None, Some(t)) if a == t => None,
(Some(a), Some(s), None) if a == s => None,
(Some(_), None, Some(_)) => None,
(Some(_), Some(s), None) => Some(s),
(Some(_), None, None) => None,
(None, Some(s), None) => Some(s),
(None, None, Some(t)) => Some(t),
(None, Some(s), Some(t)) if s == t => Some(s),
(None, Some(s), Some(_)) => Some(s),
(None, None, None) => None,
};
if let Some(val) = result {
merged.push((min_key, val.to_vec()));
}
}
tree.bulk_load(merged)
}