1use crate::platform::{NativeHandle, ViewType, PropsDiff, PropValue};
11use rustc_hash::FxHashMap;
12use std::collections::HashMap;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct NodeId(pub u64);
18
19impl std::fmt::Display for NodeId {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "node#{}", self.0)
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct ShadowNode {
28 pub id: NodeId,
29 pub view_type: ViewType,
30 pub parent: Option<NodeId>,
31 pub children: Vec<NodeId>,
32 pub props: HashMap<String, PropValue>,
33 pub native_handle: Option<NativeHandle>,
34
35 pending_props: PropsDiff,
37
38 pub component_name: Option<String>,
40}
41
42pub struct ShadowTree {
44 nodes: FxHashMap<NodeId, ShadowNode>,
45 root: Option<NodeId>,
46}
47
48impl ShadowTree {
49 pub fn new() -> Self {
50 Self {
51 nodes: FxHashMap::default(),
52 root: None,
53 }
54 }
55
56 pub fn create_node(
59 &mut self,
60 id: NodeId,
61 view_type: ViewType,
62 initial_props: HashMap<String, PropValue>,
63 ) {
64 let pending = PropsDiff {
65 changes: initial_props.clone(),
66 };
67
68 let node = ShadowNode {
69 id,
70 view_type,
71 parent: None,
72 children: Vec::new(),
73 props: initial_props,
74 native_handle: None,
75 pending_props: pending,
76 component_name: None,
77 };
78
79 self.nodes.insert(id, node);
80 }
81
82 pub fn set_root(&mut self, id: NodeId) {
84 self.root = Some(id);
85 }
86
87 pub fn root(&self) -> Option<NodeId> {
89 self.root
90 }
91
92 pub fn get(&self, id: NodeId) -> Option<&ShadowNode> {
94 self.nodes.get(&id)
95 }
96
97 pub fn get_mut(&mut self, id: NodeId) -> Option<&mut ShadowNode> {
99 self.nodes.get_mut(&id)
100 }
101
102 pub fn update_props(&mut self, id: NodeId, diff: &PropsDiff) {
105 if let Some(node) = self.nodes.get_mut(&id) {
106 for (key, value) in &diff.changes {
107 node.props.insert(key.clone(), value.clone());
108 node.pending_props.set(key.clone(), value.clone());
109 }
110 }
111 }
112
113 pub fn append_child(&mut self, parent_id: NodeId, child_id: NodeId) {
115 if let Some(child) = self.nodes.get_mut(&child_id) {
117 child.parent = Some(parent_id);
118 }
119
120 if let Some(parent) = self.nodes.get_mut(&parent_id) {
122 if !parent.children.contains(&child_id) {
123 parent.children.push(child_id);
124 }
125 }
126 }
127
128 pub fn insert_before(
130 &mut self,
131 parent_id: NodeId,
132 child_id: NodeId,
133 before_id: NodeId,
134 ) {
135 if let Some(child) = self.nodes.get_mut(&child_id) {
136 child.parent = Some(parent_id);
137 }
138
139 if let Some(parent) = self.nodes.get_mut(&parent_id) {
140 if let Some(pos) = parent.children.iter().position(|&c| c == before_id) {
141 parent.children.insert(pos, child_id);
142 } else {
143 parent.children.push(child_id);
144 }
145 }
146 }
147
148 pub fn remove_child(&mut self, parent_id: NodeId, child_id: NodeId) {
150 if let Some(parent) = self.nodes.get_mut(&parent_id) {
152 parent.children.retain(|&c| c != child_id);
153 }
154
155 self.remove_subtree(child_id);
157 }
158
159 fn remove_subtree(&mut self, id: NodeId) {
161 let children = self.nodes.get(&id)
162 .map(|n| n.children.clone())
163 .unwrap_or_default();
164
165 for child_id in children {
166 self.remove_subtree(child_id);
167 }
168
169 self.nodes.remove(&id);
170 }
171
172 pub fn set_native_handle(&mut self, id: NodeId, handle: NativeHandle) {
174 if let Some(node) = self.nodes.get_mut(&id) {
175 node.native_handle = Some(handle);
176 }
177 }
178
179 pub fn take_pending_props(&mut self, id: NodeId) -> PropsDiff {
182 self.nodes.get_mut(&id)
183 .map(|n| std::mem::take(&mut n.pending_props))
184 .unwrap_or_default()
185 }
186
187 pub fn children_of(&self, id: NodeId) -> &[NodeId] {
189 self.nodes.get(&id)
190 .map(|n| n.children.as_slice())
191 .unwrap_or(&[])
192 }
193
194 pub fn ancestors(&self, id: NodeId) -> Vec<NodeId> {
197 let mut path = Vec::new();
198 let mut current = Some(id);
199
200 while let Some(nid) = current {
201 path.push(nid);
202 current = self.nodes.get(&nid).and_then(|n| n.parent);
203 }
204
205 path.reverse();
206 path
207 }
208
209 pub fn len(&self) -> usize {
211 self.nodes.len()
212 }
213
214 pub fn is_empty(&self) -> bool {
215 self.nodes.is_empty()
216 }
217
218 pub fn iter(&self) -> impl Iterator<Item = (&NodeId, &ShadowNode)> {
220 self.nodes.iter()
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_create_and_parent() {
230 let mut tree = ShadowTree::new();
231
232 tree.create_node(NodeId(1), ViewType::Container, HashMap::new());
233 tree.create_node(NodeId(2), ViewType::Text, HashMap::new());
234 tree.create_node(NodeId(3), ViewType::Text, HashMap::new());
235
236 tree.set_root(NodeId(1));
237 tree.append_child(NodeId(1), NodeId(2));
238 tree.append_child(NodeId(1), NodeId(3));
239
240 assert_eq!(tree.children_of(NodeId(1)), &[NodeId(2), NodeId(3)]);
241 assert_eq!(tree.get(NodeId(2)).unwrap().parent, Some(NodeId(1)));
242 }
243
244 #[test]
245 fn test_ancestors() {
246 let mut tree = ShadowTree::new();
247
248 tree.create_node(NodeId(1), ViewType::Container, HashMap::new());
249 tree.create_node(NodeId(2), ViewType::Container, HashMap::new());
250 tree.create_node(NodeId(3), ViewType::Text, HashMap::new());
251
252 tree.set_root(NodeId(1));
253 tree.append_child(NodeId(1), NodeId(2));
254 tree.append_child(NodeId(2), NodeId(3));
255
256 let path = tree.ancestors(NodeId(3));
257 assert_eq!(path, vec![NodeId(1), NodeId(2), NodeId(3)]);
258 }
259
260 #[test]
261 fn test_remove_subtree() {
262 let mut tree = ShadowTree::new();
263
264 tree.create_node(NodeId(1), ViewType::Container, HashMap::new());
265 tree.create_node(NodeId(2), ViewType::Container, HashMap::new());
266 tree.create_node(NodeId(3), ViewType::Text, HashMap::new());
267
268 tree.append_child(NodeId(1), NodeId(2));
269 tree.append_child(NodeId(2), NodeId(3));
270
271 tree.remove_child(NodeId(1), NodeId(2));
272
273 assert_eq!(tree.len(), 1); assert!(tree.get(NodeId(2)).is_none());
275 assert!(tree.get(NodeId(3)).is_none());
276 }
277}