1#![allow(clippy::type_complexity)]
3
4use std::marker::PhantomData;
5
6use incremental::incrsan::NotObserver;
7use incremental::{Incr, Value};
8
9pub mod btree_map;
10#[cfg(feature = "im")]
11pub mod im_rc;
12pub mod symmetric_fold;
13
14pub use self::symmetric_fold::{DiffElement, MergeElement};
15
16pub mod prelude {
17 pub use super::btree_map::IncrBTreeMap;
18 #[cfg(feature = "im")]
19 pub use super::im_rc::Either;
20 #[cfg(feature = "im")]
21 pub use super::im_rc::IncrOrdMap;
22 pub use super::symmetric_fold::DiffElement;
23 pub use super::symmetric_fold::GenericMap;
24 pub use super::symmetric_fold::MergeElement;
25 pub use super::symmetric_fold::MutableMap;
26 pub use super::symmetric_fold::SymmetricFoldMap;
27 pub use super::symmetric_fold::SymmetricMapMap;
28 pub use super::ClosureFold;
29 pub use super::IncrMap;
30 pub use super::UnorderedFold;
31}
32
33use symmetric_fold::{GenericMap, MutableMap, SymmetricFoldMap, SymmetricMapMap};
34
35trait Operator<K, V, V2> {
36 type Output;
37 type Function;
38 fn as_opt(output: &Self::Output) -> Option<&V2>;
39 fn call_fn(&mut self, key: &K, input: Incr<V>) -> Incr<Self::Output>;
40}
41
42struct MapOperator<K, V, V2, F>(F, PhantomData<(K, V, V2)>)
43where
44 F: FnMut(&K, Incr<V>) -> Incr<V2> + NotObserver;
45
46impl<K, V, V2, F> Operator<K, V, V2> for MapOperator<K, V, V2, F>
47where
48 F: FnMut(&K, Incr<V>) -> Incr<V2> + NotObserver,
49{
50 type Output = V2;
51 type Function = F;
52 #[inline]
53 fn as_opt(output: &Self::Output) -> Option<&V2> {
54 Some(output)
55 }
56 #[inline]
57 fn call_fn(&mut self, key: &K, input: Incr<V>) -> Incr<Self::Output> {
58 (self.0)(key, input)
59 }
60}
61
62struct FilterMapOperator<K, V, V2, F>(F, PhantomData<(K, V, V2)>)
63where
64 F: FnMut(&K, Incr<V>) -> Incr<Option<V2>> + NotObserver;
65
66impl<K, V, V2, F> Operator<K, V, V2> for FilterMapOperator<K, V, V2, F>
67where
68 F: FnMut(&K, Incr<V>) -> Incr<Option<V2>> + NotObserver,
69{
70 type Output = Option<V2>;
71 type Function = F;
72 #[inline]
73 fn as_opt(output: &Self::Output) -> Option<&V2> {
74 output.as_ref()
75 }
76 #[inline]
77 fn call_fn(&mut self, key: &K, input: Incr<V>) -> Incr<Self::Output> {
78 (self.0)(key, input)
79 }
80}
81
82pub(crate) trait WithOldIO<T> {
84 fn with_old_input_output<R, F>(&self, f: F) -> Incr<R>
85 where
86 R: Value,
87 F: FnMut(Option<(T, R)>, &T) -> (R, bool) + 'static + NotObserver;
88
89 fn with_old_input_output2<R, T2, F>(&self, other: &Incr<T2>, f: F) -> Incr<R>
90 where
91 R: Value,
92 T2: Value,
93 F: FnMut(Option<(T, T2, R)>, &T, &T2) -> (R, bool) + 'static + NotObserver;
94}
95
96impl<T: Value> WithOldIO<T> for Incr<T> {
97 fn with_old_input_output<R, F>(&self, mut f: F) -> Incr<R>
98 where
99 R: Value,
100 F: FnMut(Option<(T, R)>, &T) -> (R, bool) + 'static + NotObserver,
101 {
102 let mut old_input: Option<T> = None;
103 self.map_with_old(move |old_opt, a| {
104 let oi = &mut old_input;
105 let (b, didchange) = f(old_opt.and_then(|x| oi.take().map(|oi| (oi, x))), a);
106 *oi = Some(a.clone());
107 (b, didchange)
108 })
109 }
110
111 fn with_old_input_output2<R, T2, F>(&self, other: &Incr<T2>, mut f: F) -> Incr<R>
112 where
113 R: Value,
114 T2: Value,
115 F: FnMut(Option<(T, T2, R)>, &T, &T2) -> (R, bool) + 'static + NotObserver,
116 {
117 let mut old_input: Option<(T, T2)> = None;
118 self.zip(other).map_with_old(move |old_opt, (a, b)| {
120 let oi = &mut old_input;
121 let (r, didchange) = f(
122 old_opt.and_then(|x| oi.take().map(|(oia, oib)| (oia, oib, x))),
123 a,
124 b,
125 );
126 *oi = Some((a.clone(), b.clone()));
127 (r, didchange)
128 })
129 }
130}
131pub trait IncrMap<M> {
144 fn incr_map<F, K, V, V2>(&self, f: F) -> Incr<M::OutputMap<V2>>
145 where
146 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
147 K: Value + Ord,
148 V: Value,
149 V2: Value,
150 F: FnMut(&V) -> V2 + 'static + NotObserver,
151 M::OutputMap<V2>: Value;
152
153 fn incr_filter_map<F, K, V, V2>(&self, f: F) -> Incr<M::OutputMap<V2>>
154 where
155 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
156 K: Value + Ord,
157 V: Value,
158 V2: Value,
159 F: FnMut(&V) -> Option<V2> + 'static + NotObserver,
160 M::OutputMap<V2>: Value;
161
162 fn incr_mapi<F, K, V, V2>(&self, f: F) -> Incr<M::OutputMap<V2>>
163 where
164 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
165 K: Value + Ord,
166 V: Value,
167 V2: Value,
168 F: FnMut(&K, &V) -> V2 + 'static + NotObserver,
169 M::OutputMap<V2>: Value;
170
171 fn incr_filter_mapi<F, K, V, V2>(&self, f: F) -> Incr<M::OutputMap<V2>>
172 where
173 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
174 K: Value + Ord,
175 V: Value,
176 V2: Value,
177 F: FnMut(&K, &V) -> Option<V2> + 'static + NotObserver,
178 M::OutputMap<V2>: Value;
179
180 fn incr_unordered_fold_with<K, V, R, F>(&self, init: R, fold: F) -> Incr<R>
181 where
182 M: SymmetricFoldMap<K, V>,
183 K: Value + Ord,
184 V: Value,
185 R: Value,
186 F: UnorderedFold<M, K, V, R> + 'static + NotObserver;
187
188 fn incr_unordered_fold<FAdd, FRemove, K, V, R>(
189 &self,
190 init: R,
191 add: FAdd,
192 remove: FRemove,
193 revert_to_init_when_empty: bool,
194 ) -> Incr<R>
195 where
196 M: SymmetricFoldMap<K, V>,
197 K: Value + Ord,
198 V: Value,
199 R: Value,
200 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
201 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver;
202
203 fn incr_unordered_fold_update<FAdd, FRemove, FUpdate, K, V, R>(
204 &self,
205 init: R,
206 add: FAdd,
207 remove: FRemove,
208 update: FUpdate,
209 revert_to_init_when_empty: bool,
210 ) -> Incr<R>
211 where
212 M: SymmetricFoldMap<K, V>,
213 K: Value + Ord,
214 V: Value,
215 R: Value,
216 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
217 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver,
218 FUpdate: FnMut(R, &K, &V, &V) -> R + 'static + NotObserver;
219}
220
221impl<M: Value> IncrMap<M> for Incr<M> {
222 #[inline]
223 fn incr_map<F, K, V, V2>(&self, mut f: F) -> Incr<M::OutputMap<V2>>
224 where
225 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
226 K: Value + Ord,
227 V: Value,
228 V2: Value,
229 F: FnMut(&V) -> V2 + 'static + NotObserver,
230 M::OutputMap<V2>: Value,
231 {
232 let i = self.incr_filter_mapi(move |_k, v| Some(f(v)));
233 #[cfg(debug_assertions)]
234 i.set_graphviz_user_data(Box::new(format!(
235 "incr_map -> {}",
236 std::any::type_name::<M::OutputMap<V2>>()
237 )));
238 i
239 }
240
241 #[inline]
242 fn incr_filter_map<F, K, V, V2>(&self, mut f: F) -> Incr<M::OutputMap<V2>>
243 where
244 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
245 K: Value + Ord,
246 V: Value,
247 V2: Value,
248 F: FnMut(&V) -> Option<V2> + 'static + NotObserver,
249 M::OutputMap<V2>: Value,
250 {
251 let i = self.incr_filter_mapi(move |_k, v| f(v));
252 #[cfg(debug_assertions)]
253 i.set_graphviz_user_data(Box::new(format!(
254 "incr_filter_map -> {}",
255 std::any::type_name::<M::OutputMap<V2>>()
256 )));
257 i
258 }
259
260 #[inline]
261 fn incr_mapi<F, K, V, V2>(&self, mut f: F) -> Incr<M::OutputMap<V2>>
262 where
263 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
264 K: Value + Ord,
265 V: Value,
266 V2: Value,
267 F: FnMut(&K, &V) -> V2 + 'static + NotObserver,
268 M::OutputMap<V2>: Value,
269 {
270 let i = self.incr_filter_mapi(move |k, v| Some(f(k, v)));
271 #[cfg(debug_assertions)]
272 i.set_graphviz_user_data(Box::new(format!(
273 "incr_mapi -> {}",
274 std::any::type_name::<M::OutputMap<V2>>()
275 )));
276 i
277 }
278
279 fn incr_filter_mapi<F, K, V, V2>(&self, mut f: F) -> Incr<M::OutputMap<V2>>
280 where
281 M: SymmetricFoldMap<K, V> + SymmetricMapMap<K, V>,
282 K: Value + Ord,
283 V: Value,
284 V2: Value,
285 F: FnMut(&K, &V) -> Option<V2> + 'static + NotObserver,
286 M::OutputMap<V2>: Value,
287 {
288 let i = self.with_old_input_output(move |old, input| match (old, input.len()) {
289 (_, 0) | (None, _) => (input.filter_map_collect(&mut f), true),
290 (Some((old_in, mut old_out)), _) => {
291 let mut did_change = false;
292 let old_out_mut = old_out.make_mut();
293 let _: &mut <M::OutputMap<V2> as MutableMap<K, V2>>::UnderlyingMap = old_in
294 .symmetric_fold(input, old_out_mut, |out, (key, change)| {
295 did_change = true;
296 match change {
297 DiffElement::Left(_) => {
298 out.remove(key);
299 }
300 DiffElement::Right(newval) => {
301 if let Some(v2) = f(key, newval) {
302 out.insert(key.clone(), v2);
303 } else {
304 out.remove(key);
305 }
306 }
307 DiffElement::Unequal(_, newval) => {
308 if let Some(v2) = f(key, newval) {
309 out.insert(key.clone(), v2);
310 } else {
311 out.remove(key);
312 }
313 }
314 }
315 out
316 });
317 (old_out, did_change)
318 }
319 });
320 #[cfg(debug_assertions)]
321 i.set_graphviz_user_data(Box::new(format!(
322 "incr_filter_mapi -> {}",
323 std::any::type_name::<M::OutputMap<V2>>()
324 )));
325 i
326 }
327
328 fn incr_unordered_fold<FAdd, FRemove, K, V, R>(
329 &self,
330 init: R,
331 add: FAdd,
332 remove: FRemove,
333 revert_to_init_when_empty: bool,
334 ) -> Incr<R>
335 where
336 M: SymmetricFoldMap<K, V>,
337 K: Value + Ord,
338 V: Value,
339 R: Value,
340 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
341 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver,
342 {
343 self.incr_unordered_fold_with(
344 init,
345 PlainUnorderedFold {
346 add,
347 remove,
348 revert_to_init_when_empty,
349 phantom: PhantomData,
350 },
351 )
352 }
353
354 fn incr_unordered_fold_update<FAdd, FRemove, FUpdate, K, V, R>(
355 &self,
356 init: R,
357 add: FAdd,
358 remove: FRemove,
359 update: FUpdate,
360 revert_to_init_when_empty: bool,
361 ) -> Incr<R>
362 where
363 M: SymmetricFoldMap<K, V>,
364 K: Value + Ord,
365 V: Value,
366 R: Value,
367 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
368 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver,
369 FUpdate: FnMut(R, &K, &V, &V) -> R + 'static + NotObserver,
370 {
371 let i = self.incr_unordered_fold_with(
372 init,
373 UpdateUnorderedFold {
374 add,
375 remove,
376 update,
377 revert_to_init_when_empty,
378 phantom: PhantomData,
379 },
380 );
381 #[cfg(debug_assertions)]
382 i.set_graphviz_user_data(Box::new(format!(
383 "incr_unordered_fold_update -> {}",
384 std::any::type_name::<R>()
385 )));
386 i
387 }
388
389 fn incr_unordered_fold_with<K, V, R, F>(&self, init: R, mut fold: F) -> Incr<R>
390 where
391 M: SymmetricFoldMap<K, V>,
392 K: Value + Ord,
393 V: Value,
394 R: Value,
395 F: UnorderedFold<M, K, V, R> + 'static + NotObserver,
396 {
397 let i = self.with_old_input_output(move |old, new_in| match old {
398 None => {
399 let newmap = fold.initial_fold(init.clone(), new_in);
400 (newmap, true)
401 }
402 Some((old_in, old_out)) => {
403 if fold.revert_to_init_when_empty() && new_in.is_empty() {
404 return (init.clone(), !old_in.is_empty());
405 }
406 let mut did_change = false;
407 let folded: R = old_in.symmetric_fold(new_in, old_out, |acc, (key, difference)| {
408 did_change = true;
409 match difference {
410 DiffElement::Left(value) => fold.remove(acc, key, value),
411 DiffElement::Right(value) => fold.add(acc, key, value),
412 DiffElement::Unequal(lv, rv) => fold.update(acc, key, lv, rv),
413 }
414 });
415 (folded, did_change)
416 }
417 });
418 #[cfg(debug_assertions)]
419 i.set_graphviz_user_data(Box::new(format!(
420 "incr_unordered_fold_with -> {}",
421 std::any::type_name::<R>()
422 )));
423 i
424 }
425}
426
427pub trait UnorderedFold<M, K, V, R>
434where
435 M: SymmetricFoldMap<K, V>,
436 K: Value + Ord,
437 V: Value,
438{
439 fn add(&mut self, acc: R, key: &K, value: &V) -> R;
443
444 fn remove(&mut self, acc: R, key: &K, value: &V) -> R;
448
449 fn update(&mut self, mut acc: R, key: &K, old: &V, new: &V) -> R {
451 acc = self.remove(acc, key, old);
452 self.add(acc, key, new)
453 }
454
455 fn revert_to_init_when_empty(&self) -> bool;
458
459 fn initial_fold(&mut self, acc: R, input: &M) -> R {
461 input.nonincremental_fold(acc, |acc, (k, v)| self.add(acc, k, v))
462 }
463}
464
465struct PlainUnorderedFold<M, K, V, R, FAdd, FRemove> {
466 add: FAdd,
467 remove: FRemove,
468 revert_to_init_when_empty: bool,
469 phantom: PhantomData<(M, K, V, R)>,
470}
471
472impl<M, K: Value + Ord, V: Value, R: Value, FAdd, FRemove> UnorderedFold<M, K, V, R>
473 for PlainUnorderedFold<M, K, V, R, FAdd, FRemove>
474where
475 M: SymmetricFoldMap<K, V>,
476 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
477 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver,
478{
479 fn add(&mut self, acc: R, key: &K, value: &V) -> R {
480 (self.add)(acc, key, value)
481 }
482 fn remove(&mut self, acc: R, key: &K, value: &V) -> R {
483 (self.remove)(acc, key, value)
484 }
485 fn revert_to_init_when_empty(&self) -> bool {
486 self.revert_to_init_when_empty
487 }
488}
489
490struct UpdateUnorderedFold<M, K, V, R, FAdd, FRemove, FUpdate> {
491 add: FAdd,
492 remove: FRemove,
493 update: FUpdate,
494 revert_to_init_when_empty: bool,
495 phantom: PhantomData<(M, K, V, R)>,
496}
497
498impl<M, K: Value + Ord, V: Value, R: Value, FAdd, FRemove, FUpdate> UnorderedFold<M, K, V, R>
499 for UpdateUnorderedFold<M, K, V, R, FAdd, FRemove, FUpdate>
500where
501 M: SymmetricFoldMap<K, V>,
502 FAdd: FnMut(R, &K, &V) -> R + 'static + NotObserver,
503 FUpdate: FnMut(R, &K, &V, &V) -> R + 'static + NotObserver,
504 FRemove: FnMut(R, &K, &V) -> R + 'static + NotObserver,
505{
506 fn add(&mut self, acc: R, key: &K, value: &V) -> R {
507 (self.add)(acc, key, value)
508 }
509 fn remove(&mut self, acc: R, key: &K, value: &V) -> R {
510 (self.remove)(acc, key, value)
511 }
512 fn update(&mut self, acc: R, key: &K, old: &V, new: &V) -> R {
513 (self.update)(acc, key, old, new)
514 }
515 fn revert_to_init_when_empty(&self) -> bool {
516 self.revert_to_init_when_empty
517 }
518}
519
520pub struct ClosureFold<M, K, V, R, FAdd, FRemove, FUpdate, FInitial> {
522 add: FAdd,
523 remove: FRemove,
524 update: Option<FUpdate>,
525 initial: Option<FInitial>,
526 revert_to_init_when_empty: bool,
527 phantom: PhantomData<(M, K, V, R)>,
528}
529
530impl ClosureFold<(), (), (), (), (), (), (), ()> {
531 pub fn new<M, K, V, R>(
532 ) -> ClosureFold<M, K, V, R, (), (), fn(R, &K, &V, &V) -> R, fn(R, &M) -> R>
533where {
534 ClosureFold::<M, K, V, R, _, _, _, _> {
535 add: (),
536 remove: (),
537 update: None,
538 initial: None,
539 revert_to_init_when_empty: false,
540 phantom: PhantomData,
541 }
542 }
543
544 pub fn new_add_remove<M, K, V, R, FAdd, FRemove>(
545 add: FAdd,
546 remove: FRemove,
547 ) -> ClosureFold<M, K, V, R, FAdd, FRemove, fn(R, &K, &V, &V) -> R, fn(R, &M) -> R>
548 where
549 FAdd: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
550 FRemove: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
551 {
552 ClosureFold {
553 add,
554 remove,
555 update: None,
556 initial: None,
557 revert_to_init_when_empty: false,
558 phantom: PhantomData,
559 }
560 }
561}
562
563impl<M, K, V, R, FAdd_, FRemove_, FUpdate_, FInitial_>
564 ClosureFold<M, K, V, R, FAdd_, FRemove_, FUpdate_, FInitial_>
565{
566 pub fn add<FAdd>(
567 self,
568 add: FAdd,
569 ) -> ClosureFold<M, K, V, R, FAdd, FRemove_, FUpdate_, FInitial_>
570 where
571 FAdd: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
572 {
573 ClosureFold {
574 add,
575 remove: self.remove,
576 update: None,
577 initial: None,
578 revert_to_init_when_empty: false,
579 phantom: PhantomData,
580 }
581 }
582 pub fn remove<FRemove>(
583 self,
584 remove: FRemove,
585 ) -> ClosureFold<M, K, V, R, FAdd_, FRemove, FUpdate_, FInitial_>
586 where
587 FRemove: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
588 {
589 ClosureFold {
590 add: self.add,
591 remove,
592 update: None,
593 initial: None,
594 revert_to_init_when_empty: false,
595 phantom: PhantomData,
596 }
597 }
598 pub fn update<FUpdate>(
599 self,
600 update: FUpdate,
601 ) -> ClosureFold<M, K, V, R, FAdd_, FRemove_, FUpdate, FInitial_>
602 where
603 FUpdate: for<'a> FnMut(R, &'a K, &'a V, &'a V) -> R + 'static + NotObserver,
604 {
605 ClosureFold {
606 add: self.add,
607 remove: self.remove,
608 update: Some(update),
609 initial: self.initial,
610 revert_to_init_when_empty: self.revert_to_init_when_empty,
611 phantom: self.phantom,
612 }
613 }
614
615 pub fn initial<FInitial>(
616 self,
617 initial: FInitial,
618 ) -> ClosureFold<M, K, V, R, FAdd_, FRemove_, FUpdate_, FInitial>
619 where
620 FInitial: for<'a> FnMut(R, &'a M) -> R + 'static + NotObserver,
621 {
622 ClosureFold {
623 add: self.add,
624 remove: self.remove,
625 update: self.update,
626 initial: Some(initial),
627 revert_to_init_when_empty: self.revert_to_init_when_empty,
628 phantom: self.phantom,
629 }
630 }
631 pub fn revert_to_init_when_empty(
632 self,
633 revert_to_init_when_empty: bool,
634 ) -> ClosureFold<M, K, V, R, FAdd_, FRemove_, FUpdate_, FInitial_> {
635 ClosureFold {
636 add: self.add,
637 remove: self.remove,
638 update: self.update,
639 initial: self.initial,
640 revert_to_init_when_empty,
641 phantom: self.phantom,
642 }
643 }
644}
645
646impl<M, K, V, R, FAdd, FRemove, FUpdate, FInitial> UnorderedFold<M, K, V, R>
647 for ClosureFold<M, K, V, R, FAdd, FRemove, FUpdate, FInitial>
648where
649 M: SymmetricFoldMap<K, V>,
650 K: Value + Ord,
651 V: Value,
652 R: Value,
653 FAdd: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
654 FRemove: for<'a> FnMut(R, &'a K, &'a V) -> R + 'static + NotObserver,
655 FUpdate: for<'a> FnMut(R, &'a K, &'a V, &'a V) -> R + 'static + NotObserver,
656 FInitial: for<'a> FnMut(R, &'a M) -> R + 'static + NotObserver,
657{
658 fn add(&mut self, acc: R, key: &K, value: &V) -> R {
659 (self.add)(acc, key, value)
660 }
661
662 fn remove(&mut self, acc: R, key: &K, value: &V) -> R {
663 (self.remove)(acc, key, value)
664 }
665
666 fn update(&mut self, acc: R, key: &K, old: &V, new: &V) -> R {
667 if let Some(closure) = &mut self.update {
668 closure(acc, key, old, new)
669 } else {
670 let r = self.remove(acc, key, old);
671 let r = self.add(r, key, new);
672 r
673 }
674 }
675
676 fn revert_to_init_when_empty(&self) -> bool {
677 self.revert_to_init_when_empty
678 }
679
680 fn initial_fold(&mut self, init: R, input: &M) -> R {
681 if let Some(closure) = &mut self.initial {
682 closure(init, input)
683 } else {
684 input.nonincremental_fold(init, |acc, (k, v)| self.add(acc, k, v))
685 }
686 }
687}