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