Skip to main content

ferroui_dynamic_data/cache/internal/
immutable_group.rs

1//! `ImmutableGroup<TObject, TKey, TGroupKey>` (`Cache/Internal/ImmutableGroup.cs`).
2
3use super::Cache;
4use crate::cache::{ICache, IGrouping, IQuery};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::rc::Rc;
8
9struct Inner<T, K, G> {
10    key: G,
11    cache: Cache<T, K>,
12}
13
14/// The state of a group at one moment (`ImmutableGroup<TObject, TKey, TGroupKey>`, the
15/// `IGrouping` of the change sets of `GroupWithImmutableState`): a copy of its items that does not
16/// change. A clone is the same state.
17///
18/// Deviation (DEVIATIONS.md, DynamicData): upstream's class is internal and its change sets hold
19/// the interface `IGrouping`; here they hold this type, so it is public.
20pub struct ImmutableGroup<T, K, G> {
21    inner: Rc<Inner<T, K, G>>,
22}
23
24impl<T, K, G> Clone for ImmutableGroup<T, K, G> {
25    fn clone(&self) -> Self {
26        Self { inner: self.inner.clone() }
27    }
28}
29
30impl<T: Clone, K: Eq + Hash + Clone, G> ImmutableGroup<T, K, G> {
31    /// The state of the group `key` with a copy of the items of `cache` (`ImmutableGroup(TGroupKey,
32    /// ICache<TObject, TKey>)`).
33    pub(crate) fn new(key: G, cache: &dyn IQuery<T, K>) -> Self {
34        let mut copy = Cache::with_capacity(cache.count());
35        for (item_key, item) in cache.key_values() {
36            copy.add_or_update(item, item_key);
37        }
38        Self { inner: Rc::new(Inner { key, cache: copy }) }
39    }
40
41    /// Whether `self` and `other` are the same state (`ReferenceEquals`).
42    pub fn ptr_eq(&self, other: &Self) -> bool {
43        Rc::ptr_eq(&self.inner, &other.inner)
44    }
45}
46
47impl<T: Clone, K: Eq + Hash + Clone, G> IGrouping<T, K, G> for ImmutableGroup<T, K, G> {
48    fn count(&self) -> usize {
49        self.inner.cache.count()
50    }
51
52    fn items(&self) -> Vec<T> {
53        self.inner.cache.items()
54    }
55
56    fn key(&self) -> &G {
57        &self.inner.key
58    }
59
60    fn keys(&self) -> Vec<K> {
61        self.inner.cache.keys()
62    }
63
64    fn key_values(&self) -> Vec<(K, T)> {
65        self.inner.cache.key_values()
66    }
67
68    fn lookup(&self, key: &K) -> Option<T> {
69        self.inner.cache.lookup(key)
70    }
71}
72
73impl<T, K, G: PartialEq> PartialEq for ImmutableGroup<T, K, G> {
74    /// States of the same group key are equal (`Equals`).
75    fn eq(&self, other: &Self) -> bool {
76        Rc::ptr_eq(&self.inner, &other.inner) || self.inner.key == other.inner.key
77    }
78}
79
80impl<T, K, G: Eq> Eq for ImmutableGroup<T, K, G> {}
81
82impl<T, K, G: Hash> Hash for ImmutableGroup<T, K, G> {
83    /// The hash of the group key (`GetHashCode`).
84    fn hash<H: Hasher>(&self, state: &mut H) {
85        self.inner.key.hash(state);
86    }
87}
88
89impl<T: Clone, K: Eq + std::hash::Hash + Clone, G: fmt::Display> fmt::Display for ImmutableGroup<T, K, G> {
90    /// `ToString`: `Grouping for: {Key} ({Count} items)`.
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        write!(f, "Grouping for: {} ({} items)", self.inner.key, self.inner.cache.dictionary().len())
93    }
94}
95
96impl<T: Clone, K: Eq + std::hash::Hash + Clone, G: fmt::Debug> fmt::Debug for ImmutableGroup<T, K, G> {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        write!(f, "Grouping for: {:?} ({} items)", self.inner.key, self.inner.cache.dictionary().len())
99    }
100}