merge_from.rs

  1use std::rc::Rc;
  2
  3/// Trait for recursively merging settings structures.
  4///
  5/// This trait allows settings objects to be merged from optional sources,
  6/// where `None` values are ignored and `Some` values override existing values.
  7///
  8/// HashMaps, structs and similar types are merged by combining their contents key-wise,
  9/// but all other types (including Vecs) are last-write-wins.
 10/// (Though see also ExtendingVec and SaturatingBool)
 11#[allow(unused)]
 12pub trait MergeFrom {
 13    /// Merge from an optional source of the same type.
 14    /// If `other` is `None`, no changes are made.
 15    /// If `other` is `Some(value)`, fields from `value` are merged into `self`.
 16    fn merge_from(&mut self, other: Option<&Self>);
 17}
 18
 19macro_rules! merge_from_overwrites {
 20    ($($type:ty),+) => {
 21        $(
 22            impl MergeFrom for $type {
 23                fn merge_from(&mut self, other: Option<&Self>) {
 24                    if let Some(value) = other {
 25                        *self = value.clone();
 26                    }
 27                }
 28            }
 29        )+
 30    }
 31}
 32
 33merge_from_overwrites!(
 34    u16,
 35    u32,
 36    u64,
 37    usize,
 38    i16,
 39    i32,
 40    i64,
 41    bool,
 42    f64,
 43    f32,
 44    std::num::NonZeroUsize,
 45    std::num::NonZeroU32,
 46    String,
 47    std::sync::Arc<str>,
 48    gpui::SharedString,
 49    std::path::PathBuf,
 50    gpui::Modifiers,
 51    gpui::FontFeatures
 52);
 53
 54impl<T: Clone> MergeFrom for Vec<T> {
 55    fn merge_from(&mut self, other: Option<&Self>) {
 56        if let Some(other) = other {
 57            *self = other.clone()
 58        }
 59    }
 60}
 61
 62// Implementations for collections that extend/merge their contents
 63impl<K, V> MergeFrom for collections::HashMap<K, V>
 64where
 65    K: Clone + std::hash::Hash + Eq,
 66    V: Clone + MergeFrom,
 67{
 68    fn merge_from(&mut self, other: Option<&Self>) {
 69        let Some(other) = other else { return };
 70        for (k, v) in other {
 71            if let Some(existing) = self.get_mut(k) {
 72                existing.merge_from(Some(v));
 73            } else {
 74                self.insert(k.clone(), v.clone());
 75            }
 76        }
 77    }
 78}
 79
 80impl<K, V> MergeFrom for collections::BTreeMap<K, V>
 81where
 82    K: Clone + std::hash::Hash + Eq + Ord,
 83    V: Clone + MergeFrom,
 84{
 85    fn merge_from(&mut self, other: Option<&Self>) {
 86        let Some(other) = other else { return };
 87        for (k, v) in other {
 88            if let Some(existing) = self.get_mut(k) {
 89                existing.merge_from(Some(v));
 90            } else {
 91                self.insert(k.clone(), v.clone());
 92            }
 93        }
 94    }
 95}
 96
 97impl<K, V> MergeFrom for collections::IndexMap<K, V>
 98where
 99    K: std::hash::Hash + Eq + Clone,
100    // Q: ?Sized + std::hash::Hash + collections::Equivalent<K> + Eq,
101    V: Clone + MergeFrom,
102{
103    fn merge_from(&mut self, other: Option<&Self>) {
104        let Some(other) = other else { return };
105        for (k, v) in other {
106            if let Some(existing) = self.get_mut(k) {
107                existing.merge_from(Some(v));
108            } else {
109                self.insert(k.clone(), v.clone());
110            }
111        }
112    }
113}
114
115impl<T> MergeFrom for collections::BTreeSet<T>
116where
117    T: Clone + Ord,
118{
119    fn merge_from(&mut self, other: Option<&Self>) {
120        let Some(other) = other else { return };
121        for item in other {
122            self.insert(item.clone());
123        }
124    }
125}
126
127impl<T> MergeFrom for collections::HashSet<T>
128where
129    T: Clone + std::hash::Hash + Eq,
130{
131    fn merge_from(&mut self, other: Option<&Self>) {
132        let Some(other) = other else { return };
133        for item in other {
134            self.insert(item.clone());
135        }
136    }
137}
138
139impl MergeFrom for serde_json::Value {
140    fn merge_from(&mut self, other: Option<&Self>) {
141        let Some(other) = other else { return };
142        match (self, other) {
143            (serde_json::Value::Object(this), serde_json::Value::Object(other)) => {
144                for (k, v) in other {
145                    if let Some(existing) = this.get_mut(k) {
146                        existing.merge_from(other.get(k));
147                    } else {
148                        this.insert(k.clone(), v.clone());
149                    }
150                }
151            }
152            (this, other) => *this = other.clone(),
153        }
154    }
155}
156
157impl<T: MergeFrom + Clone> MergeFrom for Rc<T> {
158    fn merge_from(&mut self, other: Option<&Self>) {
159        let Some(other) = other else { return };
160        let mut this: T = self.as_ref().clone();
161        this.merge_from(Some(other.as_ref()));
162        *self = Rc::new(this)
163    }
164}