dbc_rs/message/builder/impls.rs
1use super::MessageBuilder;
2use crate::{SignalBuilder, builder_setter, builder_string_setter};
3use std::vec::Vec;
4
5impl MessageBuilder {
6 /// Creates a new `MessageBuilder` with no fields set.
7 ///
8 /// # Examples
9 ///
10 /// ```rust,no_run
11 /// use dbc_rs::MessageBuilder;
12 ///
13 /// let builder = MessageBuilder::new();
14 /// // Must set id, name, dlc, and sender before building
15 /// # Ok::<(), dbc_rs::Error>(())
16 /// ```
17 pub fn new() -> Self {
18 Self {
19 id: None,
20 name: None,
21 dlc: None,
22 sender: None,
23 signals: Vec::new(),
24 }
25 }
26
27 // Scalar field setters generated by macros
28 builder_setter!(
29 id,
30 u32,
31 "Sets the CAN message ID (11-bit or 29-bit identifier)."
32 );
33 builder_setter!(
34 dlc,
35 u8,
36 "Sets the Data Length Code (DLC) - the number of data bytes in the message (0-8 for standard CAN, 0-64 for CAN FD)."
37 );
38
39 // String field setters generated by macros
40 builder_string_setter!(name, "Sets the message name.");
41 builder_string_setter!(
42 sender,
43 "Sets the sender (transmitter) ECU node name for this message."
44 );
45
46 /// Adds a signal to the message.
47 ///
48 /// # Arguments
49 ///
50 /// * `signal` - A `SignalBuilder` to add to this message
51 ///
52 /// # Examples
53 ///
54 /// ```rust,no_run
55 /// use dbc_rs::{MessageBuilder, SignalBuilder, ByteOrder};
56 ///
57 /// let signal = SignalBuilder::new()
58 /// .name("EngineSpeed")
59 /// .start_bit(0)
60 /// .length(16)
61 /// .byte_order(ByteOrder::LittleEndian);
62 ///
63 /// let builder = MessageBuilder::new()
64 /// .add_signal(signal);
65 /// # Ok::<(), dbc_rs::Error>(())
66 /// ```
67 #[must_use = "builder method returns modified builder"]
68 pub fn add_signal(mut self, signal: SignalBuilder) -> Self {
69 self.signals.push(signal);
70 self
71 }
72
73 /// Adds multiple signals to the message.
74 ///
75 /// # Arguments
76 ///
77 /// * `signals` - An iterator of `SignalBuilder` items to add
78 ///
79 /// # Examples
80 ///
81 /// ```rust,no_run
82 /// use dbc_rs::{MessageBuilder, SignalBuilder, ByteOrder};
83 ///
84 /// let signals = vec![
85 /// SignalBuilder::new().name("Signal1").start_bit(0).length(8).byte_order(ByteOrder::LittleEndian),
86 /// SignalBuilder::new().name("Signal2").start_bit(8).length(8).byte_order(ByteOrder::LittleEndian),
87 /// ];
88 ///
89 /// let builder = MessageBuilder::new()
90 /// .add_signals(signals);
91 /// # Ok::<(), dbc_rs::Error>(())
92 /// ```
93 #[must_use = "builder method returns modified builder"]
94 pub fn add_signals(mut self, signals: impl IntoIterator<Item = SignalBuilder>) -> Self {
95 self.signals.extend(signals);
96 self
97 }
98
99 /// Replaces all signals in the message with the provided signals.
100 ///
101 /// Clears any existing signals and adds the new ones.
102 ///
103 /// # Arguments
104 ///
105 /// * `signals` - A vector of `SignalBuilder` items to set
106 ///
107 /// # Examples
108 ///
109 /// ```rust,no_run
110 /// use dbc_rs::{MessageBuilder, SignalBuilder, ByteOrder};
111 ///
112 /// let new_signals = vec![
113 /// SignalBuilder::new().name("NewSignal").start_bit(0).length(8).byte_order(ByteOrder::LittleEndian),
114 /// ];
115 ///
116 /// let builder = MessageBuilder::new()
117 /// .signals(new_signals);
118 /// # Ok::<(), dbc_rs::Error>(())
119 /// ```
120 #[must_use = "builder method returns modified builder"]
121 pub fn signals(mut self, signals: Vec<SignalBuilder>) -> Self {
122 self.signals = signals;
123 self
124 }
125
126 /// Removes all signals from the message.
127 ///
128 /// # Examples
129 ///
130 /// ```rust,no_run
131 /// use dbc_rs::MessageBuilder;
132 ///
133 /// let builder = MessageBuilder::new()
134 /// .clear_signals();
135 /// # Ok::<(), dbc_rs::Error>(())
136 /// ```
137 #[must_use = "builder method returns modified builder"]
138 pub fn clear_signals(mut self) -> Self {
139 self.signals.clear();
140 self
141 }
142}
143
144impl Default for MessageBuilder {
145 fn default() -> Self {
146 Self::new()
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153 use crate::{ByteOrder, ReceiversBuilder};
154
155 fn minimal_signal() -> SignalBuilder {
156 SignalBuilder::new()
157 .name("TestSignal")
158 .start_bit(0)
159 .length(8)
160 .byte_order(ByteOrder::LittleEndian)
161 .unsigned(true)
162 .factor(1.0)
163 .offset(0.0)
164 .min(0.0)
165 .max(255.0)
166 .receivers(ReceiversBuilder::new().none())
167 }
168
169 fn minimal_message() -> MessageBuilder {
170 MessageBuilder::new().id(256).name("TestMessage").dlc(8).sender("ECM")
171 }
172
173 #[test]
174 fn test_message_builder_with_signal() {
175 let message = minimal_message().add_signal(minimal_signal()).build().unwrap();
176
177 assert_eq!(message.signals().len(), 1);
178 assert_eq!(message.signals().at(0).unwrap().name(), "TestSignal");
179 }
180
181 #[test]
182 fn test_message_builder_add_signals() {
183 let sig1 = minimal_signal().name("Signal1");
184 let sig2 = minimal_signal().name("Signal2").start_bit(8);
185
186 let message = minimal_message().add_signals(vec![sig1, sig2]).build().unwrap();
187
188 assert_eq!(message.signals().len(), 2);
189 }
190
191 #[test]
192 fn test_message_builder_signals() {
193 let sig1 = minimal_signal().name("Signal1");
194 let sig2 = minimal_signal().name("Signal2").start_bit(8);
195
196 let message = minimal_message().signals(vec![sig1, sig2]).build().unwrap();
197
198 assert_eq!(message.signals().len(), 2);
199 }
200
201 #[test]
202 fn test_message_builder_clear_signals() {
203 let message =
204 minimal_message().add_signal(minimal_signal()).clear_signals().build().unwrap();
205
206 assert_eq!(message.signals().len(), 0);
207 }
208}