figment/
coalesce.rs

1use crate::Profile;
2use crate::value::{Value, Map};
3
4#[derive(Debug, Clone, Copy, PartialEq)]
5pub enum Order {
6    Merge,
7    Join,
8    Adjoin,
9    Admerge,
10}
11
12pub trait Coalescible: Sized {
13    fn coalesce(self, other: Self, order: Order) -> Self;
14    fn merge(self, other: Self) -> Self { self.coalesce(other, Order::Merge) }
15}
16
17impl Coalescible for Profile {
18    fn coalesce(self, other: Self, order: Order) -> Self {
19        match order {
20            Order::Join | Order::Adjoin => self,
21            Order::Merge | Order::Admerge => other,
22        }
23    }
24}
25
26impl Coalescible for Value {
27    fn coalesce(self, other: Self, o: Order) -> Self {
28        use {Value::Dict as D, Value::Array as A, Order::*};
29        match (self, other, o) {
30            (D(t, a), D(_, b), Join | Adjoin) | (D(_, a), D(t, b), Merge | Admerge) => D(t, a.coalesce(b, o)),
31            (A(t, mut a), A(_, b), Adjoin | Admerge) => A(t, { a.extend(b); a }),
32            (v, _, Join | Adjoin) | (_, v, Merge | Admerge) => v,
33        }
34    }
35}
36
37impl<K: Eq + std::hash::Hash + Ord, V: Coalescible> Coalescible for Map<K, V> {
38    fn coalesce(self, mut other: Self, order: Order) -> Self {
39        let mut joined = Map::new();
40        for (a_key, a_val) in self {
41            match other.remove(&a_key) {
42                Some(b_val) => joined.insert(a_key, a_val.coalesce(b_val, order)),
43                None => joined.insert(a_key, a_val),
44            };
45        }
46
47        // `b` contains `b - a`, i.e, additions. keep them all.
48        joined.extend(other);
49        joined
50    }
51}