Skip to main content

ferroui_dynamic_data/
enumerable_ex.rs

1//! `EnumerableEx` (`EnumerableEx.cs`): a collection as a sequence of change sets.
2
3use ferroui_reactive::disposables::Disposable;
4use ferroui_reactive::Observable;
5use ferroui_system::{IObservable, IObserver};
6use std::hash::Hash;
7use std::rc::Rc;
8
9/// The collection as a sequence of one change set of additions (`EnumerableEx`), implemented for
10/// every collection.
11pub trait EnumerableEx<T: Clone + 'static>: IntoIterator<Item = T> + Sized {
12    /// The items as one change set of additions to a list, at each subscription; the sequence does
13    /// not end (`AsObservableChangeSet<TObject>(IEnumerable<TObject>, bool completable = false)`).
14    fn as_observable_change_set(self) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>> {
15        self.as_observable_change_set_with(false)
16    }
17
18    /// [`as_observable_change_set`](Self::as_observable_change_set) that ends after the change set
19    /// when `completable` is true.
20    fn as_observable_change_set_with(self, completable: bool) -> Rc<dyn IObservable<crate::list::ChangeSet<T>>> {
21        let items: Vec<T> = self.into_iter().collect();
22        Observable::create(move |observer: Rc<dyn IObserver<crate::list::ChangeSet<T>>>| {
23            let changes: Vec<crate::list::Change<T>> = items.iter().map(|item| crate::list::Change::new(crate::list::ListChangeReason::Add, item.clone(), None)).collect();
24            observer.on_next(crate::list::ChangeSet::from(changes));
25            if completable {
26                observer.on_completed();
27            }
28            Disposable::empty()
29        })
30    }
31
32    /// The items as one change set of additions to a cache, keyed by `key_selector`
33    /// (`AsObservableChangeSet<TObject, TKey>(IEnumerable<TObject>, Func<TObject, TKey>, bool
34    /// completable = false)`).
35    fn as_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>>> {
36        self.as_observable_change_set_cache_with(key_selector, false)
37    }
38
39    /// [`as_observable_change_set_cache`](Self::as_observable_change_set_cache) that ends after the
40    /// change set when `completable` is true.
41    fn as_observable_change_set_cache_with<K: Eq + Hash + Clone + 'static>(self, key_selector: impl Fn(&T) -> K + 'static, completable: bool) -> Rc<dyn IObservable<crate::cache::ChangeSet<T, K>>> {
42        let items: Vec<T> = self.into_iter().collect();
43        Observable::create(move |observer: Rc<dyn IObserver<crate::cache::ChangeSet<T, K>>>| {
44            let changes: crate::cache::ChangeSet<T, K> = items.iter().map(|item| crate::cache::Change::new(crate::cache::ChangeReason::Add, key_selector(item), item.clone())).collect();
45            observer.on_next(changes);
46            if completable {
47                observer.on_completed();
48            }
49            Disposable::empty()
50        })
51    }
52}
53
54impl<T: Clone + 'static, I: IntoIterator<Item = T>> EnumerableEx<T> for I {}