1use std::any::Any;
2use std::fmt::{Debug, Formatter};
3
4use generational_box::{AnyStorage, UnsyncStorage};
5use slab::Slab;
6
7use crate::map::{HashMapExt, HashSetExt, Map, Set};
8use crate::{Recomposer, Root, Scope, ScopeId, State, StateId};
9
10pub trait Composable {
11 fn compose(&self) -> NodeKey;
12 fn clone_box(&self) -> Box<dyn Composable>;
13}
14
15impl<T> Composable for T
16where
17 T: Fn() -> NodeKey + Clone + 'static,
18{
19 fn compose(&self) -> NodeKey {
20 self()
21 }
22
23 fn clone_box(&self) -> Box<dyn Composable> {
24 Box::new(self.clone())
25 }
26}
27
28impl Clone for Box<dyn Composable> {
29 fn clone(&self) -> Self {
30 self.clone_box()
31 }
32}
33
34pub trait ComposeNode: 'static {
35 type Context;
36}
37
38impl ComposeNode for () {
39 type Context = ();
40}
41
42pub trait AnyData<T> {
43 fn new(val: T) -> Self;
44 fn value(&self) -> &T;
45 fn value_mut(&mut self) -> &mut T;
46}
47
48impl<T> AnyData<T> for Box<dyn Any>
49where
50 T: 'static,
51{
52 #[inline(always)]
53 fn new(val: T) -> Self {
54 Box::new(val)
55 }
56
57 #[inline(always)]
58 fn value(&self) -> &T {
59 self.downcast_ref::<T>().unwrap()
60 }
61
62 #[inline(always)]
63 fn value_mut(&mut self) -> &mut T {
64 self.downcast_mut::<T>().unwrap()
65 }
66}
67
68pub type NodeKey = usize;
69
70#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct Node<T> {
72 pub scope_id: ScopeId,
73 pub parent: NodeKey,
74 pub children: Vec<NodeKey>,
75 pub data: Option<T>,
76}
77
78impl<T> Node<T> {
79 #[inline(always)]
80 pub fn new(scope_id: ScopeId, parent: NodeKey) -> Self {
81 Self {
82 scope_id,
83 parent,
84 children: Vec::new(),
85 data: None,
86 }
87 }
88}
89
90pub struct Composer<N>
91where
92 N: ComposeNode,
93{
94 pub context: N::Context,
95 pub nodes: Slab<Node<N>>,
96 pub(crate) initialized: bool,
97 pub(crate) root_node_key: NodeKey,
98 pub(crate) composables: Map<NodeKey, Box<dyn Composable>>,
99 pub(crate) states: Map<NodeKey, Map<StateId, Box<dyn Any>>>,
100 pub(crate) used_by: Map<StateId, Set<NodeKey>>,
101 pub(crate) uses: Map<NodeKey, Set<StateId>>,
102 pub(crate) current_node_key: NodeKey,
103 pub(crate) key_stack: Vec<usize>,
104 pub(crate) child_idx_stack: Vec<usize>,
105 pub(crate) dirty_states: Set<StateId>,
106 pub(crate) dirty_nodes: Set<NodeKey>,
107 pub(crate) mount_nodes: Set<NodeKey>,
108 pub(crate) unmount_nodes: Set<NodeKey>,
109}
110
111impl<N> Composer<N>
112where
113 N: ComposeNode,
114{
115 pub fn new(context: N::Context) -> Self {
116 Self {
117 context,
118 nodes: Slab::new(),
119 initialized: false,
120 root_node_key: 0,
121 composables: Map::new(),
122 states: Map::new(),
123 used_by: Map::new(),
124 uses: Map::new(),
125 current_node_key: 0,
126 key_stack: Vec::new(),
127 child_idx_stack: Vec::new(),
128 dirty_states: Set::new(),
129 dirty_nodes: Set::new(),
130 mount_nodes: Set::new(),
131 unmount_nodes: Set::new(),
132 }
133 }
134
135 pub fn with_capacity(context: N::Context, capacity: usize) -> Self {
136 Self {
137 context,
138 nodes: Slab::with_capacity(capacity),
139 initialized: false,
140 root_node_key: 0,
141 composables: Map::with_capacity(capacity),
142 states: Map::with_capacity(capacity),
143 used_by: Map::with_capacity(capacity),
144 uses: Map::with_capacity(capacity),
145 current_node_key: 0,
146 child_idx_stack: Vec::new(),
147 key_stack: Vec::new(),
148 dirty_states: Set::new(),
149 dirty_nodes: Set::new(),
150 mount_nodes: Set::with_capacity(capacity),
151 unmount_nodes: Set::new(),
152 }
153 }
154
155 #[track_caller]
157 pub fn compose<R>(root: R, context: N::Context) -> Recomposer<(), N>
158 where
159 R: Fn(Scope<Root, N>),
160 {
161 let owner = UnsyncStorage::owner();
162 let composer = owner.insert(Composer::with_capacity(context, 1024));
163 let id = ScopeId::new();
164 let scope = Scope::new(id, composer);
165 composer.write().start_root(scope.id);
166 let root_state = scope.use_state(|| {});
167 root(scope);
168 composer.write().end_root();
169 let mut c = composer.write();
170 c.initialized = true;
171 Recomposer {
172 owner,
173 composer,
174 root_state,
175 }
176 }
177
178 #[track_caller]
179 pub fn compose_with<R, F, T>(root: R, context: N::Context, state_fn: F) -> Recomposer<T, N>
180 where
181 R: Fn(Scope<Root, N>, State<T, N>),
182 F: Fn() -> T + 'static,
183 T: 'static,
184 {
185 let owner = UnsyncStorage::owner();
186 let composer = owner.insert(Composer::with_capacity(context, 1024));
187 let id = ScopeId::new();
188 let scope = Scope::new(id, composer);
189 composer.write().start_root(scope.id);
190 let root_state = scope.use_state(state_fn);
191 root(scope, root_state);
192 composer.write().end_root();
193 let mut c = composer.write();
194 c.initialized = true;
195 Recomposer {
196 owner,
197 composer,
198 root_state,
199 }
200 }
201
202 #[inline(always)]
203 pub(crate) fn start_root(&mut self, scope_id: ScopeId) {
204 let parent_node_key = 0;
205 let node_key = self.nodes.insert(Node::new(scope_id, parent_node_key));
206 self.child_idx_stack.push(0);
207 self.current_node_key = node_key;
208 }
209
210 #[inline(always)]
211 pub(crate) fn end_root(&mut self) {
212 let child_count = self.child_idx_stack.pop().unwrap();
213 assert_eq!(1, child_count, "Root scope must have exactly one child");
214 self.root_node_key = self.nodes[self.current_node_key].children[0];
215 }
216
217 #[inline(always)]
218 pub(crate) fn start_node(&mut self, parent_node_key: NodeKey, scope_id: ScopeId) {
219 if self.initialized {
220 let child_idx = self.child_idx_stack.last().cloned();
221 if let Some(child_idx) = child_idx {
222 let parent_node = &mut self.nodes[parent_node_key];
223 if child_idx < parent_node.children.len() {
224 let child_key = parent_node.children[child_idx];
225 let child_node = &mut self.nodes[child_key];
226 if child_node.scope_id == scope_id {
227 self.current_node_key = child_key;
229 self.mount_nodes.insert(child_key);
230 self.child_idx_stack.push(0);
231 } else {
232 let node_key = self.nodes.insert(Node::new(scope_id, parent_node_key));
234 self.nodes[parent_node_key].children[child_idx] = node_key;
235 self.unmount_nodes.insert(child_key);
236 self.mount_nodes.insert(node_key);
237 self.current_node_key = node_key;
238 self.child_idx_stack.push(0);
239 }
240 } else {
241 let node_key = self.nodes.insert(Node::new(scope_id, parent_node_key));
243 self.nodes[parent_node_key].children.push(node_key);
244 self.mount_nodes.insert(node_key);
245 self.current_node_key = node_key;
246 self.child_idx_stack.push(0);
247 }
248 } else {
249 self.child_idx_stack.push(0);
251 }
252 } else {
253 let node_key = self.nodes.insert(Node::new(scope_id, parent_node_key));
255 self.nodes[parent_node_key].children.push(node_key);
256 self.current_node_key = node_key;
257 self.child_idx_stack.push(0);
258 }
259 }
260
261 #[inline(always)]
262 pub(crate) fn end_node(&mut self, parent_node_key: NodeKey) {
263 let child_count = self.child_idx_stack.pop().unwrap();
264 let node = &mut self.nodes[self.current_node_key];
265 let old_child_count = node.children.len();
266 if child_count < old_child_count {
267 let unmount_nodes = node.children.drain(child_count..);
268 self.unmount_nodes.extend(unmount_nodes);
269 }
270 if let Some(parent_child_count) = self.child_idx_stack.last_mut() {
271 *parent_child_count += 1;
272 }
273 self.current_node_key = parent_node_key;
274 }
275
276 #[inline(always)]
277 pub(crate) fn skip_node(&mut self, parent_node_key: NodeKey) {
278 let _ = self.child_idx_stack.pop().unwrap();
279 if let Some(parent_child_count) = self.child_idx_stack.last_mut() {
280 *parent_child_count += 1;
281 }
282 self.current_node_key = parent_node_key;
283 }
284}
285
286impl<N> Debug for Composer<N>
287where
288 N: ComposeNode + Debug,
289{
290 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
291 f.debug_struct("Composer")
292 .field("nodes", &self.nodes)
293 .field("states", &self.states)
294 .field("dirty_states", &self.dirty_states)
295 .field("used_by", &self.used_by)
296 .finish()
297 }
298}