k8s_openapi/
deep_merge.rs1pub trait DeepMerge {
55 fn merge_from(&mut self, other: Self);
57}
58
59macro_rules! default_overwriting_impl {
60 () => {
61 fn merge_from(&mut self, other: Self) {
62 *self = other;
63 }
64 };
65}
66
67impl DeepMerge for bool { default_overwriting_impl! {} }
68impl DeepMerge for i32 { default_overwriting_impl! {} }
69impl DeepMerge for i64 { default_overwriting_impl! {} }
70impl DeepMerge for f64 { default_overwriting_impl! {} }
71impl DeepMerge for String { default_overwriting_impl! {} }
72impl DeepMerge for crate::ByteString { default_overwriting_impl! {} }
73impl<Tz> DeepMerge for chrono::DateTime<Tz> where Tz: chrono::TimeZone { default_overwriting_impl! {} }
74
75impl DeepMerge for serde_json::Value {
76 fn merge_from(&mut self, other: Self) {
77 if let serde_json::Value::Object(this) = self {
78 if let serde_json::Value::Object(other) = other {
79 for (k, v) in other {
80 if v.is_null() {
81 this.remove(&k);
82 }
83 else {
84 this.entry(k).or_insert(serde_json::Value::Null).merge_from(v);
85 }
86 }
87
88 return;
89 }
90 }
91
92 *self = other;
93 }
94}
95
96impl<T> DeepMerge for Box<T> where T: DeepMerge {
97 fn merge_from(&mut self, other: Self) {
98 (**self).merge_from(*other);
99 }
100}
101
102impl<T> DeepMerge for Option<T> where T: DeepMerge {
103 fn merge_from(&mut self, other: Self) {
104 if let Some(other) = other {
105 if let Some(s) = self {
106 s.merge_from(other);
107 }
108 else {
109 *self = Some(other);
110 }
111 }
112 }
113}
114
115pub mod strategies {
117 pub mod list {
121 mod private {
122 pub trait AsOptVec {
123 type Item;
124
125 fn set_if_some(&mut self, new: Self);
126 fn as_mut_opt(&mut self) -> Option<&mut Vec<Self::Item>>;
127 fn into_opt(self) -> Option<Vec<Self::Item>>;
128 }
129
130 impl<T> AsOptVec for Vec<T> {
131 type Item = T;
132
133 fn set_if_some(&mut self, new: Self) {
134 *self = new;
135 }
136
137 fn as_mut_opt(&mut self) -> Option<&mut Self> {
138 Some(self)
139 }
140
141 fn into_opt(self) -> Option<Self> {
142 Some(self)
143 }
144 }
145
146 impl<T> AsOptVec for Option<Vec<T>> {
147 type Item = T;
148
149 fn set_if_some(&mut self, new: Self) {
150 if new.is_some() {
151 *self = new;
152 }
153 }
154
155 fn as_mut_opt(&mut self) -> Option<&mut Vec<T>> {
156 self.as_mut()
157 }
158
159 fn into_opt(self) -> Self {
160 self
161 }
162 }
163 }
164 use private::AsOptVec;
165
166 pub fn atomic<V>(current: &mut V, new: V) where V: AsOptVec {
168 current.set_if_some(new);
169 }
170
171 pub fn map<V>(
175 current: &mut V,
176 new: V,
177 key_comparators: &[fn(&V::Item, &V::Item) -> bool],
178 merge_item: fn(&mut V::Item, V::Item),
179 )
180 where
181 V: AsOptVec,
182 {
183 if let Some(current) = current.as_mut_opt() {
184 for new_item in new.into_opt().into_iter().flatten() {
185 if let Some(current_item) = current.iter_mut().find(|current_item| key_comparators.iter().all(|&f| f(&**current_item, &new_item))) {
186 merge_item(current_item, new_item);
187 }
188 else {
189 current.push(new_item);
190 }
191 }
192 }
193 else {
194 current.set_if_some(new);
195 }
196 }
197
198 pub fn set<V>(current: &mut V, new: V) where V: AsOptVec, V::Item: PartialEq {
202 if let Some(current) = current.as_mut_opt() {
203 for item in new.into_opt().into_iter().flatten() {
204 if !current.contains(&item) {
205 current.push(item);
206 }
207 }
208 }
209 else {
210 current.set_if_some(new);
211 }
212 }
213 }
214
215 pub mod map {
219 mod private {
220 use std::collections::BTreeMap;
221
222 pub trait AsOptMap {
223 type Key;
224 type Value;
225
226 fn set_if_some(&mut self, new: Self);
227 fn as_mut_opt(&mut self) -> Option<&mut BTreeMap<Self::Key, Self::Value>>;
228 fn into_opt(self) -> Option<BTreeMap<Self::Key, Self::Value>>;
229 }
230
231 impl<K, V> AsOptMap for BTreeMap<K, V> {
232 type Key = K;
233 type Value = V;
234
235 fn set_if_some(&mut self, new: Self) {
236 *self = new;
237 }
238
239 fn as_mut_opt(&mut self) -> Option<&mut Self> {
240 Some(self)
241 }
242
243 fn into_opt(self) -> Option<Self> {
244 Some(self)
245 }
246 }
247
248 impl<K, V> AsOptMap for Option<BTreeMap<K, V>> {
249 type Key = K;
250 type Value = V;
251
252 fn set_if_some(&mut self, new: Self) {
253 if new.is_some() {
254 *self = new;
255 }
256 }
257
258 fn as_mut_opt(&mut self) -> Option<&mut BTreeMap<K, V>> {
259 self.as_mut()
260 }
261
262 fn into_opt(self) -> Self {
263 self
264 }
265 }
266 }
267 use private::AsOptMap;
268
269 pub fn atomic<M>(current: &mut M, new: M) where M: AsOptMap {
271 current.set_if_some(new);
272 }
273
274 pub fn granular<M>(current: &mut M, new: M, merge_value: fn(&mut M::Value, M::Value))
276 where
277 M: AsOptMap,
278 M::Key: Ord,
279 {
280 if let Some(current) = current.as_mut_opt() {
281 for (k, new_v) in new.into_opt().into_iter().flatten() {
282 match current.entry(k) {
283 std::collections::btree_map::Entry::Vacant(entry) => { entry.insert(new_v); }
284 std::collections::btree_map::Entry::Occupied(entry) => merge_value(entry.into_mut(), new_v),
285 }
286 }
287 }
288 else {
289 current.set_if_some(new);
290 }
291 }
292 }
293}