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}