1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#![allow(dead_code)]
mod state_slice;
mod tests;
use slotmap::DenseSlotMap;
use std::{
cell::{RefCell, RefMut, Ref},
ops::{Deref, DerefMut},
rc::{Rc, Weak},
};
use state_slice::StateSliceMeta;
pub use state_slice::StateSlice;
pub use crate::{__view as view, __update as update};
slotmap::new_key_type! {pub struct SubscriptionKey;}
pub struct Subscription(Weak<RefCell<StateSliceMeta>>, SubscriptionKey);
impl Drop for Subscription {
fn drop(&mut self) {
let meta = if let Some(x) = self.0.upgrade() { x } else { return; };
meta.borrow_mut().subscribers.remove(self.1);
}
}
#[derive(Default)]
pub struct State<T>(pub Rc<RefCell<StateSlice<T>>>);
unsafe impl<T> Send for State<T> {}
unsafe impl<T> Sync for State<T> {}
impl<T> Clone for State<T> {
fn clone(&self) -> Self { Self(Rc::clone(&self.0)) }
}
struct StateGuard<'a, T> {
state: Option<RefMut<'a, StateSlice<T>>>,
}
impl<'a, T> Deref for StateGuard<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target { &self.state.as_ref().unwrap().data }
}
impl<'a, T> DerefMut for StateGuard<'a, T> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.state.as_mut().unwrap().data }
}
impl<'a, T> Drop for StateGuard<'a, T> {
fn drop(&mut self) {
let meta = self.state.take().unwrap().meta.clone();
StateSliceMeta::trigger_update(&meta);
}
}
impl<T: 'static> State<T> {
pub fn new(initial: T) -> Self { State(Rc::new(RefCell::new(StateSlice::new(initial)))) }
pub fn update<'a>(&'a self) -> impl DerefMut<Target = T> + 'a {
StateGuard { state: Some(self.0.borrow_mut()) }
}
pub fn view<'a>(&'a self) -> impl Deref<Target = T> + 'a { Ref::map(self.0.borrow(), StateSlice::view) }
pub fn subscribe_key(&self, f: impl FnMut() + 'static) -> SubscriptionKey {
self.0.borrow().subscribe_key(f)
}
#[must_use]
pub fn subscribe(&self, f: impl FnMut() + 'static) -> Subscription {
let state_slice = self.0.borrow();
Subscription(Rc::downgrade(&state_slice.meta), state_slice.subscribe_key(f))
}
fn unsubscribe(&self, key: SubscriptionKey) { self.0.borrow().unsubscribe(key) }
}
#[macro_export]
macro_rules! __view {
($($element:ident).*) => {
$($element.view()).*
};
}
#[macro_export]
macro_rules! __update {
($($element:ident).*) => {
$($element.update()).*
};
}