use crate::Annotations;
use crate::CompoundClass;
use crate::Domain;
use crate::Map;
use crate::Value;
use crate::ValueClass;
use crate::ValueImpl;
pub fn merge_seqs<D: Domain>(
mut a: Vec<Value<D>>,
mut b: Vec<Value<D>>,
) -> Option<Vec<Value<D>>> {
if a.len() > b.len() {
std::mem::swap(&mut a, &mut b);
}
let mut r = vec![];
let mut bi = b.into_iter();
for av in a.into_iter() {
r.push(merge2(av, bi.next().unwrap())?);
}
r.extend(bi);
Some(r)
}
pub fn merge2<D: Domain>(v: Value<D>, w: Value<D>) -> Option<Value<D>> {
let anns = match (v.annotations(), w.annotations()) {
(Some(va), Some(wa)) => {
let mut a = va.to_vec();
a.extend(wa.to_vec());
a
}
(Some(va), None) => va.to_vec(),
(None, Some(wa)) => wa.to_vec(),
(None, None) => vec![],
};
let r = if v == w {
Some(v.peeled())
} else {
match v.value_class() {
ValueClass::Atomic(_) => None,
ValueClass::Embedded => None,
ValueClass::Compound(CompoundClass::Record) => if w.is_record() {
Some(Value::record(merge2(v.label(), w.label())?,
merge_seqs(v.iter().collect(), w.iter().collect())?))
} else {
None
}
ValueClass::Compound(CompoundClass::Sequence) => if w.is_sequence() {
Some(Value::new(merge_seqs(v.iter().collect(), w.iter().collect())?))
} else {
None
}
ValueClass::Compound(CompoundClass::Set) =>
None, ValueClass::Compound(CompoundClass::Dictionary) => if w.is_dictionary() {
let mut ws: Map<_, _> = w.entries().collect();
let mut rs = Map::new();
for (k, vv) in v.entries() {
match ws.remove(&k) {
Some(wv) => { rs.insert(k, merge2(vv, wv)?); }
None => { rs.insert(k, vv); }
}
}
rs.extend(ws.into_iter());
Some(Value::new(rs))
} else {
None
}
}
};
r.map(|r| if anns.is_empty() {
r
} else {
Value::new(Annotations::new(r, anns))
})
}
pub fn merge<D: Domain, I: IntoIterator<Item = Value<D>>>(vs: I) -> Option<Value<D>> {
let mut vs = vs.into_iter();
let mut v = vs.next().expect("at least one value in merge()");
for w in vs {
match merge2(v, w) {
Some(merged) => v = merged,
None => return None,
}
}
Some(v)
}