hooks/
signal_eq.rs

1use std::pin::Pin;
2
3use hooks_core::{Hook, HookPollNextUpdate, HookUnmount, HookValue};
4
5/// This wrapper type also derives the following traits if `S: Unpin`.
6///
7/// - [`HookUnmount`]
8/// - [`HookPollNextUpdate`]
9/// - [`HookValue`] (the [`Value`](HookValue::Value) is wrapped with [`SignalEq`])
10/// - [`Hook`] (the value returned by [`use_hook`](Hook::use_hook) is wrapped with [`SignalEq`])
11/// - [`SignalHook`](crate::SignalHook)
12/// - [`ShareValue`](crate::ShareValue)
13/// - [`Signal`](crate::Signal)
14/// - [`ToOwnedSignal`](crate::ToOwnedSignal) + [`ToOwnedShareValue`](crate::ToOwnedShareValue) (where `S: ToOwnedSignal`)
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct SignalEq<S>(pub S);
17
18impl<H: HookUnmount + Unpin> HookUnmount for SignalEq<H> {
19    fn unmount(self: Pin<&mut Self>) {
20        H::unmount(Pin::new(&mut self.get_mut().0))
21    }
22}
23
24impl<H: HookPollNextUpdate + Unpin> HookPollNextUpdate for SignalEq<H> {
25    fn poll_next_update(
26        self: Pin<&mut Self>,
27        cx: &mut std::task::Context<'_>,
28    ) -> std::task::Poll<bool> {
29        H::poll_next_update(Pin::new(&mut self.get_mut().0), cx)
30    }
31}
32
33impl<'hook, H: HookValue<'hook> + Unpin> HookValue<'hook> for SignalEq<H> {
34    type Value = SignalEq<H::Value>;
35}
36
37impl<H: Hook + Unpin> Hook for SignalEq<H> {
38    fn use_hook(self: Pin<&mut Self>) -> <Self as HookValue<'_>>::Value {
39        SignalEq(H::use_hook(Pin::new(&mut self.get_mut().0)))
40    }
41}
42
43#[cfg(feature = "Signal")]
44impl<H: crate::SignalHook + Unpin> crate::SignalHook for SignalEq<H>
45where
46    H::SignalShareValue: PartialEq,
47{
48    type SignalShareValue = H::SignalShareValue;
49    type SignalHookUninitialized = H::SignalHookUninitialized;
50
51    fn to_signal(&self) -> SignalEq<crate::Value<'_, H>> {
52        SignalEq(self.0.to_signal())
53    }
54}
55
56#[cfg(feature = "Signal")]
57impl<S, T> crate::ShareValue for SignalEq<S>
58where
59    S: crate::Signal<Value = T>,
60    T: PartialEq,
61{
62    type Value = T;
63
64    crate::proxy_share_value_non_eq!(|self| -> S { &self.0 }, |other| &other.0);
65
66    fn try_unwrap(self) -> Result<Self::Value, Self>
67    where
68        Self: Sized,
69    {
70        self.0.try_unwrap().map_err(Self)
71    }
72
73    #[inline]
74    fn set(&self, new_value: T) {
75        self.0.map_mut_and_notify_if(move |old| {
76            let changed = *old != new_value;
77            *old = new_value;
78            ((), changed)
79        })
80    }
81
82    #[inline]
83    fn replace(&self, new_value: T) -> T {
84        self.0.map_mut_and_notify_if(move |old| {
85            let changed = *old != new_value;
86            let old = std::mem::replace(old, new_value);
87            (old, changed)
88        })
89    }
90
91    #[inline]
92    fn replace_with<F: FnOnce(&T) -> T>(&self, f: F) -> T {
93        self.0.map_mut_and_notify_if(move |v| {
94            let new_value = f(v);
95            let changed = new_value != *v;
96            let old = std::mem::replace(v, new_value);
97            (old, changed)
98        })
99    }
100}
101
102#[cfg(feature = "Signal")]
103impl<S> crate::Signal for SignalEq<S>
104where
105    S: crate::Signal,
106    S::Value: PartialEq,
107    S::SignalHook: Unpin,
108{
109    type SignalHook = SignalEq<S::SignalHook>;
110
111    fn is_signal_of(&self, signal_hook: &Self::SignalHook) -> bool {
112        self.0.is_signal_of(&signal_hook.0)
113    }
114
115    fn to_signal_hook(&self) -> Self::SignalHook {
116        SignalEq(self.0.to_signal_hook())
117    }
118
119    fn update_signal_hook(&self, hook: std::pin::Pin<&mut Self::SignalHook>) {
120        self.0.update_signal_hook(Pin::new(&mut hook.get_mut().0))
121    }
122
123    fn h_signal_hook<'hook>(
124        &self,
125        hook: std::pin::Pin<
126            &'hook mut <Self::SignalHook as crate::SignalHook>::SignalHookUninitialized,
127        >,
128    ) -> crate::Value<'hook, Self::SignalHook> {
129        SignalEq(self.0.h_signal_hook(hook))
130    }
131
132    fn notify_changed(&self) {
133        self.0.notify_changed()
134    }
135
136    fn map_mut_and_notify_if<R>(&self, f: impl FnOnce(&mut Self::Value) -> (R, bool)) -> R {
137        self.0.map_mut_and_notify_if(f)
138    }
139}
140
141#[cfg(feature = "Signal")]
142impl<S> crate::ToOwnedShareValue for SignalEq<S>
143where
144    S: crate::ToOwnedSignal,
145    S::Value: PartialEq,
146    S::SignalHook: Unpin,
147{
148    type OwnedShareValue = SignalEq<S::OwnedShareValue>;
149
150    #[inline]
151    fn to_owned_share_value(&self) -> Self::OwnedShareValue {
152        SignalEq(self.0.to_owned_share_value())
153    }
154}