1use core::cell::RefCell;
8
9use alloc::rc::Rc;
10use nami_core::watcher::Context;
11
12use crate::signal::Signal;
13
14#[derive(Debug, Clone)]
16pub struct Distinct<S: Signal>
17where
18 S::Output: PartialEq,
19{
20 signal: S,
21 last_value: Rc<RefCell<Option<S::Output>>>,
22}
23
24impl<S: Signal> Distinct<S>
25where
26 S::Output: PartialEq,
27{
28 pub fn new(signal: S) -> Self {
30 Self {
31 signal,
32 last_value: Rc::new(RefCell::new(None)),
33 }
34 }
35}
36
37impl<S: Signal> Signal for Distinct<S>
38where
39 S::Output: PartialEq + Clone,
40{
41 type Output = S::Output;
42 type Guard = S::Guard;
43
44 fn get(&self) -> Self::Output {
45 self.signal.get()
46 }
47
48 fn watch(&self, watcher: impl Fn(Context<Self::Output>) + 'static) -> Self::Guard {
49 let last_value_store = self.last_value.clone();
50 self.signal.watch(move |ctx: Context<S::Output>| {
51 let last_value = last_value_store.borrow();
52 if let Some(last_value) = &*last_value {
53 if last_value != ctx.value() {
54 *last_value_store.borrow_mut() = Some(ctx.value().clone());
55 watcher(ctx);
56 }
57 } else {
58 *last_value_store.borrow_mut() = Some(ctx.value().clone());
60 watcher(ctx);
61 }
62 })
63 }
64}