devicetree_tool/node.rs
1// Copyright (c) 2023, Michael Zhao
2// SPDX-License-Identifier: MIT
3
4use crate::dts_generator::DtsGenerator;
5use crate::property::Property;
6use std::sync::{Arc, Mutex};
7
8/// A node that is used to describe a device.
9///
10/// A node has a list of properties that are represented with a vector of `Property`.
11///
12/// `Node` can also contain other nodes.
13pub struct Node {
14 pub name: String,
15 pub label: Option<String>,
16 pub properties: Vec<Arc<Mutex<Property>>>,
17 pub sub_nodes: Vec<Arc<Mutex<Node>>>,
18}
19
20impl Node {
21 /// Create an empty `Node` with name.
22 ///
23 /// # Example
24 ///
25 /// ```
26 /// use devicetree_tool::Node;
27 ///
28 /// let node = Node::new("node");
29 ///
30 /// assert_eq!(format!("{}", node), "node {\n};\n");
31 /// ```
32 pub fn new(name: &str) -> Self {
33 Node {
34 name: String::from(name),
35 label: None,
36 properties: Vec::new(),
37 sub_nodes: Vec::new(),
38 }
39 }
40
41 /// Create an empty `Node` with name and label.
42 ///
43 /// # Example
44 ///
45 /// ```
46 /// use devicetree_tool::Node;
47 ///
48 /// let node = Node::new_with_label("node", "label");
49 ///
50 /// assert_eq!(format!("{}", node), "label: node {\n};\n");
51 /// ```
52 pub fn new_with_label(name: &str, label: &str) -> Self {
53 Node {
54 name: String::from(name),
55 label: Some(String::from(label)),
56 properties: Vec::new(),
57 sub_nodes: Vec::new(),
58 }
59 }
60
61 /// Add a `Property` to the `Node`.
62 ///
63 /// # Example
64 ///
65 /// ```
66 /// use devicetree_tool::Node;
67 /// use devicetree_tool::Property;
68 ///
69 /// let mut node = Node::new("node");
70 ///
71 /// node.add_property(Property::new_u32("prop1", 42));
72 /// node.add_property(Property::new_str("prop2", "hello"));
73 ///
74 /// assert_eq!(node.properties.len(), 2);
75 ///
76 /// assert_eq!(format!("{}", node),
77 /// "node {\n\tprop1 = <0x0 0x0 0x0 0x2a>;\n\t\
78 /// prop2 = <0x68 0x65 0x6c 0x6c 0x6f 0x0>;\n};\n");
79 /// ```
80 pub fn add_property(&mut self, prop: Property) {
81 self.properties.push(Arc::new(Mutex::new(prop)));
82 }
83
84 /// Add a sub node to the `Node`.
85 ///
86 /// # Example
87 ///
88 /// ```
89 /// use devicetree_tool::Node;
90 /// use devicetree_tool::Property;
91 ///
92 /// let mut node = Node::new("node");
93 ///
94 /// // Create a sub node
95 /// let mut sub_node = Node::new("sub_node");
96 /// sub_node.add_property(Property::new_u32("prop", 42));
97 ///
98 /// // Add the sub node
99 /// node.add_sub_node(sub_node);
100 ///
101 /// assert_eq!(node.sub_nodes.len(), 1);
102 /// assert_eq!(format!("{}", node),
103 /// "node {\n\n\tsub_node {\n\t\tprop = <0x0 0x0 0x0 0x2a>;\n\t};\n};\n");
104 /// ```
105 pub fn add_sub_node(&mut self, sub_node: Node) {
106 self.sub_nodes.push(Arc::new(Mutex::new(sub_node)));
107 }
108
109 /// Find `Property` from a `Node` by name.
110 ///
111 /// # Example
112 ///
113 /// ```
114 /// use devicetree_tool::Node;
115 /// use devicetree_tool::Property;
116 ///
117 /// let mut node = Node::new("node");
118 ///
119 /// // Now the node hasn't any property
120 /// assert_eq!(node.find_property("prop").is_none(), true);
121 ///
122 /// // Add a property
123 /// node.add_property(Property::new_u32("prop", 42));
124 ///
125 /// // Find the property from the node
126 /// let prop = node.find_property("prop").unwrap();
127 ///
128 /// assert_eq!(prop.lock().unwrap().value, vec![0u8, 0u8, 0u8, 42u8]);
129 /// ```
130 pub fn find_property(&self, name: &str) -> Option<Arc<Mutex<Property>>> {
131 for prop in &self.properties {
132 if name == prop.lock().unwrap().name {
133 return Some(prop.clone());
134 }
135 }
136 None
137 }
138
139 /// Find sub node from a `Node` by name.
140 ///
141 /// # Example
142 ///
143 /// ```
144 /// use devicetree_tool::Node;
145 /// use devicetree_tool::Property;
146 ///
147 /// let mut node = Node::new("node");
148 ///
149 /// // Now the node hasn't any sub node
150 /// assert_eq!(node.find_subnode_by_name("subnode").is_none(), true);
151 ///
152 /// // Add a sub node
153 /// node.add_sub_node(Node::new("subnode"));
154 ///
155 /// // Find the sub node from the node
156 /// let sub_node = node.find_subnode_by_name("subnode").unwrap();
157 ///
158 /// assert_eq!(sub_node.lock().unwrap().name, "subnode");
159 /// ```
160 pub fn find_subnode_by_name(&self, name: &str) -> Option<Arc<Mutex<Node>>> {
161 for sub_node in &self.sub_nodes {
162 if sub_node.lock().unwrap().name == name {
163 return Some(sub_node.clone());
164 }
165 }
166 None
167 }
168
169 /// Find sub node from a `Node` by label.
170 ///
171 /// # Example
172 ///
173 /// ```
174 /// use devicetree_tool::Node;
175 /// use devicetree_tool::Property;
176 ///
177 /// let mut node = Node::new("node");
178 ///
179 /// // Now the node hasn't any sub node
180 /// assert_eq!(node.find_subnode_by_label("label").is_none(), true);
181 ///
182 /// // Add a sub node
183 /// node.add_sub_node(Node::new_with_label("subnode", "label"));
184 ///
185 /// // Find the sub node from the node
186 /// let sub_node = node.find_subnode_by_label("label").unwrap();
187 ///
188 /// assert_eq!(sub_node.lock().unwrap().name, "subnode");
189 /// ```
190 pub fn find_subnode_by_label(&self, label: &str) -> Option<Arc<Mutex<Node>>> {
191 for sub_node in &self.sub_nodes {
192 if let Some(sub_node_label) = &sub_node.lock().unwrap().label {
193 if sub_node_label == label {
194 return Some(sub_node.clone());
195 }
196 }
197 let sub_node_with_label = sub_node.lock().unwrap().find_subnode_by_label(label);
198 if sub_node_with_label.is_some() {
199 return sub_node_with_label;
200 }
201 }
202 None
203 }
204
205 /// Find sub node from a `Node` by path.
206 ///
207 /// # Example
208 ///
209 /// ```
210 /// use devicetree_tool::Node;
211 /// use devicetree_tool::Property;
212 ///
213 /// let mut node_layer_1 = Node::new("node_layer_1");
214 ///
215 /// // Now the node hasn't any sub node
216 /// assert_eq!(node_layer_1.find_subnode_by_path(vec![ "node_layer_2", "node_layer_3"]).is_none(), true);
217 ///
218 /// // Create a layer-2 sub node
219 /// let mut node_layer_2 = Node::new("node_layer_2");
220 ///
221 /// // Add a layer-3 sub node
222 /// node_layer_2.add_sub_node(Node::new("node_layer_3"));
223 ///
224 /// node_layer_1.add_sub_node(node_layer_2);
225 ///
226 /// // Find the layer-3 sub node
227 /// let sub_node = node_layer_1.find_subnode_by_path(vec!["node_layer_2", "node_layer_3"]).unwrap();
228 ///
229 /// assert_eq!(sub_node.lock().unwrap().name, "node_layer_3");
230 /// ```
231 pub fn find_subnode_by_path(&self, path: Vec<&str>) -> Option<Arc<Mutex<Node>>> {
232 for sub_node in &self.sub_nodes {
233 if sub_node.lock().unwrap().name == path[0] {
234 if path.len() == 1 {
235 // Found the matching node
236 return Some(sub_node.clone());
237 } else {
238 // There are more to match
239 let sub_node_with_path = sub_node
240 .lock()
241 .unwrap()
242 .find_subnode_by_path(path[1..].to_vec());
243 if sub_node_with_path.is_some() {
244 return sub_node_with_path;
245 }
246 }
247 }
248 }
249 None
250 }
251}
252
253impl std::fmt::Display for Node {
254 /// Print a `Property` in the format of DTS
255 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
256 let s = DtsGenerator::generate_node(self, 0);
257 writeln!(f, "{s}")
258 }
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264 use crate::property::Property;
265
266 #[test]
267 fn test_node_empty() {
268 let node = Node::new("node");
269 assert_eq!(node.properties.len(), 0);
270 assert_eq!(node.sub_nodes.len(), 0);
271 }
272
273 #[test]
274 fn test_node_sub_nodes() {
275 let mut node = Node::new("node");
276 node.add_sub_node(Node::new("sub_node_0"));
277 node.add_sub_node(Node::new("sub_node_1"));
278 node.add_sub_node(Node::new("sub_node_2"));
279
280 let mut sub_node_3 = Node::new("sub_node_3");
281 sub_node_3.add_sub_node(Node::new("sub_node_30"));
282 sub_node_3.add_sub_node(Node::new("sub_node_31"));
283
284 assert_eq!(sub_node_3.sub_nodes.len(), 2);
285
286 node.add_sub_node(sub_node_3);
287 assert_eq!(node.sub_nodes.len(), 4);
288 }
289
290 #[test]
291 fn test_node_properties() {
292 let mut node = Node::new("node");
293 node.add_property(Property::new_empty("prop0"));
294 node.add_property(Property::new_u32("prop1", 42));
295 assert_eq!(node.properties.len(), 2);
296 }
297
298 #[test]
299 fn test_property_print() {
300 let mut node = Node::new("node");
301 node.add_property(Property::new_u32("prop", 42));
302 let mut sub_node = Node::new("node");
303 sub_node.add_property(Property::new_u32("prop", 12));
304 node.add_sub_node(sub_node);
305
306 let printing = format!("{}", node);
307 assert_eq!(&printing, "node {\n\tprop = <0x0 0x0 0x0 0x2a>;\n\n\tnode {\n\t\tprop = <0x0 0x0 0x0 0xc>;\n\t};\n};\n");
308 }
309
310 #[test]
311 fn test_find_subnode_by_path() {
312 let mut node_layer_1 = Node::new("node_layer_1");
313
314 assert_eq!(
315 node_layer_1
316 .find_subnode_by_path(vec!["node_layer_2", "node_layer_3"])
317 .is_none(),
318 true
319 );
320
321 let mut node_layer_2 = Node::new("node_layer_2");
322 node_layer_2.add_sub_node(Node::new("node_layer_3"));
323 node_layer_1.add_sub_node(node_layer_2);
324
325 let sub_node = node_layer_1
326 .find_subnode_by_path(vec!["node_layer_2", "node_layer_3"])
327 .unwrap();
328 assert_eq!(sub_node.lock().unwrap().name, "node_layer_3");
329 }
330}