dbc_rs/nodes/impls.rs
1use super::{InnerNodes, Node, Nodes};
2
3impl Nodes {
4 pub(crate) fn new(nodes: InnerNodes) -> Self {
5 // Validation should have been done prior (by builder)
6 Self { nodes }
7 }
8
9 /// Returns an iterator over the node names.
10 ///
11 /// # Examples
12 ///
13 /// ```rust,no_run
14 /// use dbc_rs::Dbc;
15 ///
16 /// let dbc = Dbc::parse(r#"VERSION "1.0"
17 ///
18 /// BU_: ECM TCM BCM
19 /// "#)?;
20 ///
21 /// // Iterate over nodes
22 /// let mut iter = dbc.nodes().iter();
23 /// assert_eq!(iter.next(), Some("ECM"));
24 /// assert_eq!(iter.next(), Some("TCM"));
25 /// assert_eq!(iter.next(), Some("BCM"));
26 /// assert_eq!(iter.next(), None);
27 ///
28 /// // Or use in a loop
29 /// for node in dbc.nodes().iter() {
30 /// println!("Node: {}", node);
31 /// }
32 /// # Ok::<(), dbc_rs::Error>(())
33 /// ```
34 #[inline]
35 #[must_use = "iterator is lazy and does nothing unless consumed"]
36 pub fn iter(&self) -> impl Iterator<Item = &str> + '_ {
37 self.nodes.iter().map(|node| node.name())
38 }
39
40 /// Returns an iterator over the node structs.
41 ///
42 /// This provides access to both the node name and its comment.
43 ///
44 /// # Examples
45 ///
46 /// ```rust,no_run
47 /// use dbc_rs::Dbc;
48 ///
49 /// let dbc = Dbc::parse(r#"VERSION "1.0"
50 ///
51 /// BU_: ECM TCM
52 ///
53 /// BO_ 256 Engine : 8 ECM
54 ///
55 /// CM_ BU_ ECM "Engine Control Module";
56 /// "#)?;
57 ///
58 /// for node in dbc.nodes().iter_nodes() {
59 /// println!("Node: {}", node.name());
60 /// if let Some(comment) = node.comment() {
61 /// println!(" Comment: {}", comment);
62 /// }
63 /// }
64 /// # Ok::<(), dbc_rs::Error>(())
65 /// ```
66 #[inline]
67 #[must_use = "iterator is lazy and does nothing unless consumed"]
68 pub fn iter_nodes(&self) -> impl Iterator<Item = &Node> + '_ {
69 self.nodes.iter()
70 }
71
72 /// Checks if a node name is in the list.
73 ///
74 /// The check is case-sensitive.
75 ///
76 /// # Arguments
77 ///
78 /// * `node` - The node name to check
79 ///
80 /// # Examples
81 ///
82 /// ```rust,no_run
83 /// use dbc_rs::Dbc;
84 ///
85 /// let dbc = Dbc::parse(r#"VERSION "1.0"
86 ///
87 /// BU_: ECM TCM
88 /// "#)?;
89 ///
90 /// assert!(dbc.nodes().contains("ECM"));
91 /// assert!(dbc.nodes().contains("TCM"));
92 /// assert!(!dbc.nodes().contains("BCM"));
93 /// assert!(!dbc.nodes().contains("ecm")); // Case-sensitive
94 /// # Ok::<(), dbc_rs::Error>(())
95 /// ```
96 #[inline]
97 #[must_use = "return value should be used"]
98 pub fn contains(&self, node: &str) -> bool {
99 self.iter().any(|n| n == node)
100 }
101
102 /// Returns the number of nodes in the collection.
103 ///
104 /// # Examples
105 ///
106 /// ```rust,no_run
107 /// use dbc_rs::Dbc;
108 ///
109 /// let dbc = Dbc::parse(r#"VERSION "1.0"
110 ///
111 /// BU_: ECM TCM BCM
112 /// "#)?;
113 ///
114 /// assert_eq!(dbc.nodes().len(), 3);
115 /// # Ok::<(), dbc_rs::Error>(())
116 /// ```
117 #[inline]
118 #[must_use = "return value should be used"]
119 pub fn len(&self) -> usize {
120 self.nodes.len()
121 }
122
123 /// Returns `true` if there are no nodes in the collection.
124 ///
125 /// # Examples
126 ///
127 /// ```rust,no_run
128 /// use dbc_rs::Dbc;
129 ///
130 /// // Empty node list
131 /// let dbc = Dbc::parse(r#"VERSION "1.0"
132 ///
133 /// BU_:
134 /// "#)?;
135 /// assert!(dbc.nodes().is_empty());
136 ///
137 /// // With nodes
138 /// let dbc2 = Dbc::parse(r#"VERSION "1.0"
139 ///
140 /// BU_: ECM
141 /// "#)?;
142 /// assert!(!dbc2.nodes().is_empty());
143 /// # Ok::<(), dbc_rs::Error>(())
144 /// ```
145 #[inline]
146 #[must_use = "return value should be used"]
147 pub fn is_empty(&self) -> bool {
148 self.nodes.is_empty()
149 }
150
151 /// Gets a node name by index.
152 ///
153 /// Returns `None` if the index is out of bounds.
154 ///
155 /// # Arguments
156 ///
157 /// * `index` - The zero-based index of the node
158 ///
159 /// # Examples
160 ///
161 /// ```rust,no_run
162 /// use dbc_rs::Dbc;
163 ///
164 /// let dbc = Dbc::parse(r#"VERSION "1.0"
165 ///
166 /// BU_: ECM TCM BCM
167 /// "#)?;
168 ///
169 /// assert_eq!(dbc.nodes().at(0), Some("ECM"));
170 /// assert_eq!(dbc.nodes().at(1), Some("TCM"));
171 /// assert_eq!(dbc.nodes().at(2), Some("BCM"));
172 /// assert_eq!(dbc.nodes().at(3), None); // Out of bounds
173 /// # Ok::<(), dbc_rs::Error>(())
174 /// ```
175 #[inline]
176 #[must_use = "return value should be used"]
177 pub fn at(&self, index: usize) -> Option<&str> {
178 self.nodes.get(index).map(|node| node.name())
179 }
180
181 /// Gets a node by index.
182 ///
183 /// Returns `None` if the index is out of bounds.
184 ///
185 /// # Arguments
186 ///
187 /// * `index` - The zero-based index of the node
188 ///
189 /// # Examples
190 ///
191 /// ```rust,no_run
192 /// use dbc_rs::Dbc;
193 ///
194 /// let dbc = Dbc::parse(r#"VERSION "1.0"
195 ///
196 /// BU_: ECM TCM BCM
197 /// "#)?;
198 ///
199 /// let node = dbc.nodes().get(0).unwrap();
200 /// assert_eq!(node.name(), "ECM");
201 /// # Ok::<(), dbc_rs::Error>(())
202 /// ```
203 #[inline]
204 #[must_use = "return value should be used"]
205 pub fn get(&self, index: usize) -> Option<&Node> {
206 self.nodes.get(index)
207 }
208
209 /// Returns the comment for a specific node, if present.
210 ///
211 /// # Examples
212 ///
213 /// ```rust,no_run
214 /// use dbc_rs::Dbc;
215 ///
216 /// let dbc = Dbc::parse(r#"VERSION "1.0"
217 ///
218 /// BU_: ECM TCM
219 ///
220 /// BO_ 256 Engine : 8 ECM
221 ///
222 /// CM_ BU_ ECM "Engine Control Module";
223 /// "#)?;
224 ///
225 /// assert_eq!(dbc.nodes().node_comment("ECM"), Some("Engine Control Module"));
226 /// assert_eq!(dbc.nodes().node_comment("TCM"), None);
227 /// # Ok::<(), dbc_rs::Error>(())
228 /// ```
229 #[inline]
230 #[must_use = "return value should be used"]
231 pub fn node_comment(&self, node_name: &str) -> Option<&str> {
232 self.nodes
233 .iter()
234 .find(|node| node.name() == node_name)
235 .and_then(|node| node.comment())
236 }
237
238 /// Sets the comment for a node by name.
239 ///
240 /// Returns `true` if the node was found and the comment was set,
241 /// `false` if the node was not found.
242 pub(crate) fn set_node_comment(
243 &mut self,
244 node_name: &str,
245 comment: crate::compat::Comment,
246 ) -> bool {
247 if let Some(node) = self.nodes.iter_mut().find(|n| n.name() == node_name) {
248 node.set_comment(comment);
249 true
250 } else {
251 false
252 }
253 }
254}