dbc_rs/receivers/
core.rs

1use super::Receivers;
2use crate::{
3    MAX_NAME_SIZE, MAX_RECEIVER_NODES,
4    compat::{String, Vec},
5};
6
7impl Receivers {
8    pub(crate) fn new_broadcast() -> Self {
9        Receivers::Broadcast
10    }
11
12    pub(crate) fn new_none() -> Self {
13        Receivers::None
14    }
15
16    #[cfg(feature = "std")]
17    pub(crate) fn new_nodes(nodes: &[String<{ MAX_NAME_SIZE }>]) -> Self {
18        // Validation should have been done prior (by builder or parse)
19        let vec_nodes: Vec<String<{ MAX_NAME_SIZE }>, { MAX_RECEIVER_NODES }> =
20            nodes.iter().take(MAX_RECEIVER_NODES).cloned().collect();
21        Receivers::Nodes(vec_nodes)
22    }
23
24    /// Returns an iterator over the receiver node names.
25    ///
26    /// For `Receivers::Broadcast` and `Receivers::None`, the iterator will be empty.
27    /// For `Receivers::Nodes`, it iterates over the specific node names.
28    ///
29    /// # Examples
30    ///
31    /// ```rust,no_run
32    /// use dbc_rs::Dbc;
33    ///
34    /// let dbc = Dbc::parse(r#"VERSION "1.0"
35    ///
36    /// BU_: ECM TCM BCM
37    ///
38    /// BO_ 256 Engine : 8 ECM
39    ///  SG_ Temp : 0|8@1+ (1,0) [0|255] "°C" TCM BCM
40    /// "#)?;
41    ///
42    /// let message = dbc.messages().at(0).unwrap();
43    /// let signal = message.signals().at(0).unwrap();
44    ///
45    /// // Iterate over receiver nodes
46    /// let mut iter = signal.receivers().iter();
47    /// assert_eq!(iter.next().map(|s| s.to_string()), Some("TCM".to_string()));
48    /// assert_eq!(iter.next().map(|s| s.to_string()), Some("BCM".to_string()));
49    /// assert_eq!(iter.next(), None);
50    /// # Ok::<(), dbc_rs::Error>(())
51    /// ```
52    ///
53    /// # Broadcast and None
54    ///
55    /// ```rust,no_run
56    /// use dbc_rs::Dbc;
57    ///
58    /// let dbc = Dbc::parse(r#"VERSION "1.0"
59    ///
60    /// BU_: ECM
61    ///
62    /// BO_ 256 Engine : 8 ECM
63    ///  SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm" *
64    /// "#)?;
65    ///
66    /// let message = dbc.messages().at(0).unwrap();
67    /// let signal = message.signals().at(0).unwrap();
68    ///
69    /// // Broadcast receivers return empty iterator
70    /// assert_eq!(signal.receivers().iter().count(), 0);
71    /// # Ok::<(), dbc_rs::Error>(())
72    /// ```
73    #[inline]
74    #[must_use = "iterator is lazy and does nothing unless consumed"]
75    pub fn iter(&self) -> impl Iterator<Item = String<{ MAX_NAME_SIZE }>> {
76        match self {
77            Receivers::Nodes(nodes) => ReceiversIter {
78                nodes: Some(nodes.clone()),
79                pos: 0,
80            },
81            _ => ReceiversIter {
82                nodes: None,
83                pos: 0,
84            },
85        }
86    }
87
88    /// Returns the number of receiver nodes.
89    ///
90    /// - For `Receivers::Nodes`: Returns the count of specific receiver nodes
91    /// - For `Receivers::Broadcast` and `Receivers::None`: Returns `0`
92    ///
93    /// # Examples
94    ///
95    /// ```rust,no_run
96    /// use dbc_rs::Dbc;
97    ///
98    /// let dbc = Dbc::parse(r#"VERSION "1.0"
99    ///
100    /// BU_: ECM TCM BCM
101    ///
102    /// BO_ 256 Engine : 8 ECM
103    ///  SG_ Temp : 0|8@1+ (1,0) [0|255] "°C" TCM BCM
104    /// "#)?;
105    ///
106    /// let message = dbc.messages().at(0).unwrap();
107    /// let signal = message.signals().at(0).unwrap();
108    /// assert_eq!(signal.receivers().len(), 2);
109    /// # Ok::<(), dbc_rs::Error>(())
110    /// ```
111    #[inline]
112    #[must_use]
113    pub fn len(&self) -> usize {
114        match self {
115            Receivers::Nodes(nodes) => nodes.len(),
116            Receivers::Broadcast | Receivers::None => 0,
117        }
118    }
119
120    /// Returns `true` if there are no specific receiver nodes.
121    ///
122    /// This returns `true` for both `Receivers::Broadcast` and `Receivers::None`,
123    /// as neither has specific node names.
124    ///
125    /// # Examples
126    ///
127    /// ```rust,no_run
128    /// use dbc_rs::Dbc;
129    ///
130    /// let dbc = Dbc::parse(r#"VERSION "1.0"
131    ///
132    /// BU_: ECM
133    ///
134    /// BO_ 256 Engine : 8 ECM
135    ///  SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm"
136    /// "#)?;
137    ///
138    /// let message = dbc.messages().at(0).unwrap();
139    /// let signal = message.signals().at(0).unwrap();
140    /// assert!(signal.receivers().is_empty());
141    /// # Ok::<(), dbc_rs::Error>(())
142    /// ```
143    #[inline]
144    #[must_use]
145    pub fn is_empty(&self) -> bool {
146        self.len() == 0
147    }
148
149    /// Checks if a node name is in the receivers list.
150    ///
151    /// For `Receivers::Broadcast` and `Receivers::None`, this always returns `false`.
152    /// For `Receivers::Nodes`, it checks if the node name is in the list.
153    ///
154    /// # Arguments
155    ///
156    /// * `node` - The node name to check
157    ///
158    /// # Examples
159    ///
160    /// ```rust,no_run
161    /// use dbc_rs::Dbc;
162    ///
163    /// let dbc = Dbc::parse(r#"VERSION "1.0"
164    ///
165    /// BU_: ECM TCM BCM
166    ///
167    /// BO_ 256 Engine : 8 ECM
168    ///  SG_ Temp : 0|8@1+ (1,0) [0|255] "°C" TCM BCM
169    /// "#)?;
170    ///
171    /// let message = dbc.messages().at(0).unwrap();
172    /// let signal = message.signals().at(0).unwrap();
173    ///
174    /// assert!(signal.receivers().contains("TCM"));
175    /// assert!(signal.receivers().contains("BCM"));
176    /// assert!(!signal.receivers().contains("ECM"));
177    /// # Ok::<(), dbc_rs::Error>(())
178    /// ```
179    #[inline]
180    #[must_use]
181    pub fn contains(&self, node: &str) -> bool {
182        self.iter().any(|n| n.as_str() == node)
183    }
184
185    /// Gets a receiver node by index.
186    ///
187    /// Returns `None` if:
188    /// - The index is out of bounds
189    /// - The receiver is `Broadcast` or `None`
190    ///
191    /// # Arguments
192    ///
193    /// * `index` - The zero-based index of the receiver node
194    ///
195    /// # Examples
196    ///
197    /// ```rust,no_run
198    /// use dbc_rs::Dbc;
199    ///
200    /// let dbc = Dbc::parse(r#"VERSION "1.0"
201    ///
202    /// BU_: ECM TCM BCM
203    ///
204    /// BO_ 256 Engine : 8 ECM
205    ///  SG_ Temp : 0|8@1+ (1,0) [0|255] "°C" TCM BCM
206    /// "#)?;
207    ///
208    /// let message = dbc.messages().at(0).unwrap();
209    /// let signal = message.signals().at(0).unwrap();
210    ///
211    /// assert_eq!(signal.receivers().at(0), Some("TCM"));
212    /// assert_eq!(signal.receivers().at(1), Some("BCM"));
213    /// assert_eq!(signal.receivers().at(2), None);
214    /// # Ok::<(), dbc_rs::Error>(())
215    /// ```
216    #[inline]
217    #[must_use]
218    pub fn at(&self, index: usize) -> Option<&str> {
219        match self {
220            Receivers::Nodes(nodes) => nodes.get(index).map(|s| s.as_str()),
221            Receivers::Broadcast | Receivers::None => None,
222        }
223    }
224}
225
226struct ReceiversIter {
227    nodes: Option<Vec<String<{ MAX_NAME_SIZE }>, { MAX_RECEIVER_NODES }>>,
228    pos: usize,
229}
230
231impl Iterator for ReceiversIter {
232    type Item = String<{ MAX_NAME_SIZE }>;
233    fn next(&mut self) -> Option<Self::Item> {
234        if let Some(nodes) = &self.nodes {
235            if self.pos < nodes.len() {
236                let result: String<{ MAX_NAME_SIZE }> = nodes[self.pos].clone();
237                self.pos += 1;
238                Some(result)
239            } else {
240                None
241            }
242        } else {
243            None
244        }
245    }
246}
247
248#[cfg(test)]
249mod tests {
250    use super::Receivers;
251    use crate::Parser;
252
253    // Tests for new_broadcast()
254    mod test_new_broadcast {
255        use super::*;
256
257        #[test]
258        fn test_receivers_broadcast() {
259            let broadcast = Receivers::new_broadcast();
260            assert_eq!(broadcast.len(), 0);
261            assert!(broadcast.is_empty());
262        }
263    }
264
265    // Tests for new_none()
266    mod test_new_none {
267        use super::*;
268
269        #[test]
270        fn test_receivers_none() {
271            let none = Receivers::new_none();
272            assert_eq!(none.len(), 0);
273            assert!(none.is_empty());
274        }
275    }
276
277    // Tests for iter()
278    mod test_iter {
279        use super::*;
280
281        #[test]
282        fn test_receivers_iter() {
283            let input = "TCM BCM";
284            let mut parser = Parser::new(input.as_bytes()).unwrap();
285            let result = Receivers::parse(&mut parser).unwrap();
286            let mut iter = result.iter();
287            assert_eq!(iter.next().unwrap().as_str(), "TCM");
288            assert_eq!(iter.next().unwrap().as_str(), "BCM");
289            assert!(iter.next().is_none());
290
291            let broadcast = Receivers::new_broadcast();
292            assert_eq!(broadcast.iter().count(), 0);
293
294            let none = Receivers::new_none();
295            assert_eq!(none.iter().count(), 0);
296        }
297    }
298
299    // Tests for len()
300    mod test_len {
301        use super::*;
302
303        #[test]
304        fn test_receivers_len() {
305            let broadcast = Receivers::new_broadcast();
306            assert_eq!(broadcast.len(), 0);
307
308            let none = Receivers::new_none();
309            assert_eq!(none.len(), 0);
310
311            let input = "TCM BCM";
312            let mut parser = Parser::new(input.as_bytes()).unwrap();
313            let nodes = Receivers::parse(&mut parser).unwrap();
314            assert_eq!(nodes.len(), 2);
315        }
316    }
317
318    // Tests for is_empty()
319    mod test_is_empty {
320        use super::*;
321
322        #[test]
323        fn test_receivers_is_empty() {
324            let broadcast = Receivers::new_broadcast();
325            assert!(broadcast.is_empty());
326
327            let none = Receivers::new_none();
328            assert!(none.is_empty());
329
330            let input = "TCM";
331            let mut parser = Parser::new(input.as_bytes()).unwrap();
332            let nodes = Receivers::parse(&mut parser).unwrap();
333            assert!(!nodes.is_empty());
334        }
335    }
336
337    // Tests for contains()
338    mod test_contains {
339        use super::*;
340
341        #[test]
342        fn test_receivers_contains() {
343            let input = "TCM BCM";
344            let mut parser = Parser::new(input.as_bytes()).unwrap();
345            let result = Receivers::parse(&mut parser).unwrap();
346            assert!(result.contains("TCM"));
347            assert!(result.contains("BCM"));
348            assert!(!result.contains("ECM"));
349
350            let broadcast = Receivers::new_broadcast();
351            assert!(!broadcast.contains("TCM"));
352
353            let none = Receivers::new_none();
354            assert!(!none.contains("TCM"));
355        }
356    }
357
358    // Tests for at()
359    mod test_at {
360        use super::*;
361
362        #[test]
363        fn test_receivers_at() {
364            let input = "TCM BCM";
365            let mut parser = Parser::new(input.as_bytes()).unwrap();
366            let result = Receivers::parse(&mut parser).unwrap();
367            assert_eq!(result.at(0), Some("TCM"));
368            assert_eq!(result.at(1), Some("BCM"));
369            assert_eq!(result.at(2), None);
370
371            let broadcast = Receivers::new_broadcast();
372            assert_eq!(broadcast.at(0), None);
373
374            let none = Receivers::new_none();
375            assert_eq!(none.at(0), None);
376        }
377    }
378}