//! Implements the Preserves //! [merge](https://preserves.dev/preserves.html#appendix-merging-values) of values. use super::Map; use super::NestedValue; use super::Record; use super::Value; /// Merge two sequences of values according to [the /// specification](https://preserves.dev/preserves.html#appendix-merging-values). pub fn merge_seqs(mut a: Vec, mut b: Vec) -> Option> { 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) } /// Merge two values according to [the /// specification](https://preserves.dev/preserves.html#appendix-merging-values). pub fn merge2(v: N, w: N) -> Option { let (mut v_anns, v_val) = v.pieces(); let (w_anns, w_val) = w.pieces(); v_anns.modify(|anns| anns.extend(w_anns.to_vec().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)) } } /// Merge several values into a single value according to [the /// specification](https://preserves.dev/preserves.html#appendix-merging-values). pub fn merge>(vs: I) -> Option { 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) }