Skip to main content

ferroui_dynamic_data/list/ops/
merge_change_sets.rs

1//! `MergeChangeSets` (`List/ObservableListEx.MergeChangeSets.cs`): the change sets of several lists
2//! merged into those of one.
3//!
4//! As for caches, the kinds of sources are traits of their own: a sequence with another one or
5//! others (provided methods of [`ObservableListEx`](crate::list::ObservableListEx)), an enumerable
6//! of sequences ([`ListChangeSetSourcesEx`]) and a sequence of sequences
7//! ([`ObservableListChangeSetsEx`]). The default equality of the items, which the copies of the
8//! lists use, is `PartialEq`.
9//!
10//! Not ported: the forms on an `IObservableList` of sequences and on a sequence of change sets of
11//! sequences (`IObservableList<IObservable<IChangeSet>>`, `IObservable<IChangeSet<IObservable<
12//! IChangeSet>>>`): the items of a list are compared, and a sequence has no equality.
13
14use crate::list::internal::merge_change_sets;
15use crate::list::ChangeSet;
16use ferroui_reactive::concurrency::IScheduler;
17use ferroui_system::IObservable;
18use std::rc::Rc;
19
20macro_rules! merge_change_sets_methods {
21    () => {
22        /// The change sets of the sequence and of `other`, merged; it completes when both have
23        /// completed (`MergeChangeSets(IObservable<IChangeSet<TObject>>, IObservable<IChangeSet<
24        /// TObject>>, IEqualityComparer<TObject>? = null, IScheduler? = null, bool completable =
25        /// true)`).
26        fn merge_change_sets(
27            &self,
28            other: std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>>,
29        ) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>> {
30            crate::list::ops::merge_change_sets::merge_sources(vec![self.change_sets(), other], None, None, true)
31        }
32
33        /// [`merge_change_sets`](Self::merge_change_sets) with every argument: the equality of the
34        /// items (`PartialEq` when `None`), the scheduler that enumerates the two sequences, and
35        /// whether the merge completes after them.
36        fn merge_change_sets_with(
37            &self,
38            other: std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>>,
39            equality_comparer: Option<std::rc::Rc<dyn Fn(&T, &T) -> bool>>,
40            scheduler: Option<std::rc::Rc<dyn ferroui_reactive::concurrency::IScheduler>>,
41            completable: bool,
42        ) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>> {
43            crate::list::ops::merge_change_sets::merge_sources(vec![self.change_sets(), other], equality_comparer, scheduler, completable)
44        }
45
46        /// The change sets of the sequence and of `others`, merged
47        /// (`MergeChangeSets(IObservable<IChangeSet<TObject>>, IEnumerable<IObservable<IChangeSet<
48        /// TObject>>>, ..)`).
49        fn merge_change_sets_many(
50            &self,
51            others: Vec<std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>>>,
52        ) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>> {
53            let mut sources = vec![self.change_sets()];
54            sources.extend(others);
55            crate::list::ops::merge_change_sets::merge_sources(sources, None, None, true)
56        }
57
58        /// [`merge_change_sets_many`](Self::merge_change_sets_many) with every argument.
59        fn merge_change_sets_many_with(
60            &self,
61            others: Vec<std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>>>,
62            equality_comparer: Option<std::rc::Rc<dyn Fn(&T, &T) -> bool>>,
63            scheduler: Option<std::rc::Rc<dyn ferroui_reactive::concurrency::IScheduler>>,
64            completable: bool,
65        ) -> std::rc::Rc<dyn ferroui_system::IObservable<crate::list::ChangeSet<T>>> {
66            let mut sources = vec![self.change_sets()];
67            sources.extend(others);
68            crate::list::ops::merge_change_sets::merge_sources(sources, equality_comparer, scheduler, completable)
69        }
70    };
71}
72pub(crate) use merge_change_sets_methods;
73
74/// The merge of an enumerable of sequences (`new MergeChangeSets(IEnumerable<..>, ..)`).
75pub(crate) fn merge_sources<T: Clone + PartialEq + 'static>(
76    sources: Vec<Rc<dyn IObservable<ChangeSet<T>>>>,
77    equality_comparer: Option<Rc<dyn Fn(&T, &T) -> bool>>,
78    scheduler: Option<Rc<dyn IScheduler>>,
79    completable: bool,
80) -> Rc<dyn IObservable<ChangeSet<T>>> {
81    merge_change_sets(
82        crate::cache::internal::sources_observable(sources, completable, scheduler),
83        equality_comparer.unwrap_or_else(crate::cache::internal::default_equality_comparer),
84    )
85}
86
87/// `MergeChangeSets` of an enumerable of sequences of change sets of lists
88/// (`MergeChangeSets(this IEnumerable<IObservable<IChangeSet<TObject>>>, ..)`): the sequences are
89/// enumerated when the merge is subscribed, and the merge completes after them unless
90/// `completable` is false.
91pub trait ListChangeSetSourcesEx<T> {
92    /// The change sets of the sequences, merged (`MergeChangeSets()`).
93    fn merge_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T>>>;
94
95    /// With every argument: the equality of the items (`PartialEq` when `None`), the scheduler that
96    /// enumerates the sequences, and whether the merge completes after them
97    /// (`MergeChangeSets(IEqualityComparer<TObject>?, IScheduler?, bool)`).
98    fn merge_change_sets_with(
99        &self,
100        equality_comparer: Option<Rc<dyn Fn(&T, &T) -> bool>>,
101        scheduler: Option<Rc<dyn IScheduler>>,
102        completable: bool,
103    ) -> Rc<dyn IObservable<ChangeSet<T>>>;
104}
105
106impl<T: Clone + PartialEq + 'static> ListChangeSetSourcesEx<T> for [Rc<dyn IObservable<ChangeSet<T>>>] {
107    fn merge_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T>>> {
108        merge_sources(self.to_vec(), None, None, true)
109    }
110
111    fn merge_change_sets_with(
112        &self,
113        equality_comparer: Option<Rc<dyn Fn(&T, &T) -> bool>>,
114        scheduler: Option<Rc<dyn IScheduler>>,
115        completable: bool,
116    ) -> Rc<dyn IObservable<ChangeSet<T>>> {
117        merge_sources(self.to_vec(), equality_comparer, scheduler, completable)
118    }
119}
120
121/// `MergeChangeSets` of a sequence of sequences of change sets of lists
122/// (`MergeChangeSets(this IObservable<IObservable<IChangeSet<TObject>>>, IEqualityComparer<
123/// TObject>? = null)`).
124pub trait ObservableListChangeSetsEx<T> {
125    /// The change sets of the sequences, merged (`MergeChangeSets()`).
126    fn merge_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T>>>;
127
128    /// With the equality of the items (`MergeChangeSets(IEqualityComparer<TObject>)`).
129    fn merge_change_sets_with_comparer(&self, equality_comparer: impl Fn(&T, &T) -> bool + 'static) -> Rc<dyn IObservable<ChangeSet<T>>>;
130}
131
132impl<T: Clone + PartialEq + 'static> ObservableListChangeSetsEx<T> for Rc<dyn IObservable<Rc<dyn IObservable<ChangeSet<T>>>>> {
133    fn merge_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T>>> {
134        merge_change_sets(self.clone(), crate::cache::internal::default_equality_comparer())
135    }
136
137    fn merge_change_sets_with_comparer(&self, equality_comparer: impl Fn(&T, &T) -> bool + 'static) -> Rc<dyn IObservable<ChangeSet<T>>> {
138        merge_change_sets(self.clone(), Rc::new(equality_comparer))
139    }
140}