Skip to main content

ferroui_dynamic_data/cache/internal/
managed_group.rs

1//! `ManagedGroup<TObject, TKey, TGroupKey>` (`Cache/Internal/ManagedGroup.cs`).
2
3use crate::cache::{ChangeSet, ICacheUpdater, IGroup, IObservableCache, ObservableCache};
4use ferroui_system::IDisposable;
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::rc::Rc;
8
9struct Inner<T, K, G> {
10    key: G,
11    cache: ObservableCache<T, K>,
12}
13
14/// A group of the items of a cache that share a group key (`ManagedGroup<TObject, TKey,
15/// TGroupKey>`, the `IGroup` of the change sets of `Group`): the grouping operators edit its cache,
16/// and its observers watch it. A clone is the same group.
17///
18/// Deviation (DEVIATIONS.md, DynamicData): upstream's class is internal and its change sets hold
19/// the interface `IGroup`; here the change sets hold this type, so it is public, as `Group`.
20pub struct Group<T, K, G> {
21    inner: Rc<Inner<T, K, G>>,
22}
23
24impl<T, K, G> Clone for Group<T, K, G> {
25    fn clone(&self) -> Self {
26        Self { inner: self.inner.clone() }
27    }
28}
29
30impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static, G> Group<T, K, G> {
31    /// An empty group of `key` (`ManagedGroup(TGroupKey)`), whose cache gives the keys with its
32    /// items (`IntermediateCache`).
33    pub(crate) fn new(key: G) -> Self {
34        Self { inner: Rc::new(Inner { key, cache: ObservableCache::without_key_selector() }) }
35    }
36
37    /// The group key (`Key`).
38    pub fn key(&self) -> &G {
39        &self.inner.key
40    }
41
42    /// The items of the group (`Cache`).
43    pub fn cache(&self) -> Rc<dyn IObservableCache<T, K>> {
44        Rc::new(self.inner.cache.clone())
45    }
46
47    /// The cache of the group, as its concrete type.
48    pub(crate) fn observable_cache(&self) -> &ObservableCache<T, K> {
49        &self.inner.cache
50    }
51
52    /// The number of items (`Count`).
53    pub(crate) fn count(&self) -> usize {
54        self.inner.cache.count()
55    }
56
57    /// Holds back the notifications of the cache of the group until the result is disposed
58    /// (`SuspendNotifications`).
59    pub(crate) fn suspend_notifications(&self) -> Rc<dyn IDisposable> {
60        self.inner.cache.suspend_notifications()
61    }
62
63    /// The items of the group as additions (`GetInitialUpdates`).
64    pub(crate) fn get_initial_updates(&self) -> ChangeSet<T, K> {
65        self.inner.cache.get_initial_updates(None)
66    }
67
68    /// Edits the cache of the group (`Update`, `IntermediateCache.Edit`).
69    pub(crate) fn update(&self, update_action: impl FnOnce(&mut dyn ICacheUpdater<T, K>)) {
70        self.inner.cache.update_from_intermediate(update_action);
71    }
72
73    /// Whether `self` and `other` are the same group (`ReferenceEquals`).
74    pub fn ptr_eq(&self, other: &Self) -> bool {
75        Rc::ptr_eq(&self.inner, &other.inner)
76    }
77}
78
79impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static, G> IGroup<T, K, G> for Group<T, K, G> {
80    fn key(&self) -> &G {
81        &self.inner.key
82    }
83
84    fn cache(&self) -> Rc<dyn IObservableCache<T, K>> {
85        Rc::new(self.inner.cache.clone())
86    }
87}
88
89impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static, G> IDisposable for Group<T, K, G> {
90    /// Ends the cache of the group, which completes its observers (`Dispose`).
91    fn dispose(&self) {
92        self.inner.cache.dispose();
93    }
94}
95
96impl<T, K, G: PartialEq> PartialEq for Group<T, K, G> {
97    /// Groups of the same key are equal (`Equals`).
98    fn eq(&self, other: &Self) -> bool {
99        Rc::ptr_eq(&self.inner, &other.inner) || self.inner.key == other.inner.key
100    }
101}
102
103impl<T, K, G: Eq> Eq for Group<T, K, G> {}
104
105impl<T, K, G: Hash> Hash for Group<T, K, G> {
106    /// The hash of the group key (`GetHashCode`).
107    fn hash<H: Hasher>(&self, state: &mut H) {
108        self.inner.key.hash(state);
109    }
110}
111
112impl<T, K, G: fmt::Display> fmt::Display for Group<T, K, G> {
113    /// `ToString`: `Group: {Key}`.
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(f, "Group: {}", self.inner.key)
116    }
117}
118
119impl<T, K, G: fmt::Debug> fmt::Debug for Group<T, K, G> {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        write!(f, "Group: {:?}", self.inner.key)
122    }
123}