1use std::{
2 cmp,
3 collections::HashMap,
4 fmt::{self, Debug, Display, Formatter},
5 hash::{Hash, Hasher},
6 ops::{Deref, DerefMut},
7 task::{Context, Poll, Waker},
8};
9
10use generational_box::{AnyStorage, GenerationalBox, Owner, SyncStorage};
11
12use crate::ElementKey;
13
14pub trait Notifier: Default + Send + Sync + 'static {
15 fn wake(&mut self);
16 fn register(&mut self, key: Option<&ElementKey>, waker: Waker);
17 fn clear(&mut self);
18 fn remove(&mut self, _key: &ElementKey) {}
19}
20
21#[derive(Default)]
22#[doc(hidden)]
23pub struct SingleWaker {
24 waker: Option<Waker>,
25}
26
27impl Notifier for SingleWaker {
28 fn wake(&mut self) {
29 if let Some(waker) = self.waker.take() {
30 waker.wake();
31 }
32 }
33
34 fn register(&mut self, _key: Option<&ElementKey>, waker: Waker) {
35 self.waker = Some(waker);
36 }
37
38 fn clear(&mut self) {
39 self.waker = None;
40 }
41}
42
43#[derive(Default)]
44#[doc(hidden)]
45pub struct WakerMap {
46 wakers: HashMap<ElementKey, Waker>,
47}
48
49impl Notifier for WakerMap {
50 fn wake(&mut self) {
51 for waker in self.wakers.values() {
52 waker.wake_by_ref();
53 }
54 }
55
56 fn register(&mut self, key: Option<&ElementKey>, waker: Waker) {
57 if let Some(key) = key {
58 self.wakers.insert(key.clone(), waker);
59 }
60 }
61
62 fn clear(&mut self) {
63 self.wakers.clear();
64 }
65
66 fn remove(&mut self, key: &ElementKey) {
67 self.wakers.remove(key);
68 }
69}
70
71pub struct ReactiveValue<T, N> {
72 value: T,
73 notifier: N,
74 is_changed: bool,
75}
76
77pub struct ReactiveHandle<T, N>
79where
80 T: Send + Sync + 'static,
81 N: Notifier,
82{
83 pub(crate) inner: GenerationalBox<ReactiveValue<T, N>, SyncStorage>,
84}
85
86impl<T, N> Clone for ReactiveHandle<T, N>
87where
88 T: Send + Sync + 'static,
89 N: Notifier,
90{
91 fn clone(&self) -> Self {
92 *self
93 }
94}
95
96impl<T, N> Copy for ReactiveHandle<T, N>
97where
98 T: Send + Sync + 'static,
99 N: Notifier,
100{
101}
102
103impl<T, N> ReactiveHandle<T, N>
104where
105 T: Send + Sync + 'static,
106 N: Notifier,
107{
108 pub(crate) fn new_in(owner: &Owner<SyncStorage>, value: T) -> Self {
109 Self {
110 inner: owner.insert(ReactiveValue {
111 value,
112 notifier: N::default(),
113 is_changed: false,
114 }),
115 }
116 }
117
118 #[cfg(feature = "atom")]
120 pub(crate) fn same_storage(&self, other: &Self) -> bool {
121 self.inner.ptr_eq(&other.inner)
122 }
123
124 #[cfg(feature = "atom")]
125 pub(crate) fn remove_waker(&self, key: &ElementKey) {
126 if let Ok(mut value) = self.inner.try_write() {
127 value.notifier.remove(key);
128 }
129 }
130
131 #[cfg(test)]
132 pub(crate) fn has_waker(&self, key: &ElementKey) -> bool
133 where
134 N: WakerLookup,
135 {
136 self.inner
137 .try_read()
138 .map(|value| value.notifier.has_waker(key))
139 .unwrap_or(false)
140 }
141
142 pub(crate) fn poll_change(&self, key: Option<&ElementKey>, cx: &mut Context<'_>) -> Poll<()> {
143 if let Ok(mut value) = self.inner.try_write() {
144 if value.is_changed {
145 value.is_changed = false;
146 value.notifier.clear();
147 Poll::Ready(())
148 } else {
149 value.notifier.register(key, cx.waker().clone());
150 Poll::Pending
151 }
152 } else {
153 Poll::Pending
154 }
155 }
156
157 pub fn try_read(&'_ self) -> Option<ReactiveRef<'_, T, N>> {
159 self.inner
160 .try_read()
161 .ok()
162 .map(|inner| ReactiveRef { inner })
163 }
164
165 pub fn read(&'_ self) -> ReactiveRef<'_, T, N> {
167 self.try_read()
168 .expect("attempt to read state while unavailable or already mutably borrowed")
169 }
170
171 pub fn try_write(&'_ self) -> Option<ReactiveMutRef<'_, T, N>> {
173 self.inner
174 .try_write()
175 .map(|inner| ReactiveMutRef {
176 inner,
177 is_deref_mut: false,
178 })
179 .ok()
180 }
181
182 pub fn write(&'_ self) -> ReactiveMutRef<'_, T, N> {
184 self.try_write()
185 .expect("attempt to write state while unavailable or already borrowed")
186 }
187
188 pub fn try_write_no_update(&'_ self) -> Option<ReactiveMutNoUpdate<'_, T, N>> {
190 self.inner
191 .try_write()
192 .map(|inner| ReactiveMutNoUpdate { inner })
193 .ok()
194 }
195
196 pub fn write_no_update(&'_ self) -> ReactiveMutNoUpdate<'_, T, N> {
198 self.try_write_no_update()
199 .expect("attempt to write state while unavailable or already borrowed")
200 }
201
202 pub fn set(&mut self, value: T) {
204 if let Some(mut current) = self.try_write() {
205 *current = value;
206 }
207 }
208
209 pub fn set_no_update(&mut self, value: T) {
211 if let Some(mut current) = self.try_write_no_update() {
212 *current = value;
213 }
214 }
215}
216
217#[cfg(test)]
218pub(crate) trait WakerLookup {
219 fn has_waker(&self, key: &ElementKey) -> bool;
220}
221
222#[cfg(test)]
223impl WakerLookup for WakerMap {
224 fn has_waker(&self, key: &ElementKey) -> bool {
225 self.wakers.contains_key(key)
226 }
227}
228
229impl<T, N> ReactiveHandle<T, N>
230where
231 T: Send + Sync + Copy + 'static,
232 N: Notifier,
233{
234 pub fn get(&self) -> T {
235 *self.read()
236 }
237}
238
239#[cfg(feature = "atom")]
240impl<T> ReactiveHandle<T, WakerMap>
241where
242 T: Send + Sync + 'static,
243{
244 pub fn new(value: T) -> Self {
245 Self::new_in(&crate::atom::OWNER, value)
246 }
247}
248
249pub struct ReactiveRef<'a, T, N>
251where
252 T: 'static,
253 N: Notifier,
254{
255 inner: <SyncStorage as AnyStorage>::Ref<'a, ReactiveValue<T, N>>,
256}
257
258impl<T, N> Deref for ReactiveRef<'_, T, N>
259where
260 T: 'static,
261 N: Notifier,
262{
263 type Target = T;
264
265 fn deref(&self) -> &Self::Target {
266 &self.inner.value
267 }
268}
269
270pub struct ReactiveMutRef<'a, T, N>
272where
273 T: 'static,
274 N: Notifier,
275{
276 inner: <SyncStorage as AnyStorage>::Mut<'a, ReactiveValue<T, N>>,
277 is_deref_mut: bool,
278}
279
280impl<T, N> Deref for ReactiveMutRef<'_, T, N>
281where
282 T: 'static,
283 N: Notifier,
284{
285 type Target = T;
286
287 fn deref(&self) -> &Self::Target {
288 &self.inner.value
289 }
290}
291
292impl<T, N> DerefMut for ReactiveMutRef<'_, T, N>
293where
294 T: 'static,
295 N: Notifier,
296{
297 fn deref_mut(&mut self) -> &mut Self::Target {
298 self.is_deref_mut = true;
299 &mut self.inner.value
300 }
301}
302
303impl<T, N> Drop for ReactiveMutRef<'_, T, N>
304where
305 T: 'static,
306 N: Notifier,
307{
308 fn drop(&mut self) {
309 if self.is_deref_mut {
310 self.inner.is_changed = true;
311 self.inner.notifier.wake();
312 }
313 }
314}
315
316pub struct ReactiveMutNoUpdate<'a, T, N>
318where
319 T: 'static,
320 N: Notifier,
321{
322 inner: <SyncStorage as AnyStorage>::Mut<'a, ReactiveValue<T, N>>,
323}
324
325impl<T, N> Deref for ReactiveMutNoUpdate<'_, T, N>
326where
327 T: 'static,
328 N: Notifier,
329{
330 type Target = T;
331
332 fn deref(&self) -> &Self::Target {
333 &self.inner.value
334 }
335}
336
337impl<T, N> DerefMut for ReactiveMutNoUpdate<'_, T, N>
338where
339 T: 'static,
340 N: Notifier,
341{
342 fn deref_mut(&mut self) -> &mut Self::Target {
343 &mut self.inner.value
344 }
345}
346
347impl<T, N> Debug for ReactiveHandle<T, N>
348where
349 T: Debug + Send + Sync + 'static,
350 N: Notifier,
351{
352 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
353 self.read().fmt(f)
354 }
355}
356
357impl<T, N> Display for ReactiveHandle<T, N>
358where
359 T: Display + Send + Sync + 'static,
360 N: Notifier,
361{
362 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
363 self.read().fmt(f)
364 }
365}
366
367impl<T, N> Hash for ReactiveHandle<T, N>
368where
369 T: Hash + Send + Sync + 'static,
370 N: Notifier,
371{
372 fn hash<H: Hasher>(&self, state: &mut H) {
373 self.read().hash(state)
374 }
375}
376
377impl<T, N> cmp::PartialEq<T> for ReactiveHandle<T, N>
378where
379 T: cmp::PartialEq<T> + Send + Sync + 'static,
380 N: Notifier,
381{
382 fn eq(&self, other: &T) -> bool {
383 *self.read() == *other
384 }
385}
386
387impl<T, N> cmp::PartialOrd<T> for ReactiveHandle<T, N>
388where
389 T: cmp::PartialOrd<T> + Send + Sync + 'static,
390 N: Notifier,
391{
392 fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
393 self.read().partial_cmp(other)
394 }
395}
396
397impl<T, N> cmp::PartialEq<ReactiveHandle<T, N>> for ReactiveHandle<T, N>
398where
399 T: cmp::PartialEq<T> + Send + Sync + 'static,
400 N: Notifier,
401{
402 fn eq(&self, other: &ReactiveHandle<T, N>) -> bool {
403 *self.read() == *other.read()
404 }
405}
406
407impl<T, N> cmp::PartialOrd<ReactiveHandle<T, N>> for ReactiveHandle<T, N>
408where
409 T: cmp::PartialOrd<T> + Send + Sync + 'static,
410 N: Notifier,
411{
412 fn partial_cmp(&self, other: &ReactiveHandle<T, N>) -> Option<cmp::Ordering> {
413 self.read().partial_cmp(&other.read())
414 }
415}
416
417impl<T, N> cmp::Eq for ReactiveHandle<T, N>
418where
419 T: cmp::Eq + Send + Sync + 'static,
420 N: Notifier,
421{
422}
423
424impl<T, N> std::ops::Add<T> for ReactiveHandle<T, N>
425where
426 T: std::ops::Add<Output = T> + Copy + Send + Sync + 'static,
427 N: Notifier,
428{
429 type Output = T;
430
431 fn add(self, rhs: T) -> T {
432 self.get() + rhs
433 }
434}
435
436impl<T, N> std::ops::AddAssign<T> for ReactiveHandle<T, N>
437where
438 T: std::ops::AddAssign<T> + Copy + Send + Sync + 'static,
439 N: Notifier,
440{
441 fn add_assign(&mut self, rhs: T) {
442 if let Some(mut current) = self.try_write() {
443 *current += rhs;
444 }
445 }
446}
447
448impl<T, N> std::ops::Sub<T> for ReactiveHandle<T, N>
449where
450 T: std::ops::Sub<Output = T> + Copy + Send + Sync + 'static,
451 N: Notifier,
452{
453 type Output = T;
454
455 fn sub(self, rhs: T) -> T {
456 self.get() - rhs
457 }
458}
459
460impl<T, N> std::ops::SubAssign<T> for ReactiveHandle<T, N>
461where
462 T: std::ops::SubAssign<T> + Copy + Send + Sync + 'static,
463 N: Notifier,
464{
465 fn sub_assign(&mut self, rhs: T) {
466 if let Some(mut current) = self.try_write() {
467 *current -= rhs;
468 }
469 }
470}
471
472impl<T, N> std::ops::Mul<T> for ReactiveHandle<T, N>
473where
474 T: std::ops::Mul<Output = T> + Copy + Send + Sync + 'static,
475 N: Notifier,
476{
477 type Output = T;
478
479 fn mul(self, rhs: T) -> T {
480 self.get() * rhs
481 }
482}
483
484impl<T, N> std::ops::MulAssign<T> for ReactiveHandle<T, N>
485where
486 T: std::ops::MulAssign<T> + Copy + Send + Sync + 'static,
487 N: Notifier,
488{
489 fn mul_assign(&mut self, rhs: T) {
490 if let Some(mut current) = self.try_write() {
491 *current *= rhs;
492 }
493 }
494}
495
496impl<T, N> std::ops::Div<T> for ReactiveHandle<T, N>
497where
498 T: std::ops::Div<Output = T> + Copy + Send + Sync + 'static,
499 N: Notifier,
500{
501 type Output = T;
502
503 fn div(self, rhs: T) -> T {
504 self.get() / rhs
505 }
506}
507
508impl<T, N> std::ops::DivAssign<T> for ReactiveHandle<T, N>
509where
510 T: std::ops::DivAssign<T> + Copy + Send + Sync + 'static,
511 N: Notifier,
512{
513 fn div_assign(&mut self, rhs: T) {
514 if let Some(mut current) = self.try_write() {
515 *current /= rhs;
516 }
517 }
518}