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