Skip to main content

ferroui_dynamic_data/cache/
change_set.rs

1//! `ChangeSet<TObject, TKey>` and `IChangeSet<TObject, TKey>` (`Cache/ChangeSet.cs`,
2//! `Cache/IChangeSet.cs`, `IChangeSet.cs`).
3
4use super::{Change, ChangeReason};
5use std::fmt;
6use std::ops::Deref;
7use std::rc::Rc;
8
9/// The changes of one edit of a cache (`ChangeSet<TObject, TKey>`): a shared, immutable list,
10/// which every observer of a sequence receives as it is (docs/porting/reactive.md, section 5.4).
11pub struct ChangeSet<T, K> {
12    changes: Rc<Vec<Change<T, K>>>,
13}
14
15impl<T, K> Clone for ChangeSet<T, K> {
16    fn clone(&self) -> Self {
17        Self { changes: self.changes.clone() }
18    }
19}
20
21impl<T, K> Default for ChangeSet<T, K> {
22    fn default() -> Self {
23        Self::empty()
24    }
25}
26
27impl<T, K> ChangeSet<T, K> {
28    /// A change set without changes (`ChangeSet<TObject, TKey>.Empty`).
29    pub fn empty() -> Self {
30        Self { changes: Rc::new(Vec::new()) }
31    }
32
33    /// The changes, in order.
34    pub fn changes(&self) -> &[Change<T, K>] {
35        &self.changes
36    }
37
38    /// The number of changes (`Count`).
39    pub fn count(&self) -> usize {
40        self.changes.len()
41    }
42
43    fn count_of(&self, reason: ChangeReason) -> usize {
44        self.changes.iter().filter(|change| change.reason() == reason).count()
45    }
46
47    /// The number of additions (`Adds`).
48    pub fn adds(&self) -> usize {
49        self.count_of(ChangeReason::Add)
50    }
51
52    /// The number of updates (`Updates`).
53    pub fn updates(&self) -> usize {
54        self.count_of(ChangeReason::Update)
55    }
56
57    /// The number of removals (`Removes`).
58    pub fn removes(&self) -> usize {
59        self.count_of(ChangeReason::Remove)
60    }
61
62    /// The number of refreshes (`Refreshes`).
63    pub fn refreshes(&self) -> usize {
64        self.count_of(ChangeReason::Refresh)
65    }
66
67    /// The number of moves (`Moves`).
68    pub fn moves(&self) -> usize {
69        self.count_of(ChangeReason::Moved)
70    }
71
72    /// The changes as a list of their own, to build on.
73    pub fn to_vec(&self) -> Vec<Change<T, K>>
74    where
75        T: Clone,
76        K: Clone,
77    {
78        self.changes.as_ref().clone()
79    }
80
81    /// Whether `self` and `other` are the same change set (`ReferenceEquals`).
82    pub fn ptr_eq(&self, other: &Self) -> bool {
83        Rc::ptr_eq(&self.changes, &other.changes)
84    }
85}
86
87impl<T, K> From<Vec<Change<T, K>>> for ChangeSet<T, K> {
88    /// A change set of the changes (`new ChangeSet<TObject, TKey>(IEnumerable<Change>)`).
89    fn from(changes: Vec<Change<T, K>>) -> Self {
90        Self { changes: Rc::new(changes) }
91    }
92}
93
94impl<T, K> FromIterator<Change<T, K>> for ChangeSet<T, K> {
95    fn from_iter<I: IntoIterator<Item = Change<T, K>>>(iter: I) -> Self {
96        Self::from(iter.into_iter().collect::<Vec<_>>())
97    }
98}
99
100impl<T, K> Deref for ChangeSet<T, K> {
101    type Target = [Change<T, K>];
102
103    fn deref(&self) -> &Self::Target {
104        &self.changes
105    }
106}
107
108impl<'a, T, K> IntoIterator for &'a ChangeSet<T, K> {
109    type Item = &'a Change<T, K>;
110    type IntoIter = std::slice::Iter<'a, Change<T, K>>;
111
112    fn into_iter(self) -> Self::IntoIter {
113        self.changes.iter()
114    }
115}
116
117impl<T: PartialEq, K: PartialEq> PartialEq for ChangeSet<T, K> {
118    fn eq(&self, other: &Self) -> bool {
119        self.changes == other.changes
120    }
121}
122
123impl<T: fmt::Debug, K: fmt::Debug> fmt::Debug for ChangeSet<T, K> {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        f.debug_list().entries(self.changes.iter()).finish()
126    }
127}
128
129/// A change set of a cache, of any form (`IChangeSet<TObject, TKey>`): the plain one, and the
130/// sorted, paged, virtual and contextual ones, which hold a plain one with more parts. The
131/// operators of caches take any of them, as upstream's take its interface
132/// (docs/porting/reactive.md, section 5.4).
133pub trait IChangeSet<T, K>: Clone + 'static {
134    /// The changes.
135    fn change_set(&self) -> &ChangeSet<T, K>;
136}
137
138impl<T: 'static, K: 'static> IChangeSet<T, K> for ChangeSet<T, K> {
139    fn change_set(&self) -> &ChangeSet<T, K> {
140        self
141    }
142}