dbc_rs/receivers/builder/
mod.rs

1use super::Receivers;
2use crate::{Error, MAX_NAME_SIZE, MAX_NODES, Result};
3use std::{collections::HashSet, string::String};
4
5/// Builder for creating `Receivers` programmatically.
6///
7/// This builder allows you to construct receiver configurations for signals
8/// when building DBC files programmatically.
9///
10/// # Examples
11///
12/// ```rust,no_run
13/// use dbc_rs::{ReceiversBuilder, SignalBuilder, ByteOrder};
14///
15/// // Broadcast receiver
16/// let broadcast = ReceiversBuilder::new().broadcast().build()?;
17///
18/// // Specific nodes
19/// let specific = ReceiversBuilder::new()
20///     .add_node("TCM")
21///     .add_node("BCM")
22///     .build()?;
23///
24/// // No receivers
25/// let none = ReceiversBuilder::new().none().build()?;
26///
27/// // Use with signal builder
28/// let signal = SignalBuilder::new()
29///     .name("RPM")
30///     .start_bit(0)
31///     .length(16)
32///     .byte_order(ByteOrder::BigEndian)
33///     .unsigned(true)
34///     .factor(0.25)
35///     .offset(0.0)
36///     .min(0.0)
37///     .max(8000.0)
38///     .receivers(ReceiversBuilder::new().add_node("TCM").add_node("BCM"))
39///     .build()?;
40/// # Ok::<(), dbc_rs::Error>(())
41/// ```
42///
43/// # Feature Requirements
44///
45/// This builder requires the `std` feature to be enabled.
46#[derive(Debug, Clone)]
47pub struct ReceiversBuilder {
48    is_broadcast: bool,
49    nodes: Vec<String>,
50}
51
52impl ReceiversBuilder {
53    /// Creates a new `ReceiversBuilder` with default settings (no receivers).
54    ///
55    /// # Examples
56    ///
57    /// ```rust,no_run
58    /// use dbc_rs::ReceiversBuilder;
59    ///
60    /// let builder = ReceiversBuilder::new();
61    /// let receivers = builder.build()?;
62    /// assert_eq!(receivers.len(), 0);
63    /// # Ok::<(), dbc_rs::Error>(())
64    /// ```
65    pub fn new() -> Self {
66        Self {
67            is_broadcast: false,
68            nodes: Vec::new(),
69        }
70    }
71
72    /// Sets the receiver to broadcast (`*` in DBC format).
73    ///
74    /// This clears any previously set nodes and sets the receiver to broadcast mode.
75    ///
76    /// # Examples
77    ///
78    /// ```rust,no_run
79    /// use dbc_rs::ReceiversBuilder;
80    ///
81    /// let receivers = ReceiversBuilder::new()
82    ///     .add_node("TCM")  // This will be cleared
83    ///     .broadcast()
84    ///     .build()?;
85    /// assert_eq!(receivers, dbc_rs::Receivers::Broadcast);
86    /// # Ok::<(), dbc_rs::Error>(())
87    /// ```
88    #[must_use = "builder method returns modified builder"]
89    pub fn broadcast(mut self) -> Self {
90        self.is_broadcast = true;
91        self.nodes.clear();
92        self
93    }
94
95    /// Sets the receiver to none (no explicit receivers).
96    ///
97    /// This clears any previously set nodes and sets the receiver to none mode.
98    ///
99    /// # Examples
100    ///
101    /// ```rust,no_run
102    /// use dbc_rs::ReceiversBuilder;
103    ///
104    /// let receivers = ReceiversBuilder::new()
105    ///     .add_node("TCM")  // This will be cleared
106    ///     .none()
107    ///     .build()?;
108    /// assert_eq!(receivers, dbc_rs::Receivers::None);
109    /// # Ok::<(), dbc_rs::Error>(())
110    /// ```
111    #[must_use = "builder method returns modified builder"]
112    pub fn none(mut self) -> Self {
113        self.is_broadcast = false;
114        self.nodes.clear();
115        self
116    }
117
118    /// Adds a single receiver node.
119    ///
120    /// This automatically clears broadcast and none modes, switching to specific nodes mode.
121    ///
122    /// # Arguments
123    ///
124    /// * `node` - The node name (anything that implements `AsRef<str>`)
125    ///
126    /// # Examples
127    ///
128    /// ```rust,no_run
129    /// use dbc_rs::ReceiversBuilder;
130    ///
131    /// let receivers = ReceiversBuilder::new()
132    ///     .add_node("TCM")
133    ///     .add_node("BCM")
134    ///     .build()?;
135    /// assert_eq!(receivers.len(), 2);
136    /// assert!(receivers.contains("TCM"));
137    /// # Ok::<(), dbc_rs::Error>(())
138    /// ```
139    pub fn add_node(mut self, node: impl AsRef<str>) -> Self {
140        let node = node.as_ref().to_string();
141        self.is_broadcast = false;
142        self.nodes.push(node);
143
144        self
145    }
146
147    /// Adds multiple receiver nodes from an iterator.
148    ///
149    /// This automatically clears broadcast and none modes, switching to specific nodes mode.
150    ///
151    /// # Arguments
152    ///
153    /// * `nodes` - An iterator of node names (each item must implement `AsRef<str>`)
154    ///
155    /// # Examples
156    ///
157    /// ```rust,no_run
158    /// use dbc_rs::ReceiversBuilder;
159    ///
160    /// // From a slice
161    /// let receivers = ReceiversBuilder::new()
162    ///     .add_nodes(&["TCM", "BCM", "ECM"])
163    ///     .build()?;
164    /// assert_eq!(receivers.len(), 3);
165    ///
166    /// // From a vector
167    /// let node_vec = vec!["Node1", "Node2"];
168    /// let receivers2 = ReceiversBuilder::new()
169    ///     .add_nodes(node_vec.iter())
170    ///     .build()?;
171    /// assert_eq!(receivers2.len(), 2);
172    /// # Ok::<(), dbc_rs::Error>(())
173    /// ```
174    pub fn add_nodes<I, S>(mut self, nodes: I) -> Self
175    where
176        I: IntoIterator<Item = S>,
177        S: AsRef<str>,
178    {
179        for node in nodes {
180            self = self.add_node(node);
181        }
182
183        self
184    }
185
186    /// Clears all receiver nodes and resets to default state (none).
187    ///
188    /// # Examples
189    ///
190    /// ```rust,no_run
191    /// use dbc_rs::ReceiversBuilder;
192    ///
193    /// let receivers = ReceiversBuilder::new()
194    ///     .add_node("TCM")
195    ///     .add_node("BCM")
196    ///     .clear()
197    ///     .add_node("ECM")
198    ///     .build()?;
199    /// assert_eq!(receivers.len(), 1);
200    /// assert!(receivers.contains("ECM"));
201    /// assert!(!receivers.contains("TCM"));
202    /// # Ok::<(), dbc_rs::Error>(())
203    /// ```
204    #[must_use = "builder method returns modified builder"]
205    pub fn clear(mut self) -> Self {
206        self.nodes.clear();
207        self.is_broadcast = false;
208        self
209    }
210}
211
212impl ReceiversBuilder {
213    /// Builds the `Receivers` from the builder configuration.
214    ///
215    /// # Returns
216    ///
217    /// Returns `Ok(Receivers)` if successful, or `Err(Error::Signal)` if:
218    /// - More than 64 receiver nodes are specified (exceeds maximum limit)
219    ///
220    /// # Examples
221    ///
222    /// ```rust,no_run
223    /// use dbc_rs::ReceiversBuilder;
224    ///
225    /// // Broadcast
226    /// let broadcast = ReceiversBuilder::new().broadcast().build()?;
227    ///
228    /// // Specific nodes
229    /// let nodes = ReceiversBuilder::new()
230    ///     .add_node("TCM")
231    ///     .add_node("BCM")
232    ///     .build()?;
233    ///
234    /// // None (default)
235    /// let none = ReceiversBuilder::new().build()?;
236    /// # Ok::<(), dbc_rs::Error>(())
237    /// ```
238    ///
239    /// # Errors
240    ///
241    /// ```rust,no_run
242    /// use dbc_rs::ReceiversBuilder;
243    ///
244    /// // Too many nodes (limit is 64)
245    /// let mut builder = ReceiversBuilder::new();
246    /// for i in 0..65 {
247    ///     builder = builder.add_node(format!("Node{i}"));
248    /// }
249    /// assert!(builder.build().is_err());
250    /// ```
251    pub fn build(&self) -> Result<Receivers> {
252        if self.is_broadcast {
253            Ok(Receivers::new_broadcast())
254        } else if self.nodes.is_empty() {
255            Ok(Receivers::new_none())
256        } else {
257            // Make sure the number of nodes is not greater than the maximum allowed
258            // Receivers can have at most MAX_NODES - 1 nodes
259            if let Some(err) = crate::error::check_max_limit(
260                self.nodes.len(),
261                MAX_NODES - 1,
262                Error::Signal(Error::SIGNAL_RECEIVERS_TOO_MANY),
263            ) {
264                return Err(err);
265            }
266
267            // Make sure the nodes are not duplicated
268            let mut seen = HashSet::new();
269            if !self.nodes.iter().all(|item| seen.insert(item)) {
270                return Err(Error::Signal(Error::RECEIVERS_DUPLICATE_NAME));
271            }
272
273            // Make sure the node names are not too long and convert to compat::String
274            use crate::compat::{String, Vec};
275            let mut compat_nodes: Vec<String<{ MAX_NAME_SIZE }>, { MAX_NODES }> = Vec::new();
276            for node in &self.nodes {
277                if let Some(err) = crate::error::check_max_limit(
278                    node.len(),
279                    MAX_NAME_SIZE,
280                    Error::Signal(Error::MAX_NAME_SIZE_EXCEEDED),
281                ) {
282                    return Err(err);
283                }
284                let compat_str = String::try_from(node.as_str())
285                    .map_err(|_| Error::Signal(Error::MAX_NAME_SIZE_EXCEEDED))?;
286                compat_nodes
287                    .push(compat_str)
288                    .map_err(|_| Error::Signal(Error::SIGNAL_RECEIVERS_TOO_MANY))?;
289            }
290
291            Ok(Receivers::new_nodes(compat_nodes.as_slice()))
292        }
293    }
294}
295
296impl Default for ReceiversBuilder {
297    fn default() -> Self {
298        Self::new()
299    }
300}
301
302#[cfg(test)]
303mod tests {
304    use super::*;
305    use crate::error::Error;
306
307    #[test]
308    fn test_receivers_builder_broadcast() {
309        let receivers = ReceiversBuilder::new().broadcast().build().unwrap();
310        assert_eq!(receivers, Receivers::Broadcast);
311    }
312
313    #[test]
314    fn test_receivers_builder_none() {
315        let receivers = ReceiversBuilder::new().none().build().unwrap();
316        assert_eq!(receivers, Receivers::None);
317    }
318
319    #[test]
320    fn test_receivers_builder_empty() {
321        let receivers = ReceiversBuilder::new().build().unwrap();
322        assert_eq!(receivers, Receivers::None);
323    }
324
325    #[test]
326    fn test_receivers_builder_single_node() {
327        let receivers = ReceiversBuilder::new().add_node("TCM").build().unwrap();
328        match &receivers {
329            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 1),
330            _ => panic!("Expected Nodes variant"),
331        }
332    }
333
334    #[test]
335    fn test_receivers_builder_multiple_nodes() {
336        let receivers = ReceiversBuilder::new()
337            .add_node("TCM")
338            .add_node("BCM")
339            .add_node("ECM")
340            .build()
341            .unwrap();
342        match &receivers {
343            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 3),
344            _ => panic!("Expected Nodes variant"),
345        }
346    }
347
348    #[test]
349    fn test_receivers_builder_too_many() {
350        let mut builder = ReceiversBuilder::new();
351        for i in 0..MAX_NODES {
352            builder = builder.add_node(format!("Node{i}"));
353        }
354        let result = builder.add_node(format!("Node{}", MAX_NODES)).build();
355        assert!(result.is_err());
356        match result.unwrap_err() {
357            Error::Signal(msg) => {
358                assert_eq!(msg, Error::SIGNAL_RECEIVERS_TOO_MANY);
359            }
360            _ => panic!("Expected Signal error"),
361        }
362    }
363
364    #[test]
365    fn test_receivers_builder_add_nodes() {
366        let receivers = ReceiversBuilder::new().add_nodes(["ECM", "TCM", "BCM"]).build().unwrap();
367        match &receivers {
368            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 3),
369            _ => panic!("Expected Nodes variant"),
370        }
371        assert!(receivers.contains("ECM"));
372        assert!(receivers.contains("TCM"));
373        assert!(receivers.contains("BCM"));
374    }
375
376    #[test]
377    fn test_receivers_builder_add_nodes_iterator() {
378        let node_vec = ["Node1", "Node2", "Node3"];
379        let receivers = ReceiversBuilder::new().add_nodes(node_vec.iter()).build().unwrap();
380        match &receivers {
381            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 3),
382            _ => panic!("Expected Nodes variant"),
383        }
384    }
385
386    #[test]
387    fn test_receivers_builder_clear() {
388        let receivers = ReceiversBuilder::new()
389            .add_node("ECM")
390            .add_node("TCM")
391            .clear()
392            .add_node("BCM")
393            .build()
394            .unwrap();
395        match &receivers {
396            Receivers::Nodes(nodes) => {
397                assert_eq!(nodes.len(), 1);
398                assert!(receivers.contains("BCM"));
399                assert!(!receivers.contains("ECM"));
400            }
401            _ => panic!("Expected Nodes variant"),
402        }
403    }
404
405    #[test]
406    fn test_receivers_builder_broadcast_clears_nodes() {
407        let receivers = ReceiversBuilder::new()
408            .add_node("ECM")
409            .add_node("TCM")
410            .broadcast()
411            .build()
412            .unwrap();
413        assert_eq!(receivers, Receivers::Broadcast);
414        assert_eq!(receivers.len(), 0);
415    }
416
417    #[test]
418    fn test_receivers_builder_none_clears_nodes() {
419        let receivers =
420            ReceiversBuilder::new().add_node("ECM").add_node("TCM").none().build().unwrap();
421        assert_eq!(receivers, Receivers::None);
422        assert_eq!(receivers.len(), 0);
423    }
424
425    #[test]
426    fn test_receivers_builder_add_node_clears_broadcast() {
427        let receivers = ReceiversBuilder::new().broadcast().add_node("ECM").build().unwrap();
428        match &receivers {
429            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 1),
430            _ => panic!("Expected Nodes variant"),
431        }
432    }
433
434    #[test]
435    fn test_receivers_builder_add_node_clears_none() {
436        let receivers = ReceiversBuilder::new().none().add_node("ECM").build().unwrap();
437        match &receivers {
438            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 1),
439            _ => panic!("Expected Nodes variant"),
440        }
441    }
442
443    #[test]
444    fn test_receivers_builder_at_limit() {
445        let mut builder = ReceiversBuilder::new();
446        // Fill up to MAX_NODES - 1 (the limit)
447        for i in 0..(MAX_NODES - 1) {
448            let node_str = format!("Node{i}");
449            builder = builder.add_node(node_str);
450        }
451        let receivers = builder.build().unwrap();
452        match &receivers {
453            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), MAX_NODES - 1),
454            _ => panic!("Expected Nodes variant"),
455        }
456    }
457}