Skip to main content

ferroui_dynamic_data/
observable_items_ex.rs

1//! The operators of plain sequences that make change sets: `ToObservableChangeSet`
2//! (`Cache/ObservableCacheEx.ToObservableChangeSet.cs`, `List/ObservableListEx.ToObservableChangeSet.cs`)
3//! and `EditDiff` of a sequence of collections (`Cache/ObservableCacheEx.EditDiff.cs`).
4//!
5//! Upstream's overloads differ by the type of the sequence (`IObservable<T>` or
6//! `IObservable<IEnumerable<T>>`) and by optional arguments. Here a sequence of items has the
7//! methods of [`ObservableItemsEx`], and a sequence of collections those of
8//! [`ObservableSequencesEx`] (the `_many` methods); the cache forms take the suffix `_cache`; the
9//! optional arguments are the `_with` form (`expire_after`, `limit_size_to` of `None` for upstream's
10//! `-1`, and the scheduler), with the default scheduler when `None`.
11
12use ferroui_reactive::concurrency::IScheduler;
13use ferroui_system::IObservable;
14use std::hash::Hash;
15use std::rc::Rc;
16use std::time::Duration;
17
18/// The expiration of an item: the time after which it is removed, `None` for never.
19pub type ExpireAfterSelector<T> = Rc<dyn Fn(&T) -> Option<Duration>>;
20
21/// The operators of sequences of items (`ToObservableChangeSet(IObservable<T>, ..)`), implemented
22/// for `Rc<dyn IObservable<T>>`.
23pub trait ObservableItemsEx<T: Clone + 'static> {
24    /// The sequence as the handle the operators take.
25    fn item_sequence(&self) -> Rc<dyn IObservable<T>>;
26
27    /// The items as additions to a list (`ToObservableChangeSet<T>(IObservable<T>, IScheduler? =
28    /// null)`): the first change set comes at the subscription, empty if need be.
29    fn to_observable_change_set(&self) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
30    where
31        T: PartialEq,
32    {
33        crate::list::internal::to_observable_change_set_of_items(self.item_sequence(), None, None, None)
34    }
35
36    /// [`to_observable_change_set`](Self::to_observable_change_set), whose items expire after the
37    /// time that `expire_after` gives and whose oldest beyond `limit_size_to` are removed, timed on
38    /// `scheduler` (`ToObservableChangeSet<T>(IObservable<T>, Func<T, TimeSpan?>?, int,
39    /// IScheduler?)` and the shorter overloads).
40    fn to_observable_change_set_with(
41        &self,
42        expire_after: Option<ExpireAfterSelector<T>>,
43        limit_size_to: Option<usize>,
44        scheduler: Option<Rc<dyn IScheduler>>,
45    ) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
46    where
47        T: PartialEq,
48    {
49        crate::list::internal::to_observable_change_set_of_items(self.item_sequence(), expire_after, limit_size_to, scheduler)
50    }
51
52    /// The items as additions or updates of a cache, keyed by `key_selector`
53    /// (`ToObservableChangeSet<TObject, TKey>(IObservable<TObject>, Func<TObject, TKey>, ..)`).
54    fn to_observable_change_set_cache<K: Eq + Hash + Clone + 'static>(&self, key_selector: impl Fn(&T) -> K + 'static) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
55        crate::cache::internal::to_observable_change_set_of_items(self.item_sequence(), Rc::new(key_selector), None, None, None)
56    }
57
58    /// [`to_observable_change_set_cache`](Self::to_observable_change_set_cache) with the
59    /// expiration, the limit of size and the scheduler (`ToObservableChangeSet(IObservable<TObject>,
60    /// Func<TObject, TKey>, Func<TObject, TimeSpan?>? = null, int limitSizeTo = -1, IScheduler? =
61    /// null)`).
62    fn to_observable_change_set_cache_with<K: Eq + Hash + Clone + 'static>(
63        &self,
64        key_selector: impl Fn(&T) -> K + 'static,
65        expire_after: Option<ExpireAfterSelector<T>>,
66        limit_size_to: Option<usize>,
67        scheduler: Option<Rc<dyn IScheduler>>,
68    ) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
69        crate::cache::internal::to_observable_change_set_of_items(self.item_sequence(), Rc::new(key_selector), expire_after, limit_size_to, scheduler)
70    }
71}
72
73impl<T: Clone + 'static> ObservableItemsEx<T> for Rc<dyn IObservable<T>> {
74    fn item_sequence(&self) -> Rc<dyn IObservable<T>> {
75        self.clone()
76    }
77}
78
79/// The operators of sequences of collections of items (`ToObservableChangeSet(IObservable<
80/// IEnumerable<T>>, ..)` and `EditDiff(IObservable<IEnumerable<TObject>>, ..)`), implemented for
81/// `Rc<dyn IObservable<I>>` of every collection `I`.
82pub trait ObservableSequencesEx<T: Clone + 'static> {
83    /// The items of each collection as additions to a list (`ToObservableChangeSet<T>(
84    /// IObservable<IEnumerable<T>>, IScheduler? = null)`).
85    fn to_observable_change_set_many(&self) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
86    where
87        T: PartialEq;
88
89    /// [`to_observable_change_set_many`](Self::to_observable_change_set_many) with the expiration,
90    /// the limit of size and the scheduler.
91    fn to_observable_change_set_many_with(
92        &self,
93        expire_after: Option<ExpireAfterSelector<T>>,
94        limit_size_to: Option<usize>,
95        scheduler: Option<Rc<dyn IScheduler>>,
96    ) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
97    where
98        T: PartialEq;
99
100    /// The items of each collection as additions or updates of a cache, keyed by `key_selector`
101    /// (`ToObservableChangeSet<TObject, TKey>(IObservable<IEnumerable<TObject>>, ..)`).
102    fn to_observable_change_set_cache_many<K: Eq + Hash + Clone + 'static>(&self, key_selector: impl Fn(&T) -> K + 'static) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>>;
103
104    /// [`to_observable_change_set_cache_many`](Self::to_observable_change_set_cache_many) with the
105    /// expiration, the limit of size and the scheduler.
106    fn to_observable_change_set_cache_many_with<K: Eq + Hash + Clone + 'static>(
107        &self,
108        key_selector: impl Fn(&T) -> K + 'static,
109        expire_after: Option<ExpireAfterSelector<T>>,
110        limit_size_to: Option<usize>,
111        scheduler: Option<Rc<dyn IScheduler>>,
112    ) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>>;
113
114    /// The changes of a cache, keyed by `key_selector`, that holds the latest collection: each
115    /// collection edits it by difference, items compared by `PartialEq`; the cache ends with the
116    /// sequence (`EditDiff(IObservable<IEnumerable<TObject>>, Func<TObject, TKey>,
117    /// IEqualityComparer? = null)`).
118    fn edit_diff<K: Eq + Hash + Clone + 'static>(&self, key_selector: impl Fn(&T) -> K + 'static) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>>
119    where
120        T: PartialEq;
121
122    /// [`edit_diff`](Self::edit_diff) with the equality of `equality_comparer`.
123    fn edit_diff_with_comparer<K: Eq + Hash + Clone + 'static>(
124        &self,
125        key_selector: impl Fn(&T) -> K + 'static,
126        equality_comparer: impl Fn(&T, &T) -> bool + 'static,
127    ) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>>;
128}
129
130impl<T: Clone + 'static, I: IntoIterator<Item = T> + 'static> ObservableSequencesEx<T> for Rc<dyn IObservable<I>> {
131    fn to_observable_change_set_many(&self) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
132    where
133        T: PartialEq,
134    {
135        crate::list::internal::to_observable_change_set(self.clone(), None, None, None)
136    }
137
138    fn to_observable_change_set_many_with(
139        &self,
140        expire_after: Option<ExpireAfterSelector<T>>,
141        limit_size_to: Option<usize>,
142        scheduler: Option<Rc<dyn IScheduler>>,
143    ) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>>
144    where
145        T: PartialEq,
146    {
147        crate::list::internal::to_observable_change_set(self.clone(), expire_after, limit_size_to, scheduler)
148    }
149
150    fn to_observable_change_set_cache_many<K: Eq + Hash + Clone + 'static>(&self, key_selector: impl Fn(&T) -> K + 'static) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
151        crate::cache::internal::to_observable_change_set(self.clone(), Rc::new(key_selector), None, None, None)
152    }
153
154    fn to_observable_change_set_cache_many_with<K: Eq + Hash + Clone + 'static>(
155        &self,
156        key_selector: impl Fn(&T) -> K + 'static,
157        expire_after: Option<ExpireAfterSelector<T>>,
158        limit_size_to: Option<usize>,
159        scheduler: Option<Rc<dyn IScheduler>>,
160    ) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
161        crate::cache::internal::to_observable_change_set(self.clone(), Rc::new(key_selector), expire_after, limit_size_to, scheduler)
162    }
163
164    fn edit_diff<K: Eq + Hash + Clone + 'static>(&self, key_selector: impl Fn(&T) -> K + 'static) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>>
165    where
166        T: PartialEq,
167    {
168        crate::cache::internal::edit_diff_change_set(self.clone(), Rc::new(key_selector), Rc::new(|a: &T, b: &T| a == b))
169    }
170
171    fn edit_diff_with_comparer<K: Eq + Hash + Clone + 'static>(
172        &self,
173        key_selector: impl Fn(&T) -> K + 'static,
174        equality_comparer: impl Fn(&T, &T) -> bool + 'static,
175    ) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
176        crate::cache::internal::edit_diff_change_set(self.clone(), Rc::new(key_selector), Rc::new(equality_comparer))
177    }
178}