1use crate::{path::StorePath, KeyMap, KeyedAccess, KeyedSubfield, StoreField};
2use indexmap::IndexMap;
3use itertools::{EitherOrBoth, Itertools};
4use reactive_graph::traits::{Notify, UntrackableGuard};
5use std::{
6 borrow::Cow,
7 collections::{BTreeMap, HashMap},
8 fmt::Debug,
9 hash::Hash,
10 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
11 num::{
12 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8,
13 NonZeroIsize, NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64,
14 NonZeroU8, NonZeroUsize,
15 },
16 rc::Rc,
17 sync::Arc,
18};
19
20pub trait Patch {
22 type Value;
24
25 fn patch(&self, new: Self::Value);
27}
28
29impl<T> Patch for T
30where
31 T: StoreField,
32 T::Value: PatchField,
33{
34 type Value = T::Value;
35
36 fn patch(&self, new: Self::Value) {
37 let path = self.path_unkeyed().into_iter().collect::<StorePath>();
38 let keys = self.keys();
39
40 if let Some(mut writer) = self.writer() {
41 writer.untrack();
43 let mut notify = |path: &StorePath| {
44 self.triggers_for_path_unkeyed(path.to_owned()).notify();
45 };
46 writer.patch_field(new, &path, &mut notify, keys.as_ref());
47 }
48 }
49}
50
51impl<Inner, Prev, K, T> KeyedSubfield<Inner, Prev, K, T>
52where
53 Self: Clone,
54 for<'a> &'a T: IntoIterator,
55 Self: StoreField<Value = T>,
56 <Self as StoreField>::Value: PatchFieldKeyed<K>,
57 Inner: StoreField<Value = Prev>,
58 T: PatchFieldKeyed<K>,
59 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
60 Prev: 'static,
61{
62 pub fn patch(&self, new: T) {
67 let path = self.path_unkeyed().into_iter().collect::<StorePath>();
68 let keys = self.keys();
69
70 let structure_changed = if let Some(mut writer) = self.writer() {
71 writer.untrack();
73 let mut notify = |path: &StorePath| {
74 self.triggers_for_path_unkeyed(path.to_owned()).notify();
75 };
76 writer.patch_field_keyed(
77 new,
78 &mut notify,
79 keys.as_ref(),
80 self.key_fn,
81 |key| self.path_at_key(&path, key),
82 )
83 } else {
84 false
85 };
86
87 if structure_changed {
88 let trigger = self.get_trigger_unkeyed(path.clone());
92 trigger.children.notify();
93
94 let mut ancestor_path = path;
95 while !ancestor_path.is_empty() {
96 ancestor_path.pop();
97 let inner = self.get_trigger_unkeyed(ancestor_path.clone());
98 inner.children.notify();
99 }
100 }
101
102 self.update_keys();
103 }
104}
105
106pub trait PatchField {
108 fn patch_field(
117 &mut self,
118 new: Self,
119 path: &StorePath,
120 notify: &mut dyn FnMut(&StorePath),
121 keys: Option<&KeyMap>,
122 );
123}
124
125pub trait PatchFieldKeyed<K>
136where
137 Self: Sized + KeyedAccess<K>,
138 for<'a> &'a Self: IntoIterator,
139{
140 fn patch_field_keyed(
153 &mut self,
154 new: Self,
155 notify: &mut dyn FnMut(&StorePath),
156 keys: Option<&KeyMap>,
157 key_fn: impl Fn(<&Self as IntoIterator>::Item) -> K,
158 path_at_key: impl Fn(&K) -> Option<StorePath>,
159 ) -> bool
160 where
161 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static;
162}
163
164macro_rules! patch_primitives {
165 ($($ty:ty),*) => {
166 $(impl PatchField for $ty {
167 fn patch_field(
168 &mut self,
169 new: Self,
170 path: &StorePath,
171 notify: &mut dyn FnMut(&StorePath),
172 _keys: Option<&KeyMap>
173 ) {
174 if new != *self {
175 *self = new;
176 notify(path);
177 }
178 }
179 })*
180 };
181}
182
183patch_primitives! {
184 &str,
185 String,
186 Arc<str>,
187 Rc<str>,
188 Cow<'_, str>,
189 usize,
190 u8,
191 u16,
192 u32,
193 u64,
194 u128,
195 isize,
196 i8,
197 i16,
198 i32,
199 i64,
200 i128,
201 f32,
202 f64,
203 char,
204 bool,
205 IpAddr,
206 SocketAddr,
207 SocketAddrV4,
208 SocketAddrV6,
209 Ipv4Addr,
210 Ipv6Addr,
211 NonZeroI8,
212 NonZeroU8,
213 NonZeroI16,
214 NonZeroU16,
215 NonZeroI32,
216 NonZeroU32,
217 NonZeroI64,
218 NonZeroU64,
219 NonZeroI128,
220 NonZeroU128,
221 NonZeroIsize,
222 NonZeroUsize
223}
224
225impl<T> PatchField for Option<T>
226where
227 T: PatchField,
228{
229 fn patch_field(
230 &mut self,
231 new: Self,
232 path: &StorePath,
233 notify: &mut dyn FnMut(&StorePath),
234 keys: Option<&KeyMap>,
235 ) {
236 match (self, new) {
237 (None, None) => {}
238 (old @ Some(_), None) => {
239 old.take();
240 notify(path);
241 }
242 (old @ None, new @ Some(_)) => {
243 *old = new;
244 notify(path);
245 }
246 (Some(old), Some(new)) => {
247 let mut new_path = path.to_owned();
248 new_path.push(0);
249 old.patch_field(new, &new_path, notify, keys);
250 }
251 }
252 }
253}
254
255impl<T> PatchField for Vec<T>
256where
257 T: PatchField,
258{
259 fn patch_field(
260 &mut self,
261 new: Self,
262 path: &StorePath,
263 notify: &mut dyn FnMut(&StorePath),
264 keys: Option<&KeyMap>,
265 ) {
266 if self.is_empty() && new.is_empty() {
267 return;
268 }
269
270 if new.is_empty() {
271 self.clear();
272 notify(path);
273 } else if self.is_empty() {
274 self.extend(new);
275 notify(path);
276 } else {
277 let mut adds = vec![];
278 let mut removes_at_end = 0;
279 let mut new_path = path.to_owned();
280 new_path.push(0);
281 for (idx, item) in
282 new.into_iter().zip_longest(self.iter_mut()).enumerate()
283 {
284 match item {
285 EitherOrBoth::Both(new, old) => {
286 old.patch_field(new, &new_path, notify, keys);
287 }
288 EitherOrBoth::Left(new) => {
289 adds.push(new);
290 }
291 EitherOrBoth::Right(_) => {
292 removes_at_end += 1;
293 }
294 }
295 new_path.replace_last(idx + 1);
296 }
297
298 let length_changed = removes_at_end > 0 || !adds.is_empty();
299 self.truncate(self.len() - removes_at_end);
300 self.append(&mut adds);
301
302 if length_changed {
303 notify(path);
304 }
305 }
306 }
307}
308
309impl<K, T> PatchFieldKeyed<K> for Vec<T>
310where
311 T: PatchField,
312{
313 fn patch_field_keyed(
314 &mut self,
315 mut new: Self,
316 notify: &mut dyn FnMut(&StorePath),
317 keys: Option<&KeyMap>,
318 key_fn: impl Fn(<&Self as IntoIterator>::Item) -> K,
319 path_at_key: impl Fn(&K) -> Option<StorePath>,
320 ) -> bool
321 where
322 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
323 {
324 let mut has_changed = false;
325
326 let mut old_keyed = HashMap::new();
327 let mut new_keyed = IndexMap::new();
328
329 for (idx, item) in self.drain(0..).enumerate() {
331 let key = key_fn(&item);
332 old_keyed.insert(key, (idx, item));
333 }
334
335 for (idx, item) in new.drain(0..).enumerate() {
337 let key = key_fn(&item);
338 new_keyed.insert(key, (idx, item));
339 }
340
341 for old_key in old_keyed.keys() {
343 if !new_keyed.contains_key(old_key) {
344 has_changed = true;
345 }
346 }
347
348 for (key, (new_idx, new_value)) in new_keyed {
357 let old_at_key = old_keyed.remove(&key);
358
359 match old_at_key {
360 None => {
361 new.push(new_value);
363
364 has_changed = true;
366 }
367 Some((old_idx, old_value)) => {
369 if old_idx != new_idx {
371 has_changed = true;
372 }
373
374 new.push(old_value);
378 let field_to_patch = &mut new[new_idx];
379
380 if let Some(path) = path_at_key(&key) {
386 field_to_patch
387 .patch_field(new_value, &path, notify, keys);
388 } else {
389 has_changed = true;
390 }
391 }
392 }
393 }
394
395 *self = new;
397
398 has_changed
399 }
400}
401
402impl<K, V> PatchFieldKeyed<K> for HashMap<K, V>
403where
404 V: PatchField,
405 K: Eq + Hash,
406{
407 fn patch_field_keyed(
408 &mut self,
409 mut new: Self,
410 notify: &mut dyn FnMut(&StorePath),
411 keys: Option<&KeyMap>,
412 key_fn: impl Fn(<&Self as IntoIterator>::Item) -> K,
413 path_at_key: impl Fn(&K) -> Option<StorePath>,
414 ) -> bool
415 where
416 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
417 {
418 let mut has_changed = false;
419
420 let mut old_keyed = HashMap::with_capacity(self.len());
421 let mut new_keyed = HashMap::with_capacity(new.len());
422
423 for item in self.drain() {
425 let key = key_fn((&item.0, &item.1));
426 old_keyed.insert(key, item);
427 }
428
429 for item in new.drain() {
431 let key = key_fn((&item.0, &item.1));
432 new_keyed.insert(key, item);
433 }
434
435 for old_key in old_keyed.keys() {
437 if !new_keyed.contains_key(old_key) {
438 has_changed = true;
439 }
440 }
441
442 for (key, new_value) in new_keyed {
448 let old_at_key = old_keyed.remove(&key);
449
450 match old_at_key {
451 None => {
452 new.insert(new_value.0, new_value.1);
454
455 has_changed = true;
457 }
458 Some(mut old_value) => {
460 if let Some(path) = path_at_key(&key) {
464 old_value.1.patch_field(
465 new_value.1,
466 &path,
467 notify,
468 keys,
469 );
470 } else {
471 has_changed = true;
472 }
473
474 new.insert(new_value.0, old_value.1);
476 }
477 }
478 }
479
480 *self = new;
482
483 has_changed
484 }
485}
486
487impl<K, V> PatchFieldKeyed<K> for BTreeMap<K, V>
488where
489 V: PatchField + Clone,
490 K: Eq + Ord + Clone,
491{
492 fn patch_field_keyed(
493 &mut self,
494 new: Self,
495 notify: &mut dyn FnMut(&StorePath),
496 keys: Option<&KeyMap>,
497 key_fn: impl Fn(<&Self as IntoIterator>::Item) -> K,
498 path_at_key: impl Fn(&K) -> Option<StorePath>,
499 ) -> bool
500 where
501 K: Clone + Debug + Send + Sync + PartialEq + Eq + Hash + 'static,
502 {
503 let mut has_changed = false;
504 let mut old_keyed = BTreeMap::new();
505 let mut new_keyed = BTreeMap::new();
506
507 for item in self.iter() {
511 let key = key_fn(item);
512 old_keyed.insert(key, (item.0.clone(), item.1.clone()));
513 }
514
515 for item in new {
519 let key = key_fn((&item.0, &item.1));
520 new_keyed.insert(key, item);
521 }
522
523 let mut new = BTreeMap::new();
524
525 for old_key in old_keyed.keys() {
527 if !new_keyed.contains_key(old_key) {
528 has_changed = true;
529 }
530 }
531
532 for (key, new_value) in new_keyed {
538 let old_at_key = old_keyed.remove(&key);
539
540 match old_at_key {
541 None => {
542 new.insert(new_value.0, new_value.1);
544
545 has_changed = true;
547 }
548 Some(mut old_value) => {
550 if let Some(path) = path_at_key(&key) {
554 old_value.1.patch_field(
555 new_value.1,
556 &path,
557 notify,
558 keys,
559 );
560 } else {
561 has_changed = true;
562 }
563
564 new.insert(new_value.0, old_value.1);
566 }
567 }
568 }
569
570 *self = new;
572
573 has_changed
574 }
575}
576
577macro_rules! patch_tuple {
578 ($($ty:ident),*) => {
579 impl<$($ty),*> PatchField for ($($ty,)*)
580 where
581 $($ty: PatchField),*,
582 {
583 fn patch_field(
584 &mut self,
585 new: Self,
586 path: &StorePath,
587 notify: &mut dyn FnMut(&StorePath),
588 keys: Option<&KeyMap>
589 ) {
590 let mut idx = 0;
591 let mut new_path = path.to_owned();
592 new_path.push(0);
593
594 paste::paste! {
595 #[allow(non_snake_case)]
596 let ($($ty,)*) = self;
597 let ($([<new_ $ty:lower>],)*) = new;
598 $(
599 $ty.patch_field([<new_ $ty:lower>], &new_path, notify, keys);
600 idx += 1;
601 new_path.replace_last(idx);
602 )*
603 }
604 }
605 }
606 }
607}
608
609impl PatchField for () {
610 fn patch_field(
611 &mut self,
612 _new: Self,
613 _path: &StorePath,
614 _notify: &mut dyn FnMut(&StorePath),
615 _keys: Option<&KeyMap>,
616 ) {
617 }
618}
619
620patch_tuple!(A);
621patch_tuple!(A, B);
622patch_tuple!(A, B, C);
623patch_tuple!(A, B, C, D);
624patch_tuple!(A, B, C, D, E);
625patch_tuple!(A, B, C, D, E, F);
626patch_tuple!(A, B, C, D, E, F, G);
627patch_tuple!(A, B, C, D, E, F, G, H);
628patch_tuple!(A, B, C, D, E, F, G, H, I);
629patch_tuple!(A, B, C, D, E, F, G, H, I, J);
630patch_tuple!(A, B, C, D, E, F, G, H, I, J, K);
631patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L);
632patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M);
633patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N);
634patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
635patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
636patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q);
637patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R);
638patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S);
639patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T);
640patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
641patch_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V);
642patch_tuple!(
643 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W
644);
645patch_tuple!(
646 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X
647);
648patch_tuple!(
649 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
650);
651patch_tuple!(
652 A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y,
653 Z
654);