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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use std::{
cell::RefCell,
ops::{Deref, DerefMut},
};
use crate::{
construction::{hook::HookBuilder, types::HookReturn},
locking::{SubtreeUnmountedError, UnmountedLock},
};
#[derive(Clone)]
pub struct Reference<T: Default + 'static> {
inside: &'static RefCell<T>,
lock: UnmountedLock,
}
impl<T: Default + 'static> PartialEq for Reference<T> {
fn eq(&self, other: &Reference<T>) -> bool {
self.inside.as_ptr() == other.inside.as_ptr()
}
}
impl<T: Default + 'static> Reference<T> {
pub fn visit_with<Ret: 'static, F: FnOnce(&T) -> Ret>(
&self,
func: F,
) -> Result<Ret, SubtreeUnmountedError> {
if self.lock.is_mounted() {
Ok(func(self.inside.borrow().deref()))
} else {
Err(SubtreeUnmountedError)
}
}
pub fn visit_mut_with<Ret: 'static, F: FnOnce(&mut T) -> Ret>(
&self,
func: F,
) -> Result<Ret, SubtreeUnmountedError> {
if self.lock.is_mounted() {
Ok(func(self.inside.borrow_mut().deref_mut()))
} else {
Err(SubtreeUnmountedError)
}
}
pub fn set_in(&self, value: T) -> Result<(), SubtreeUnmountedError> {
self.visit_mut_with(|v| {
*v = value;
})
}
}
impl<T: Clone + Default + 'static> Reference<T> {
pub fn clone_out(&self) -> Result<T, SubtreeUnmountedError> {
self.visit_with(|v| v.clone())
}
}
pub fn use_ref<T>(cc: HookBuilder, _: ()) -> impl HookReturn<Reference<T>>
where
T: Default + 'static,
{
let cc = cc.init();
let (cc, store): (_, &'static RefCell<T>) = cc.use_one_store();
let reference = Reference {
inside: store,
lock: cc.lock.clone(),
};
(cc, reference)
}