preserves/implementations/rust/preserves/src/merge.rs

93 lines
3.0 KiB
Rust

use crate::Annotations;
use crate::ArcValue;
use crate::CompoundClass;
use crate::Map;
use crate::Record;
use crate::Value;
use crate::ValueClass;
use crate::ValueImpl;
pub fn merge_seqs<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(
mut a: Vec<Value<V>>,
mut b: Vec<Value<W>>,
) -> Option<Vec<ArcValue<V::Embedded>>> {
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.map(|bv| bv.value_clone()));
Some(r)
}
pub fn merge2<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(v: &Value<V>, w: &Value<W>) -> Option<ArcValue<V::Embedded>> {
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().value_clone())
} else {
match v.value_class() {
ValueClass::Atomic(_) => None,
ValueClass::Embedded => None,
ValueClass::Compound(CompoundClass::Record) => if w.is_record() {
todo!()
// Some(owned(Record::new(merge2(&*v.label(), &*w.label())?,
// merge_seqs(v.iter().collect(), w.iter().collect())?)))
} else {
None
}
ValueClass::Compound(CompoundClass::Sequence) => if w.is_sequence() {
Some(owned(merge_seqs(v.iter().collect(), w.iter().collect())?))
} else {
None
}
ValueClass::Compound(CompoundClass::Set) =>
None, // unsure how to merge sets
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.value_clone(), merge2(&*vv, &*wv)?); }
None => { rs.insert(k.value_clone(), vv.value_clone()); }
}
}
rs.extend(ws.into_iter().map(|(k, wv)| (k.value_clone(), wv.value_clone())));
Some(owned(rs))
} else {
None
}
}
};
r.map(|r| if anns.is_empty() {
r
} else {
owned(Annotations::new(r, anns))
})
}
pub fn merge<V: ValueImpl, I: IntoIterator<Item = Value<V>>>(vs: I) -> Option<ArcValue<V::Embedded>> {
let mut vs = vs.into_iter();
let mut v = vs.next().expect("at least one value in merge()").value_clone();
for w in vs {
match merge2(&*v, &*w) {
Some(merged) => v = merged,
None => return None,
}
}
Some(v)
}