stardom_render/
node.rs

1use std::{
2    cell::{Ref, RefCell, RefMut},
3    rc::{Rc, Weak},
4};
5
6use indexmap::IndexMap;
7use stardom_nodes::{EventKey, Node, NodeType};
8
9#[derive(Clone, Debug)]
10pub struct NodeRef(Rc<RefCell<Inner>>);
11
12type WeakNode = Weak<RefCell<Inner>>;
13
14#[derive(Debug)]
15struct Inner {
16    parent: Option<WeakNode>,
17    kind: NodeKind,
18}
19
20#[derive(Debug)]
21pub(crate) enum NodeKind {
22    Element {
23        namespace: Option<String>,
24        name: String,
25        attrs: IndexMap<String, String>,
26        children: Vec<NodeRef>,
27    },
28    Fragment(Vec<NodeRef>),
29    Text(String),
30    Raw(String),
31}
32
33impl NodeRef {
34    fn new(kind: NodeKind) -> Self {
35        let inner = Inner { parent: None, kind };
36        Self(Rc::new(RefCell::new(inner)))
37    }
38
39    pub(crate) fn kind(&self) -> Ref<NodeKind> {
40        let inner = self.0.borrow();
41        Ref::map(inner, |inner| &inner.kind)
42    }
43
44    fn kind_mut(&self) -> RefMut<NodeKind> {
45        let inner = self.0.borrow_mut();
46        RefMut::map(inner, |inner| &mut inner.kind)
47    }
48
49    fn children_ref(&self) -> Option<Ref<Vec<Self>>> {
50        let inner = self.0.borrow();
51        Ref::filter_map(inner, |inner| match &inner.kind {
52            NodeKind::Element { children, .. } => Some(children),
53            NodeKind::Fragment(children) => Some(children),
54            _ => None,
55        })
56        .ok()
57    }
58
59    fn children_mut(&self) -> Option<RefMut<Vec<Self>>> {
60        let inner = self.0.borrow_mut();
61        RefMut::filter_map(inner, |inner| match &mut inner.kind {
62            NodeKind::Element { children, .. } => Some(children),
63            NodeKind::Fragment(children) => Some(children),
64            _ => None,
65        })
66        .ok()
67    }
68}
69
70impl Node for NodeRef {
71    fn element(namespace: Option<&str>, name: &str) -> Self {
72        let kind = NodeKind::Element {
73            namespace: namespace.map(str::to_string),
74            name: name.to_string(),
75            attrs: IndexMap::new(),
76            children: vec![],
77        };
78        Self::new(kind)
79    }
80
81    fn text() -> Self {
82        let kind = NodeKind::Text(String::new());
83        Self::new(kind)
84    }
85
86    fn fragment() -> Self {
87        let kind = NodeKind::Fragment(vec![]);
88        Self::new(kind)
89    }
90
91    fn raw() -> Self {
92        let kind = NodeKind::Raw(String::new());
93        Self::new(kind)
94    }
95
96    fn ty(&self) -> NodeType {
97        match &*self.kind() {
98            NodeKind::Element { .. } => NodeType::Element,
99            NodeKind::Fragment(_) => NodeType::Fragment,
100            NodeKind::Text(_) => NodeType::Text,
101            NodeKind::Raw(_) => NodeType::Raw,
102        }
103    }
104
105    fn parent(&self) -> Option<Self> {
106        self.0
107            .borrow()
108            .parent
109            .as_ref()
110            .and_then(Weak::upgrade)
111            .map(NodeRef)
112    }
113
114    fn children(&self) -> Vec<Self> {
115        self.children_ref()
116            .expect("only element and fragment nodes can have children")
117            .clone()
118    }
119
120    fn next_sibling(&self) -> Option<Self> {
121        let parent = self.parent()?;
122        let children = parent.children_ref()?;
123
124        let idx = children.iter().position(|node| node == self)?;
125        children.get(idx + 1).cloned()
126    }
127
128    fn insert(&self, child: &Self, before: Option<&Self>) {
129        let mut children = self
130            .children_mut()
131            .expect("only element and fragment nodes can have children");
132        let idx = if let Some(before) = before {
133            children
134                .iter()
135                .position(|node| node == before)
136                .expect("not a parent of insertion point node")
137        } else {
138            children.len()
139        };
140        children.insert(idx, child.clone());
141
142        child.0.borrow_mut().parent.replace(Rc::downgrade(&self.0));
143    }
144
145    fn remove(&self, child: &Self) {
146        let mut children = self
147            .children_mut()
148            .expect("only element and fragment nodes can have children");
149        let idx = children
150            .iter()
151            .position(|node| node == child)
152            .expect("not a parent of child node");
153        children.remove(idx);
154
155        child.0.borrow_mut().parent.take();
156    }
157
158    fn set_text(&self, content: &str) {
159        match &mut self.0.borrow_mut().kind {
160            NodeKind::Text(text) => {
161                *text = content.to_string();
162            }
163            NodeKind::Raw(raw) => {
164                *raw = content.to_string();
165            }
166            _ => panic!("can only set text content of text or raw nodes"),
167        }
168    }
169
170    fn attr(&self, name: &str) -> Option<String> {
171        if let NodeKind::Element { attrs, .. } = &*self.kind() {
172            attrs.get(name).cloned()
173        } else {
174            panic!("attributes only exist on element nodes");
175        }
176    }
177
178    fn set_attr(&self, name: &str, value: &str) {
179        if let NodeKind::Element { attrs, .. } = &mut *self.kind_mut() {
180            attrs.insert(name.to_string(), value.to_string());
181        } else {
182            panic!("attributes only exist on element nodes");
183        }
184    }
185
186    fn remove_attr(&self, name: &str) {
187        if let NodeKind::Element { attrs, .. } = &mut *self.kind_mut() {
188            attrs.remove(name);
189        } else {
190            panic!("attributes only exist on element nodes");
191        }
192    }
193
194    fn event<E, F>(&self, _event: &E, _f: F)
195    where
196        E: EventKey,
197        F: Fn(E::Event) + 'static,
198    {
199        // no-op since events don't exist on renders
200    }
201}
202
203impl PartialEq for NodeRef {
204    fn eq(&self, other: &Self) -> bool {
205        Rc::ptr_eq(&self.0, &other.0)
206    }
207}
208
209impl Eq for NodeRef {}