dbc_rs/signal/builder/
impls.rs

1use super::SignalBuilder;
2use super::{ByteOrder, ReceiversBuilder};
3use crate::{builder_setter, builder_string_setter};
4
5impl SignalBuilder {
6    /// Creates a new `SignalBuilder` with no fields set.
7    ///
8    /// # Examples
9    ///
10    /// ```rust,no_run
11    /// use dbc_rs::SignalBuilder;
12    ///
13    /// let builder = SignalBuilder::new();
14    /// // Must set name, start_bit, length, and byte_order before building
15    /// # Ok::<(), dbc_rs::Error>(())
16    /// ```
17    pub fn new() -> Self {
18        Self {
19            name: None,
20            start_bit: None,
21            length: None,
22            byte_order: None,
23            unsigned: None,
24            factor: None,
25            offset: None,
26            min: None,
27            max: None,
28            unit: None,
29            receivers: ReceiversBuilder::new(),
30        }
31    }
32
33    // String field setters generated by macros
34    builder_string_setter!(name, "Sets the signal name.");
35    builder_string_setter!(
36        unit,
37        "Sets the unit of measurement for this signal (e.g., \"km/h\", \"rpm\", \"°C\")."
38    );
39
40    // Scalar field setters generated by macros
41    builder_setter!(
42        start_bit,
43        u16,
44        "Sets the start bit position of the signal in the CAN message payload."
45    );
46    builder_setter!(length, u16, "Sets the length of the signal in bits.");
47    builder_setter!(
48        byte_order,
49        ByteOrder,
50        "Sets the byte order (endianness) of the signal."
51    );
52    builder_setter!(
53        unsigned,
54        bool,
55        "Sets whether the signal is unsigned (`true`) or signed (`false`)."
56    );
57    builder_setter!(
58        factor,
59        f64,
60        "Sets the scaling factor for converting raw values to physical values (physical = raw * factor + offset)."
61    );
62    builder_setter!(
63        offset,
64        f64,
65        "Sets the offset for converting raw values to physical values (physical = raw * factor + offset)."
66    );
67    builder_setter!(min, f64, "Sets the minimum physical value for this signal.");
68    builder_setter!(max, f64, "Sets the maximum physical value for this signal.");
69
70    /// Sets the receivers (ECU nodes) that subscribe to this signal.
71    ///
72    /// # Arguments
73    ///
74    /// * `receivers` - A `ReceiversBuilder` specifying which nodes receive this signal
75    ///
76    /// # Examples
77    ///
78    /// ```rust,no_run
79    /// use dbc_rs::{SignalBuilder, ReceiversBuilder};
80    ///
81    /// let receivers = ReceiversBuilder::new()
82    ///     .add_node("ECU1")
83    ///     .add_node("ECU2");
84    ///
85    /// let builder = SignalBuilder::new()
86    ///     .receivers(receivers);
87    /// # Ok::<(), dbc_rs::Error>(())
88    /// ```
89    #[must_use = "builder method returns modified builder"]
90    pub fn receivers(mut self, receivers: ReceiversBuilder) -> Self {
91        self.receivers = receivers;
92        self
93    }
94}
95
96impl Default for SignalBuilder {
97    fn default() -> Self {
98        Self::new()
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    fn minimal_signal() -> SignalBuilder {
107        SignalBuilder::new()
108            .name("TestSignal")
109            .start_bit(0)
110            .length(8)
111            .byte_order(ByteOrder::LittleEndian)
112            .unsigned(true)
113            .factor(1.0)
114            .offset(0.0)
115            .min(0.0)
116            .max(255.0)
117            .receivers(ReceiversBuilder::new().none())
118    }
119
120    #[test]
121    fn test_signal_builder_minimal() {
122        let signal = minimal_signal().build().unwrap();
123
124        assert_eq!(signal.name(), "TestSignal");
125        assert_eq!(signal.start_bit(), 0);
126        assert_eq!(signal.length(), 8);
127        assert_eq!(signal.byte_order(), ByteOrder::LittleEndian);
128        assert!(signal.is_unsigned());
129        assert_eq!(signal.factor(), 1.0);
130        assert_eq!(signal.offset(), 0.0);
131        assert_eq!(signal.min(), 0.0);
132        assert_eq!(signal.max(), 255.0);
133        assert!(signal.unit().is_none());
134    }
135
136    #[test]
137    fn test_signal_builder_with_unit() {
138        let signal = minimal_signal().unit("rpm").build().unwrap();
139        assert_eq!(signal.unit(), Some("rpm"));
140    }
141
142    #[test]
143    fn test_signal_builder_signed() {
144        let signal = minimal_signal().unsigned(false).build().unwrap();
145        assert!(!signal.is_unsigned());
146    }
147
148    #[test]
149    fn test_signal_builder_big_endian() {
150        let signal = minimal_signal().byte_order(ByteOrder::BigEndian).build().unwrap();
151        assert_eq!(signal.byte_order(), ByteOrder::BigEndian);
152    }
153
154    #[test]
155    fn test_signal_builder_with_receivers() {
156        let signal = minimal_signal()
157            .receivers(ReceiversBuilder::new().add_node("ECM").add_node("TCM"))
158            .build()
159            .unwrap();
160
161        assert_eq!(signal.receivers().len(), 2);
162    }
163}