ferroui_dynamic_data/cache/
change_aware_cache.rs1use super::{Change, ChangeReason, ChangeSet, ICache, IQuery};
4use ferroui_system::collections::generic::Dictionary;
5use std::hash::Hash;
6
7pub struct ChangeAwareCache<T, K> {
10 data: Dictionary<K, T>,
11 changes: Vec<Change<T, K>>,
12}
13
14impl<T: Clone, K: Eq + Hash + Clone> Default for ChangeAwareCache<T, K> {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl<T: Clone, K: Eq + Hash + Clone> ChangeAwareCache<T, K> {
21 pub fn new() -> Self {
23 Self { data: Dictionary::new(), changes: Vec::new() }
24 }
25
26 pub fn with_capacity(capacity: usize) -> Self {
28 Self { data: Dictionary::with_capacity(capacity), changes: Vec::with_capacity(capacity) }
29 }
30
31 pub fn from_dictionary(data: Dictionary<K, T>) -> Self {
34 Self { data, changes: Vec::new() }
35 }
36
37 pub fn dictionary(&self) -> &Dictionary<K, T> {
39 &self.data
40 }
41
42 pub fn into_dictionary(self) -> Dictionary<K, T> {
44 self.data
45 }
46
47 pub fn add(&mut self, item: T, key: K) {
52 self.changes.push(Change::new(ChangeReason::Add, key.clone(), item.clone()));
53 self.data.add(key, item);
54 }
55
56 pub fn capture_changes(&mut self) -> ChangeSet<T, K> {
58 if self.changes.is_empty() {
59 return ChangeSet::empty();
60 }
61 ChangeSet::from(std::mem::take(&mut self.changes))
62 }
63
64 pub fn has_changes(&self) -> bool {
66 !self.changes.is_empty()
67 }
68}
69
70impl<T: Clone, K: Eq + Hash + Clone> IQuery<T, K> for ChangeAwareCache<T, K> {
71 fn count(&self) -> usize {
72 self.data.len()
73 }
74
75 fn items(&self) -> Vec<T> {
76 self.data.values().cloned().collect()
77 }
78
79 fn keys(&self) -> Vec<K> {
80 self.data.keys().cloned().collect()
81 }
82
83 fn key_values(&self) -> Vec<(K, T)> {
84 self.data.iter().map(|(key, item)| (key.clone(), item.clone())).collect()
85 }
86
87 fn lookup(&self, key: &K) -> Option<T> {
88 self.data.get(key).cloned()
89 }
90}
91
92impl<T: Clone, K: Eq + Hash + Clone> ICache<T, K> for ChangeAwareCache<T, K> {
93 fn add_or_update(&mut self, item: T, key: K) {
94 let change = match self.data.get(&key) {
95 Some(existing) => Change::update(key.clone(), item.clone(), existing.clone()),
96 None => Change::new(ChangeReason::Add, key.clone(), item.clone()),
97 };
98 self.changes.push(change);
99 self.data.insert(key, item);
100 }
101
102 fn clear(&mut self) {
103 let removed = self.data.iter().map(|(key, item)| Change::new(ChangeReason::Remove, key.clone(), item.clone()));
104 self.changes.extend(removed);
105 self.data.clear();
106 }
107
108 fn clone_changes(&mut self, changes: &ChangeSet<T, K>) {
109 for change in changes {
110 match change.reason() {
111 ChangeReason::Add | ChangeReason::Update => self.add_or_update(change.current().clone(), change.key().clone()),
112 ChangeReason::Remove => self.remove(change.key()),
113 ChangeReason::Refresh => self.refresh(change.key()),
114 ChangeReason::Moved => {}
115 }
116 }
117 }
118
119 fn refresh_all(&mut self) {
120 let refreshed = self.data.iter().map(|(key, item)| Change::new(ChangeReason::Refresh, key.clone(), item.clone()));
121 self.changes.extend(refreshed);
122 }
123
124 fn refresh_keys(&mut self, keys: &mut dyn Iterator<Item = K>) {
125 for key in keys {
126 self.refresh(&key);
127 }
128 }
129
130 fn refresh(&mut self, key: &K) {
131 if let Some(existing) = self.data.get(key) {
132 self.changes.push(Change::new(ChangeReason::Refresh, key.clone(), existing.clone()));
133 }
134 }
135
136 fn remove(&mut self, key: &K) {
137 if let Some(existing) = self.data.remove(key) {
138 self.changes.push(Change::new(ChangeReason::Remove, key.clone(), existing));
139 }
140 }
141
142 fn remove_keys(&mut self, keys: &mut dyn Iterator<Item = K>) {
143 for key in keys {
144 self.remove(&key);
145 }
146 }
147}