use core::cell::RefCell;
use alloc::rc::Rc;
use nami_core::watcher::Context;
use crate::signal::{Signal, SignalIdentity};
#[derive(Debug, Clone)]
pub struct Distinct<S: Signal>
where
S::Output: PartialEq,
{
signal: S,
last_value: Rc<RefCell<Option<S::Output>>>,
}
impl<S: Signal> Distinct<S>
where
S::Output: PartialEq,
{
pub fn new(signal: S) -> Self {
Self {
signal,
last_value: Rc::new(RefCell::new(None)),
}
}
}
impl<S: Signal> Signal for Distinct<S>
where
S::Output: PartialEq + Clone,
{
type Output = S::Output;
type Guard = S::Guard;
fn get(&self) -> Self::Output {
self.signal.get()
}
fn identity(&self) -> Option<SignalIdentity> {
self.signal.identity()
}
fn watch(&self, watcher: impl Fn(Context<Self::Output>) + 'static) -> Self::Guard {
let last_value_store = self.last_value.clone();
self.signal.watch(move |ctx: Context<S::Output>| {
let changed = last_value_store.borrow().as_ref() != Some(ctx.value());
if changed {
*last_value_store.borrow_mut() = Some(ctx.value().clone());
watcher(ctx);
}
})
}
}