Skip to main content

ferroui_dynamic_data/cache/internal/
cache_updater.rs

1//! `CacheUpdater<TObject, TKey>` (`Cache/Internal/CacheUpdater.cs`).
2//!
3//! The updater reaches the cache it edits through a [`RefCell`] that each of its methods borrows
4//! for that method only: an edit that starts another edit of the same cache from inside its
5//! function (a nested edit, `ReaderWriter.WriteNested`) edits the same cache, as upstream's does.
6
7use crate::cache::{ChangeSet, ICache, ICacheUpdater, IQuery, ISourceUpdater};
8use std::cell::RefCell;
9use std::rc::Rc;
10
11/// The key selector of a cache (`Func<TObject, TKey>`).
12pub type KeySelector<T, K> = Rc<dyn Fn(&T) -> K>;
13
14/// The edit of a cache (`CacheUpdater<TObject, TKey>`).
15pub(crate) struct CacheUpdater<'a, T, K> {
16    cache: &'a RefCell<dyn ICache<T, K>>,
17    key_selector: Option<&'a KeySelector<T, K>>,
18}
19
20impl<'a, T, K> CacheUpdater<'a, T, K> {
21    pub(crate) fn new(cache: &'a RefCell<dyn ICache<T, K>>, key_selector: Option<&'a KeySelector<T, K>>) -> Self {
22        Self { cache, key_selector }
23    }
24
25    fn key_of(&self, item: &T) -> K {
26        match self.key_selector {
27            Some(selector) => selector(item),
28            None => panic!("A key selector must be specified"),
29        }
30    }
31
32    fn with<R>(&self, action: impl FnOnce(&mut dyn ICache<T, K>) -> R) -> R {
33        action(&mut *self.cache.borrow_mut())
34    }
35}
36
37impl<T, K> IQuery<T, K> for CacheUpdater<'_, T, K> {
38    fn count(&self) -> usize {
39        self.cache.borrow().count()
40    }
41
42    fn items(&self) -> Vec<T> {
43        self.cache.borrow().items()
44    }
45
46    fn keys(&self) -> Vec<K> {
47        self.cache.borrow().keys()
48    }
49
50    fn key_values(&self) -> Vec<(K, T)> {
51        self.cache.borrow().key_values()
52    }
53
54    fn lookup(&self, key: &K) -> Option<T> {
55        self.cache.borrow().lookup(key)
56    }
57}
58
59impl<T, K> ICacheUpdater<T, K> for CacheUpdater<'_, T, K> {
60    fn add_or_update_pairs(&mut self, pairs: &mut dyn Iterator<Item = (K, T)>) {
61        for (key, item) in pairs {
62            self.with(|cache| cache.add_or_update(item, key));
63        }
64    }
65
66    fn add_or_update_with_key(&mut self, item: T, key: K) {
67        self.with(|cache| cache.add_or_update(item, key));
68    }
69
70    fn clear(&mut self) {
71        self.with(|cache| cache.clear());
72    }
73
74    fn clone_changes(&mut self, changes: &ChangeSet<T, K>) {
75        self.with(|cache| cache.clone_changes(changes));
76    }
77
78    fn get_key(&self, item: &T) -> K {
79        self.key_of(item)
80    }
81
82    fn get_key_values(&self, items: &mut dyn Iterator<Item = T>) -> Vec<(K, T)> {
83        items.map(|item| (self.key_of(&item), item)).collect()
84    }
85
86    fn refresh_all(&mut self) {
87        self.with(|cache| cache.refresh_all());
88    }
89
90    fn refresh_keys(&mut self, keys: &mut dyn Iterator<Item = K>) {
91        for key in keys {
92            self.with(|cache| cache.refresh(&key));
93        }
94    }
95
96    fn refresh_key(&mut self, key: &K) {
97        self.with(|cache| cache.refresh(key));
98    }
99
100    fn remove_keys(&mut self, keys: &mut dyn Iterator<Item = K>) {
101        for key in keys {
102            self.with(|cache| cache.remove(&key));
103        }
104    }
105
106    fn remove_key(&mut self, key: &K) {
107        self.with(|cache| cache.remove(key));
108    }
109
110    fn remove_pairs(&mut self, pairs: &mut dyn Iterator<Item = (K, T)>) {
111        for (key, _) in pairs {
112            self.with(|cache| cache.remove(&key));
113        }
114    }
115}
116
117impl<T, K> ISourceUpdater<T, K> for CacheUpdater<'_, T, K> {
118    fn add_or_update_items(&mut self, items: &mut dyn Iterator<Item = T>) {
119        for item in items {
120            self.add_or_update(item);
121        }
122    }
123
124    fn add_or_update_items_with(&mut self, items: &mut dyn Iterator<Item = T>, comparer: &dyn Fn(&T, &T) -> bool) {
125        for item in items {
126            self.add_or_update_with(item, comparer);
127        }
128    }
129
130    fn add_or_update(&mut self, item: T) {
131        let key = self.key_of(&item);
132        self.with(|cache| cache.add_or_update(item, key));
133    }
134
135    fn add_or_update_with(&mut self, item: T, comparer: &dyn Fn(&T, &T) -> bool) {
136        let key = self.key_of(&item);
137        let old = self.cache.borrow().lookup(&key);
138        if let Some(old) = old {
139            if comparer(&old, &item) {
140                return;
141            }
142        }
143        self.with(|cache| cache.add_or_update(item, key));
144    }
145
146    fn load(&mut self, items: &mut dyn Iterator<Item = T>) {
147        self.with(|cache| cache.clear());
148        self.add_or_update_items(items);
149    }
150
151    fn lookup_item(&self, item: &T) -> Option<T> {
152        let key = self.key_of(item);
153        self.cache.borrow().lookup(&key)
154    }
155
156    fn refresh_items(&mut self, items: &mut dyn Iterator<Item = T>) {
157        for item in items {
158            self.refresh_item(&item);
159        }
160    }
161
162    fn refresh_item(&mut self, item: &T) {
163        let key = self.key_of(item);
164        self.with(|cache| cache.refresh(&key));
165    }
166
167    fn remove_items(&mut self, items: &mut dyn Iterator<Item = T>) {
168        for item in items {
169            self.remove_item(&item);
170        }
171    }
172
173    fn remove_item(&mut self, item: &T) {
174        let key = self.key_of(item);
175        self.with(|cache| cache.remove(&key));
176    }
177}