iron_ingot/any/
reactive.rs1use crate::{IDManager, Shared};
2
3use std::{
4 any::type_name,
5 cell::{Ref, RefCell, RefMut},
6 fmt::{self, Debug, Formatter},
7 marker::PhantomData,
8 mem::transmute,
9 rc::Rc,
10};
11
12struct Child<T: ?Sized, R: ?Sized + Debug = dyn Debug> {
13 reactive: Shared<Reactive<R>>,
14 on_change: Box<dyn FnMut(&T) -> Box<R>>,
15}
16
17impl<T: ?Sized, R: ?Sized + Debug> Debug for Child<T, R> {
18 fn fmt(&self, formatter: &mut Formatter<'_>) -> Result<(), fmt::Error> {
19 formatter
20 .debug_struct(&format!(
21 "Child<{}, {}>",
22 type_name::<T>(),
23 type_name::<R>()
24 ))
25 .field("reactive", &self.reactive)
26 .finish_non_exhaustive()
27 }
28}
29
30#[derive(Debug)]
31pub struct Handle<T: ?Sized>(Shared<Reactive<dyn Debug>>, PhantomData<T>);
32
33impl<T: ?Sized> Handle<T> {
34 fn new(value: Shared<Reactive<dyn Debug>>) -> Self {
35 Self(value, PhantomData)
36 }
37
38 pub fn borrow(&self) -> Ref<Reactive<T>> {
39 unsafe { transmute::<_, &Shared<_>>(&self.0) }.borrow()
42 }
43
44 pub fn borrow_mut(&self) -> RefMut<Reactive<T>> {
45 unsafe { transmute::<_, &Shared<_>>(&self.0) }.borrow_mut()
48 }
49}
50
51impl<T: ?Sized> Clone for Handle<T> {
52 fn clone(&self) -> Self {
53 Self(Rc::clone(&self.0), PhantomData)
54 }
55}
56
57impl<T: Debug + 'static> Handle<T> {
58 pub fn from(value: T) -> Self {
59 Self(
60 Rc::new(RefCell::new(Reactive::new(Box::new(value), None))),
61 PhantomData,
62 )
63 }
64}
65
66impl<T: ?Sized> From<Shared<Reactive<dyn Debug>>> for Handle<T> {
67 fn from(value: Shared<Reactive<dyn Debug>>) -> Self {
68 Self(value, PhantomData)
69 }
70}
71
72impl<T: ?Sized> From<Reactive<dyn Debug>> for Handle<T> {
73 fn from(value: Reactive<dyn Debug>) -> Self {
74 Self(Rc::new(RefCell::new(value)), PhantomData)
75 }
76}
77
78#[derive(Debug)]
82pub struct Reactive<T: ?Sized> {
83 watcher_id_manager: IDManager,
84 id: usize,
85 watcher_id: Option<usize>,
86 children: Vec<Option<Child<T>>>,
87 value: Box<T>,
88}
89
90impl<T: ?Sized> Reactive<T> {
91 fn new(value: Box<T>, watcher_id: Option<usize>) -> Self {
92 static mut ID_MANAGER: IDManager = IDManager::new();
93 Self {
94 watcher_id_manager: IDManager::new(),
95
96 id: unsafe { ID_MANAGER.next() }.unwrap(),
98
99 watcher_id,
100 children: vec![],
101 value,
102 }
103 }
104
105 pub fn get_id(&self) -> usize {
106 self.id
107 }
108
109 pub fn get_value(&self) -> &T {
110 &self.value
111 }
112
113 pub(crate) unsafe fn get_value_mut(&mut self) -> &mut T {
122 &mut self.value
123 }
124
125 pub(crate) unsafe fn wake_children(&mut self) {
133 for child in &mut self.children.iter_mut().flatten() {
134 child
135 .reactive
136 .borrow_mut()
137 .set_boxed_value((child.on_change)(&*self.value));
138 }
139 }
140
141 pub fn watch<U: Debug + 'static>(
148 &mut self,
149 mut on_change: impl FnMut(&T) -> U + 'static,
150 ) -> Handle<U> {
151 let watcher_id = self.watcher_id_manager.next().unwrap();
152 let reactive: Shared<Reactive<dyn Debug>> = Rc::new(RefCell::new(Reactive::new(
153 Box::new(on_change(&self.value)),
154 Some(watcher_id),
155 )));
156 let child: Child<_, dyn Debug> = Child {
157 on_change: Box::new(move |value| Box::new(on_change(value))),
158 reactive: Rc::clone(&reactive),
159 };
160 if watcher_id == self.children.len() {
161 self.children.push(Some(child));
162 } else {
163 self.children[watcher_id] = Some(child);
164 }
165 Handle::new(reactive)
166 }
167
168 pub fn unwatch<U: ?Sized + Debug>(&mut self, reactive: Handle<U>) {
173 let watcher_id = reactive.borrow().watcher_id.unwrap();
174 self.children[watcher_id] = None;
175 self.watcher_id_manager.free(watcher_id).unwrap();
176 }
177}
178
179impl<T: ?Sized + Debug> Reactive<T> {
180 fn set_boxed_value(&mut self, value: Box<T>) {
181 if format!("{:?}", &*self.value) == format!("{:?}", &*value) {
182 return;
183 }
184 self.value = value;
185
186 unsafe { self.wake_children() };
188 }
189}
190
191impl<T> Reactive<T> {
192 pub fn into_value(self) -> T {
193 *self.value
194 }
195}
196
197impl<T: Debug> Reactive<T> {
198 pub fn set_value(&mut self, value: T) {
199 self.set_boxed_value(Box::new(value));
200 }
201}
202
203impl<T: ?Sized> From<Handle<T>> for Shared<Reactive<dyn Debug>> {
204 fn from(value: Handle<T>) -> Self {
205 value.0
206 }
207}
208
209impl<T: ?Sized> From<Handle<T>> for Reactive<dyn Debug> {
210 fn from(value: Handle<T>) -> Self {
211 Rc::try_unwrap(value.0)
212 .expect(
213 "value should be the only reactive handle instance to a particular reactive object exists at the current moment!"
214 )
215 .into_inner()
216 }
217}
218
219impl<T: Debug> From<Handle<T>> for Reactive<T> {
220 fn from(value: Handle<T>) -> Self {
221 Rc::try_unwrap(unsafe { transmute::<_, Shared<_>>(value.0) })
224 .expect(
225 "value should be the only reactive handle instance to a particular reactive object exists at the current moment!"
226 )
227 .into_inner()
228 }
229}