ferroui_dynamic_data/cache/ops/
combine.rs1use crate::cache::internal::{combiner, dynamic_combiner, CombineOperator, SameReference};
26use crate::cache::{ChangeSet, IConnectableCache, IObservableCache, ISourceCache, ObservableCache, SourceCache};
27use crate::list::{IObservableList, ObservableList, SourceList};
28use ferroui_system::IObservable;
29use std::hash::Hash;
30use std::ops::Deref;
31use std::rc::Rc;
32
33pub(crate) fn same_reference<T: Deref + 'static>() -> SameReference<T> {
35 Rc::new(|a: &T, b: &T| std::ptr::addr_eq(Deref::deref(a) as *const T::Target, Deref::deref(b) as *const T::Target))
36}
37
38pub(crate) fn combine_with_others<T: Clone + Deref + 'static, K: Eq + Hash + Clone + 'static>(
41 source: Rc<dyn IObservable<ChangeSet<T, K>>>,
42 kind: CombineOperator,
43 others: Vec<Rc<dyn IObservable<ChangeSet<T, K>>>>,
44) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
45 let mut sources = Vec::with_capacity(others.len() + 1);
46 sources.push(source);
47 sources.extend(others);
48 combiner(sources, kind, same_reference())
49}
50
51pub trait CacheChangeSetSource: 'static {
54 type Item: Clone + 'static;
56 type Key: Eq + Hash + Clone + 'static;
58
59 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>;
61}
62
63impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> CacheChangeSetSource for Rc<dyn IObservable<ChangeSet<T, K>>> {
64 type Item = T;
65 type Key = K;
66
67 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
68 self.clone()
69 }
70}
71
72impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> CacheChangeSetSource for SourceCache<T, K> {
73 type Item = T;
74 type Key = K;
75
76 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
77 self.connect()
78 }
79}
80
81impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> CacheChangeSetSource for ObservableCache<T, K> {
82 type Item = T;
83 type Key = K;
84
85 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
86 self.connect()
87 }
88}
89
90impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> CacheChangeSetSource for Rc<dyn IObservableCache<T, K>> {
91 type Item = T;
92 type Key = K;
93
94 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
95 self.connect()
96 }
97}
98
99impl<T: Clone + 'static, K: Eq + Hash + Clone + 'static> CacheChangeSetSource for Rc<dyn ISourceCache<T, K>> {
100 type Item = T;
101 type Key = K;
102
103 fn source_change_sets(&self) -> Rc<dyn IObservable<ChangeSet<T, K>>> {
104 self.connect()
105 }
106}
107
108impl<T, K> PartialEq for dyn IObservableCache<T, K> {
110 fn eq(&self, other: &Self) -> bool {
111 std::ptr::addr_eq(self as *const Self, other as *const Self)
112 }
113}
114
115impl<T, K> PartialEq for dyn ISourceCache<T, K> {
117 fn eq(&self, other: &Self) -> bool {
118 std::ptr::addr_eq(self as *const Self, other as *const Self)
119 }
120}
121
122pub trait CacheSourcesCombineEx {
126 type Item: Clone + 'static;
128 type Key: Eq + Hash + Clone + 'static;
130
131 fn and_cache(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
133 where
134 Self::Item: Deref;
135
136 fn or(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
138 where
139 Self::Item: Deref;
140
141 fn xor(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
143 where
144 Self::Item: Deref;
145
146 fn except(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
148 where
149 Self::Item: Deref;
150}
151
152fn combine_collection<S: CacheChangeSetSource>(sources: &[S], kind: CombineOperator) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
154where
155 S::Item: Deref,
156{
157 combiner(sources.iter().map(CacheChangeSetSource::source_change_sets).collect(), kind, same_reference())
158}
159
160impl<S: CacheChangeSetSource> CacheSourcesCombineEx for [S] {
161 type Item = S::Item;
162 type Key = S::Key;
163
164 fn and_cache(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
165 where
166 Self::Item: Deref,
167 {
168 combine_collection(self, CombineOperator::And)
169 }
170
171 fn or(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
172 where
173 Self::Item: Deref,
174 {
175 combine_collection(self, CombineOperator::Or)
176 }
177
178 fn xor(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
179 where
180 Self::Item: Deref,
181 {
182 combine_collection(self, CombineOperator::Xor)
183 }
184
185 fn except(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
186 where
187 Self::Item: Deref,
188 {
189 combine_collection(self, CombineOperator::Except)
190 }
191}
192
193pub trait CacheSourceListCombineEx {
199 type Item: Clone + 'static;
201 type Key: Eq + Hash + Clone + 'static;
203
204 fn and_cache(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
207 where
208 Self::Item: Deref;
209
210 fn or(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
212 where
213 Self::Item: Deref;
214
215 fn xor(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
217 where
218 Self::Item: Deref;
219
220 fn except(&self) -> Rc<dyn IObservable<ChangeSet<Self::Item, Self::Key>>>
223 where
224 Self::Item: Deref;
225}
226
227fn combine_list<S: CacheChangeSetSource + Clone + PartialEq>(list: &dyn IObservableList<S>, kind: CombineOperator) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
229where
230 S::Item: Deref,
231{
232 dynamic_combiner(list.connect(), Rc::new(|source: &S| source.source_change_sets()), kind, same_reference())
233}
234
235macro_rules! cache_source_list_combine_impl {
237 ($list:ident) => {
238 impl<S: CacheChangeSetSource + Clone + PartialEq> CacheSourceListCombineEx for $list<S> {
239 type Item = S::Item;
240 type Key = S::Key;
241
242 fn and_cache(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
243 where
244 Self::Item: Deref,
245 {
246 combine_list(self, CombineOperator::And)
247 }
248
249 fn or(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
250 where
251 Self::Item: Deref,
252 {
253 combine_list(self, CombineOperator::Or)
254 }
255
256 fn xor(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
257 where
258 Self::Item: Deref,
259 {
260 combine_list(self, CombineOperator::Xor)
261 }
262
263 fn except(&self) -> Rc<dyn IObservable<ChangeSet<S::Item, S::Key>>>
264 where
265 Self::Item: Deref,
266 {
267 combine_list(self, CombineOperator::Except)
268 }
269 }
270 };
271}
272
273cache_source_list_combine_impl!(SourceList);
274cache_source_list_combine_impl!(ObservableList);