fdt_edit/node/
mod.rs

1use core::fmt::Debug;
2
3use alloc::{
4    collections::BTreeMap,
5    string::{String, ToString},
6    vec::Vec,
7};
8use fdt_raw::data::StrIter;
9
10use crate::{Phandle, Property, RangesEntry, Status, node::gerneric::NodeRefGen};
11
12mod clock;
13mod display;
14mod gerneric;
15mod interrupt_controller;
16mod iter;
17mod memory;
18mod pci;
19
20pub use clock::*;
21pub use display::*;
22pub use interrupt_controller::*;
23pub use iter::*;
24pub use memory::*;
25pub use pci::*;
26
27/// 节点类型枚举,用于模式匹配
28#[derive(Clone, Debug)]
29pub enum NodeKind<'a> {
30    Clock(NodeRefClock<'a>),
31    Pci(NodeRefPci<'a>),
32    InterruptController(NodeRefInterruptController<'a>),
33    Memory(NodeRefMemory<'a>),
34    Generic(NodeRefGen<'a>),
35}
36
37#[derive(Clone)]
38pub struct Node {
39    pub name: String,
40    /// 属性列表(保持原始顺序)
41    pub(crate) properties: Vec<Property>,
42    /// 属性名到索引的映射(用于快速查找)
43    pub(crate) prop_cache: BTreeMap<String, usize>,
44    children: Vec<Node>,
45    name_cache: BTreeMap<String, usize>,
46}
47
48impl Node {
49    pub fn new(name: &str) -> Self {
50        Self {
51            name: name.to_string(),
52            properties: Vec::new(),
53            prop_cache: BTreeMap::new(),
54            children: Vec::new(),
55            name_cache: BTreeMap::new(),
56        }
57    }
58
59    pub fn name(&self) -> &str {
60        &self.name
61    }
62
63    pub fn properties(&self) -> impl Iterator<Item = &Property> {
64        self.properties.iter()
65    }
66
67    pub fn children(&self) -> &[Node] {
68        &self.children
69    }
70
71    pub fn children_mut(&mut self) -> impl Iterator<Item = &mut Node> {
72        self.children.iter_mut()
73    }
74
75    pub fn add_child(&mut self, child: Node) {
76        let index = self.children.len();
77        self.name_cache.insert(child.name.clone(), index);
78        self.children.push(child);
79    }
80
81    pub fn add_property(&mut self, prop: Property) {
82        let name = prop.name.clone();
83        let index = self.properties.len();
84        self.prop_cache.insert(name, index);
85        self.properties.push(prop);
86    }
87
88    pub fn get_child(&self, name: &str) -> Option<&Node> {
89        if let Some(&index) = self.name_cache.get(name) {
90            if let Some(child) = self.children.get(index) {
91                return Some(child);
92            }
93        }
94
95        // Fallback if the cache is stale
96        self.children.iter().find(|c| c.name == name)
97    }
98
99    pub fn get_child_mut(&mut self, name: &str) -> Option<&mut Node> {
100        if let Some(&index) = self.name_cache.get(name) {
101            if index < self.children.len() && self.children[index].name == name {
102                return self.children.get_mut(index);
103            }
104        }
105
106        // Cache miss or mismatch: search and rebuild cache to keep indices in sync
107        let pos = self.children.iter().position(|c| c.name == name)?;
108        self.rebuild_name_cache();
109        self.children.get_mut(pos)
110    }
111
112    pub fn remove_child(&mut self, name: &str) -> Option<Node> {
113        let index = self
114            .name_cache
115            .get(name)
116            .copied()
117            .filter(|&idx| self.children.get(idx).map(|c| c.name.as_str()) == Some(name))
118            .or_else(|| self.children.iter().position(|c| c.name == name));
119
120        let Some(idx) = index else { return None };
121
122        let removed = self.children.remove(idx);
123        self.rebuild_name_cache();
124        Some(removed)
125    }
126
127    pub fn set_property(&mut self, prop: Property) {
128        let name = prop.name.clone();
129        if let Some(&idx) = self.prop_cache.get(&name) {
130            // 更新已存在的属性
131            self.properties[idx] = prop;
132        } else {
133            // 添加新属性
134            let idx = self.properties.len();
135            self.prop_cache.insert(name, idx);
136            self.properties.push(prop);
137        }
138    }
139
140    pub fn get_property(&self, name: &str) -> Option<&Property> {
141        self.prop_cache.get(name).map(|&idx| &self.properties[idx])
142    }
143
144    pub fn get_property_mut(&mut self, name: &str) -> Option<&mut Property> {
145        self.prop_cache
146            .get(name)
147            .map(|&idx| &mut self.properties[idx])
148    }
149
150    pub fn remove_property(&mut self, name: &str) -> Option<Property> {
151        if let Some(&idx) = self.prop_cache.get(name) {
152            self.prop_cache.remove(name);
153            // 重建索引(移除元素后需要更新后续索引)
154            let prop = self.properties.remove(idx);
155            for (_, v) in self.prop_cache.iter_mut() {
156                if *v > idx {
157                    *v -= 1;
158                }
159            }
160            Some(prop)
161        } else {
162            None
163        }
164    }
165
166    pub fn address_cells(&self) -> Option<u32> {
167        self.get_property("#address-cells")
168            .and_then(|prop| prop.get_u32())
169    }
170
171    pub fn size_cells(&self) -> Option<u32> {
172        self.get_property("#size-cells")
173            .and_then(|prop| prop.get_u32())
174    }
175
176    pub fn phandle(&self) -> Option<Phandle> {
177        self.get_property("phandle")
178            .and_then(|prop| prop.get_u32())
179            .map(Phandle::from)
180    }
181
182    pub fn interrupt_parent(&self) -> Option<Phandle> {
183        self.get_property("interrupt-parent")
184            .and_then(|prop| prop.get_u32())
185            .map(Phandle::from)
186    }
187
188    pub fn status(&self) -> Option<Status> {
189        let prop = self.get_property("status")?;
190        let s = prop.as_str()?;
191        match s {
192            "okay" => Some(Status::Okay),
193            "disabled" => Some(Status::Disabled),
194            _ => None,
195        }
196    }
197
198    pub fn ranges(&self, parent_address_cells: u32) -> Option<Vec<RangesEntry>> {
199        let prop = self.get_property("ranges")?;
200        let mut entries = Vec::new();
201        let mut reader = prop.as_reader();
202
203        // 当前节点的 #address-cells 用于子节点地址
204        let child_address_cells = self.address_cells().unwrap_or(2) as usize;
205        // 父节点的 #address-cells 用于父总线地址
206        let parent_addr_cells = parent_address_cells as usize;
207        // 当前节点的 #size-cells
208        let size_cells = self.size_cells().unwrap_or(1) as usize;
209
210        while let (Some(child_addr), Some(parent_addr), Some(size)) = (
211            reader.read_cells(child_address_cells),
212            reader.read_cells(parent_addr_cells),
213            reader.read_cells(size_cells),
214        ) {
215            entries.push(RangesEntry {
216                child_bus_address: child_addr,
217                parent_bus_address: parent_addr,
218                length: size,
219            });
220        }
221
222        Some(entries)
223    }
224
225    fn rebuild_name_cache(&mut self) {
226        self.name_cache.clear();
227        for (idx, child) in self.children.iter().enumerate() {
228            self.name_cache.insert(child.name.clone(), idx);
229        }
230    }
231
232    pub fn compatible(&self) -> Option<StrIter<'_>> {
233        let prop = self.get_property("compatible")?;
234        Some(prop.as_str_iter())
235    }
236
237    pub fn compatibles(&self) -> impl Iterator<Item = &str> {
238        self.get_property("compatible")
239            .map(|prop| prop.as_str_iter())
240            .into_iter()
241            .flatten()
242    }
243
244    pub fn device_type(&self) -> Option<&str> {
245        let prop = self.get_property("device_type")?;
246        prop.as_str()
247    }
248
249    /// 通过精确路径删除子节点及其子树
250    /// 只支持精确路径匹配,不支持模糊匹配
251    ///
252    /// # 参数
253    /// - `path`: 删除路径,格式如 "soc/gpio@1000" 或 "/soc/gpio@1000"
254    ///
255    /// # 返回值
256    /// `Ok(Option<Node>)`: 如果找到并删除了节点,返回被删除的节点;如果路径不存在,返回 None
257    /// `Err(FdtError)`: 如果路径格式无效
258    ///
259    /// # 示例
260    /// ```rust
261    /// # use fdt_edit::Node;
262    /// let mut root = Node::new("");
263    /// // 添加测试节点
264    /// let mut soc = Node::new("soc");
265    /// soc.add_child(Node::new("gpio@1000"));
266    /// root.add_child(soc);
267    ///
268    /// // 精确删除节点
269    /// let removed = root.remove_by_path("soc/gpio@1000")?;
270    /// assert!(removed.is_some());
271    /// # Ok::<(), fdt_raw::FdtError>(())
272    /// ```
273    pub fn remove_by_path(&mut self, path: &str) -> Result<Option<Node>, fdt_raw::FdtError> {
274        let normalized_path = path.trim_start_matches('/');
275        if normalized_path.is_empty() {
276            return Err(fdt_raw::FdtError::InvalidInput);
277        }
278
279        let parts: Vec<&str> = normalized_path.split('/').collect();
280        if parts.is_empty() {
281            return Err(fdt_raw::FdtError::InvalidInput);
282        }
283        if parts.len() == 1 {
284            // 删除直接子节点(精确匹配)
285            let child_name = parts[0];
286            Ok(self.remove_child(child_name))
287        } else {
288            // 需要递归到父节点进行删除
289            self.remove_child_recursive(&parts, 0)
290        }
291    }
292
293    /// 递归删除子节点的实现
294    /// 找到要删除节点的父节点,然后从父节点中删除目标子节点
295    fn remove_child_recursive(
296        &mut self,
297        parts: &[&str],
298        index: usize,
299    ) -> Result<Option<Node>, fdt_raw::FdtError> {
300        if index >= parts.len() - 1 {
301            // 已经到达要删除节点的父级
302            let child_name_to_remove = parts[index];
303            Ok(self.remove_child(child_name_to_remove))
304        } else {
305            // 继续向下递归
306            let current_part = parts[index];
307
308            // 中间级别只支持精确匹配(使用缓存)
309            if let Some(&child_index) = self.name_cache.get(current_part) {
310                self.children[child_index].remove_child_recursive(parts, index + 1)
311            } else {
312                // 路径不存在
313                Ok(None)
314            }
315        }
316    }
317}
318
319impl From<&fdt_raw::Node<'_>> for Node {
320    fn from(raw: &fdt_raw::Node<'_>) -> Self {
321        let mut new_node = Node::new(raw.name());
322        // 复制属性
323        for raw_prop in raw.properties() {
324            let prop = Property::from(&raw_prop);
325            new_node.set_property(prop);
326        }
327        new_node
328    }
329}