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