dbc_rs/receivers/builder/
build.rs

1use super::{Receivers, ReceiversBuilder};
2use crate::{Error, MAX_NAME_SIZE, MAX_NODES, Result};
3
4impl ReceiversBuilder {
5    /// Builds the `Receivers` from the builder configuration.
6    ///
7    /// # Returns
8    ///
9    /// Returns `Ok(Receivers)` if successful, or `Err(Error::Signal)` if:
10    /// - More than 64 receiver nodes are specified (exceeds maximum limit)
11    ///
12    /// # Examples
13    ///
14    /// ```rust,no_run
15    /// use dbc_rs::ReceiversBuilder;
16    ///
17    /// // Specific nodes
18    /// let nodes = ReceiversBuilder::new()
19    ///     .add_node("TCM")
20    ///     .add_node("BCM")
21    ///     .build()?;
22    ///
23    /// // None (default - serializes as Vector__XXX)
24    /// let none = ReceiversBuilder::new().build()?;
25    /// # Ok::<(), dbc_rs::Error>(())
26    /// ```
27    ///
28    /// # Errors
29    ///
30    /// ```rust,no_run
31    /// use dbc_rs::ReceiversBuilder;
32    ///
33    /// // Too many nodes (limit is 64)
34    /// let mut builder = ReceiversBuilder::new();
35    /// for i in 0..65 {
36    ///     builder = builder.add_node(format!("Node{i}"));
37    /// }
38    /// assert!(builder.build().is_err());
39    /// ```
40    pub fn build(self) -> Result<Receivers> {
41        if self.nodes.is_empty() {
42            Ok(Receivers::new_none())
43        } else {
44            // Make sure the number of nodes is not greater than the maximum allowed
45            // Receivers can have at most MAX_NODES - 1 nodes
46            if let Some(err) = crate::error::check_max_limit(
47                self.nodes.len(),
48                MAX_NODES - 1,
49                Error::signal(Error::SIGNAL_RECEIVERS_TOO_MANY),
50            ) {
51                return Err(err);
52            }
53
54            // Make sure the nodes are not duplicated
55            // Using O(n²) loop instead of HashSet to avoid allocation overhead
56            // (receiver lists are typically small, making this faster in practice)
57            for (i, node1) in self.nodes.iter().enumerate() {
58                for node2 in self.nodes.iter().skip(i + 1) {
59                    if node1 == node2 {
60                        return Err(Error::signal(Error::RECEIVERS_DUPLICATE_NAME));
61                    }
62                }
63            }
64
65            // Make sure the node names are not too long and convert to compat::String
66            use crate::compat::{String, Vec};
67            let mut compat_nodes: Vec<String<{ MAX_NAME_SIZE }>, { MAX_NODES - 1 }> = Vec::new();
68            for node in &self.nodes {
69                if let Some(err) = crate::error::check_max_limit(
70                    node.len(),
71                    MAX_NAME_SIZE,
72                    Error::signal(Error::MAX_NAME_SIZE_EXCEEDED),
73                ) {
74                    return Err(err);
75                }
76                let compat_str = String::try_from(node.as_str())
77                    .map_err(|_| Error::signal(Error::MAX_NAME_SIZE_EXCEEDED))?;
78                compat_nodes
79                    .push(compat_str)
80                    .map_err(|_| Error::signal(Error::SIGNAL_RECEIVERS_TOO_MANY))?;
81            }
82
83            Ok(Receivers::new_nodes(compat_nodes))
84        }
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use crate::error::Error;
92
93    #[test]
94    fn test_receivers_builder_none() {
95        let receivers = ReceiversBuilder::new().none().build().unwrap();
96        assert_eq!(receivers, Receivers::None);
97    }
98
99    #[test]
100    fn test_receivers_builder_empty() {
101        let receivers = ReceiversBuilder::new().build().unwrap();
102        assert_eq!(receivers, Receivers::None);
103    }
104
105    #[test]
106    fn test_receivers_builder_single_node() {
107        let receivers = ReceiversBuilder::new().add_node("TCM").build().unwrap();
108        match &receivers {
109            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 1),
110            _ => panic!("Expected Nodes variant"),
111        }
112    }
113
114    #[test]
115    fn test_receivers_builder_multiple_nodes() {
116        let receivers = ReceiversBuilder::new()
117            .add_node("TCM")
118            .add_node("BCM")
119            .add_node("ECM")
120            .build()
121            .unwrap();
122        match &receivers {
123            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), 3),
124            _ => panic!("Expected Nodes variant"),
125        }
126    }
127
128    #[test]
129    fn test_receivers_builder_too_many() {
130        let mut builder = ReceiversBuilder::new();
131        for i in 0..MAX_NODES {
132            builder = builder.add_node(format!("Node{i}"));
133        }
134        let result = builder.add_node(format!("Node{}", MAX_NODES)).build();
135        assert!(result.is_err());
136        match result.unwrap_err() {
137            Error::Signal { msg, .. } => {
138                assert_eq!(msg, Error::SIGNAL_RECEIVERS_TOO_MANY);
139            }
140            _ => panic!("Expected Signal error"),
141        }
142    }
143
144    #[test]
145    fn test_receivers_builder_at_limit() {
146        let mut builder = ReceiversBuilder::new();
147        // Fill up to MAX_NODES - 1 (the limit)
148        for i in 0..(MAX_NODES - 1) {
149            let node_str = format!("Node{i}");
150            builder = builder.add_node(node_str);
151        }
152        let receivers = builder.build().unwrap();
153        match &receivers {
154            Receivers::Nodes(nodes) => assert_eq!(nodes.len(), MAX_NODES - 1),
155            _ => panic!("Expected Nodes variant"),
156        }
157    }
158}