68 lines
2.0 KiB
Rust
68 lines
2.0 KiB
Rust
use super::Map;
|
|
use super::NestedValue;
|
|
use super::Record;
|
|
use super::Value;
|
|
|
|
pub fn merge_seqs<N: NestedValue>(mut a: Vec<N>, mut b: Vec<N>) -> Option<Vec<N>> {
|
|
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<N: NestedValue>(v: N, w: N) -> Option<N> {
|
|
let (mut v_anns, v_val) = v.pieces();
|
|
let (w_anns, w_val) = w.pieces();
|
|
match &mut v_anns {
|
|
None => v_anns = w_anns,
|
|
Some(vs) => match w_anns {
|
|
None => (),
|
|
Some(ws) => vs.extend(ws.into_iter()),
|
|
}
|
|
}
|
|
if v_val == w_val {
|
|
Some(N::wrap(v_anns, v_val))
|
|
} else {
|
|
let maybe_merged = match v_val {
|
|
Value::Record(rv) =>
|
|
Some(Value::Record(Record(merge_seqs(rv.0, w_val.into_record()?.0)?))),
|
|
Value::Sequence(vs) =>
|
|
Some(Value::Sequence(merge_seqs(vs, w_val.into_sequence()?)?)),
|
|
Value::Set(_vs) =>
|
|
None, // unsure how to merge sets
|
|
Value::Dictionary(vs) => {
|
|
let mut ws = w_val.into_dictionary()?;
|
|
let mut rs = Map::new();
|
|
for (k, vv) in vs.into_iter() {
|
|
match ws.remove(&k) {
|
|
Some(wv) => { rs.insert(k, merge2(vv, wv)?); }
|
|
None => { rs.insert(k, vv); }
|
|
}
|
|
}
|
|
rs.extend(ws.into_iter());
|
|
Some(Value::Dictionary(rs))
|
|
}
|
|
_ => None,
|
|
};
|
|
maybe_merged.map(|vw| N::wrap(v_anns, vw))
|
|
}
|
|
}
|
|
|
|
pub fn merge<N: NestedValue, I: IntoIterator<Item = N>>(vs: I) -> Option<N> {
|
|
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)
|
|
}
|