silkenweb_reactive/
accumulators.rs1use std::cell::RefCell;
23
24use num_traits::{WrappingAdd, WrappingSub, Zero};
25
26use crate::signal::{ReadSignal, Signal, SignalReceiver, WriteSignal};
27
28#[derive(Clone)]
32pub struct SumTotal<T> {
33 deltas: WriteSignal<T>,
34 total: ReadSignal<T>,
35}
36
37impl<T: 'static + Zero + Clone + WrappingAdd> Default for SumTotal<T> {
38 fn default() -> Self {
39 let deltas = Signal::new(T::zero());
40 let total = deltas.read().map_to(AccumulateSum(RefCell::new(T::zero())));
41 Self {
42 deltas: deltas.write(),
43 total,
44 }
45 }
46}
47
48impl<T: 'static> SumTotal<T> {
49 pub fn read(&self) -> ReadSignal<T> {
50 self.total.clone()
51 }
52}
53
54pub struct SumElement<T: 'static + Clone + Zero + WrappingAdd + WrappingSub> {
58 current: RefCell<T>,
59 total: SumTotal<T>,
60}
61
62impl<T: 'static + Zero + Clone + Zero + WrappingAdd + WrappingSub> SumElement<T> {
63 pub fn new(total: &SumTotal<T>) -> Self {
64 Self {
65 current: RefCell::new(T::zero()),
66 total: total.clone(),
67 }
68 }
69}
70
71impl<T: 'static + Clone + Zero + WrappingAdd + WrappingSub> SignalReceiver<T, SumHandle>
72 for SumElement<T>
73{
74 fn receive(&self, x: &T) -> SumHandle {
75 let delta = x.wrapping_sub(&self.current.borrow());
76 self.current.replace(x.clone());
77 self.total.deltas.set(delta);
78 SumHandle()
79 }
80}
81
82impl<T: 'static + Clone + Zero + WrappingAdd + WrappingSub> Drop for SumElement<T> {
83 fn drop(&mut self) {
84 self.total
85 .deltas
86 .set(T::zero().wrapping_sub(&self.current.borrow()));
87 }
88}
89
90pub struct SumHandle();
94
95struct AccumulateSum<T>(RefCell<T>);
96
97impl<T: 'static + Clone + WrappingAdd> SignalReceiver<T, T> for AccumulateSum<T> {
98 fn receive(&self, x: &T) -> T {
99 let mut total = self.0.borrow_mut();
100 *total = total.wrapping_add(x);
101 total.clone()
102 }
103}