dioxus_signals/
set_compare.rs1use crate::{write::WritableExt, ReadableExt};
2use std::hash::Hash;
3
4use dioxus_core::ReactiveContext;
5use futures_util::StreamExt;
6use generational_box::{Storage, UnsyncStorage};
7
8use crate::{CopyValue, ReadSignal, Signal, SignalData};
9use rustc_hash::FxHashMap;
10
11pub struct SetCompare<R, S: 'static = UnsyncStorage> {
13 subscribers: CopyValue<FxHashMap<R, Signal<bool, S>>>,
14}
15
16impl<R: Eq + Hash + 'static> SetCompare<R> {
17 #[track_caller]
21 pub fn new(f: impl FnMut() -> R + 'static) -> SetCompare<R> {
22 Self::new_maybe_sync(f)
23 }
24}
25
26impl<R: Eq + Hash + 'static, S: Storage<SignalData<bool>> + 'static> SetCompare<R, S> {
27 #[track_caller]
31 pub fn new_maybe_sync(mut f: impl FnMut() -> R + 'static) -> SetCompare<R, S> {
32 let subscribers: CopyValue<FxHashMap<R, Signal<bool, S>>> =
33 CopyValue::new(FxHashMap::default());
34 let mut previous = CopyValue::new(None);
35
36 let mut recompute = move || {
37 let subscribers = subscribers.read();
38 let mut previous = previous.write();
39
40 if let Some(previous) = previous.take() {
41 if let Some(mut value) = subscribers.get(&previous).cloned() {
42 *value.write() = false;
43 }
44 }
45
46 let current = f();
47
48 if let Some(mut value) = subscribers.get(¤t).cloned() {
49 *value.write() = true;
50 }
51
52 *previous = Some(current);
53 };
54 let (rc, mut changed) = ReactiveContext::new();
55 dioxus_core::spawn(async move {
56 loop {
57 rc.reset_and_run_in(&mut recompute);
59
60 let _ = changed.next().await;
62 }
63 });
64
65 SetCompare { subscribers }
66 }
67}
68
69impl<R: Eq + Hash + 'static> SetCompare<R> {
70 pub fn equal(&mut self, value: R) -> ReadSignal<bool> {
72 let subscribers = self.subscribers.write();
73
74 match subscribers.get(&value) {
75 Some(&signal) => signal.into(),
76 None => {
77 drop(subscribers);
78 let mut subscribers = self.subscribers.write();
79 let signal = Signal::new_maybe_sync(false);
80 subscribers.insert(value, signal);
81 signal.into()
82 }
83 }
84 }
85}
86
87impl<R, S: Storage<SignalData<bool>>> PartialEq for SetCompare<R, S> {
88 fn eq(&self, other: &Self) -> bool {
89 self.subscribers == other.subscribers
90 }
91}
92
93impl<R, S: Storage<SignalData<bool>>> Clone for SetCompare<R, S> {
94 fn clone(&self) -> Self {
95 *self
96 }
97}
98
99impl<R, S: Storage<SignalData<bool>>> Copy for SetCompare<R, S> {}