dbc_rs/signal/
signal_builder.rs

1use crate::{
2    ByteOrder, Receivers, ReceiversBuilder,
3    error::{Error, Result, messages},
4    signal::Signal,
5};
6
7type SignalFields = (
8    String,
9    u16,
10    u16,
11    ByteOrder,
12    bool,
13    f64,
14    f64,
15    f64,
16    f64,
17    Option<String>,
18    Receivers<'static>,
19);
20
21#[derive(Debug, Clone)]
22pub struct SignalBuilder {
23    name: Option<String>,
24    start_bit: Option<u16>,
25    length: Option<u16>,
26    byte_order: ByteOrder,
27    unsigned: bool,
28    factor: f64,
29    offset: f64,
30    min: f64,
31    max: f64,
32    unit: Option<String>,
33    receivers: Receivers<'static>,
34}
35
36impl Default for SignalBuilder {
37    fn default() -> Self {
38        Self {
39            name: None,
40            start_bit: None,
41            length: None,
42            byte_order: ByteOrder::BigEndian,
43            unsigned: true,
44            factor: 1.0,
45            offset: 0.0,
46            min: 0.0,
47            max: 0.0,
48            unit: None,
49            receivers: ReceiversBuilder::new().broadcast().build().unwrap(),
50        }
51    }
52}
53
54impl SignalBuilder {
55    pub fn new() -> Self {
56        Self::default()
57    }
58
59    #[must_use]
60    pub fn name(mut self, name: impl AsRef<str>) -> Self {
61        self.name = Some(name.as_ref().to_string());
62        self
63    }
64
65    #[must_use]
66    pub fn start_bit(mut self, start_bit: u16) -> Self {
67        self.start_bit = Some(start_bit);
68        self
69    }
70
71    #[must_use]
72    pub fn length(mut self, length: u16) -> Self {
73        self.length = Some(length);
74        self
75    }
76
77    #[must_use]
78    pub fn byte_order(mut self, byte_order: ByteOrder) -> Self {
79        self.byte_order = byte_order;
80        self
81    }
82
83    #[must_use]
84    pub fn unsigned(mut self, unsigned: bool) -> Self {
85        self.unsigned = unsigned;
86        self
87    }
88
89    #[must_use]
90    pub fn factor(mut self, factor: f64) -> Self {
91        self.factor = factor;
92        self
93    }
94
95    #[must_use]
96    pub fn offset(mut self, offset: f64) -> Self {
97        self.offset = offset;
98        self
99    }
100
101    #[must_use]
102    pub fn min(mut self, min: f64) -> Self {
103        self.min = min;
104        self
105    }
106
107    #[must_use]
108    pub fn max(mut self, max: f64) -> Self {
109        self.max = max;
110        self
111    }
112
113    #[must_use]
114    pub fn unit(mut self, unit: impl AsRef<str>) -> Self {
115        self.unit = Some(unit.as_ref().to_string());
116        self
117    }
118
119    #[must_use]
120    pub fn no_unit(mut self) -> Self {
121        self.unit = None;
122        self
123    }
124
125    #[must_use]
126    pub fn receivers(mut self, receivers: Receivers<'static>) -> Self {
127        self.receivers = receivers;
128        self
129    }
130
131    fn extract_fields(self) -> Result<SignalFields> {
132        let name = self
133            .name
134            .ok_or_else(|| Error::Signal(messages::SIGNAL_NAME_EMPTY.to_string()))?;
135        let start_bit = self
136            .start_bit
137            .ok_or_else(|| Error::Signal(messages::SIGNAL_START_BIT_REQUIRED.to_string()))?;
138        let length = self
139            .length
140            .ok_or_else(|| Error::Signal(messages::SIGNAL_LENGTH_REQUIRED.to_string()))?;
141        Ok((
142            name,
143            start_bit,
144            length,
145            self.byte_order,
146            self.unsigned,
147            self.factor,
148            self.offset,
149            self.min,
150            self.max,
151            self.unit,
152            self.receivers,
153        ))
154    }
155
156    #[must_use = "validation result should be checked"]
157    pub fn validate(self) -> Result<Self> {
158        let (
159            name,
160            _start_bit,
161            length,
162            byte_order,
163            unsigned,
164            factor,
165            offset,
166            min,
167            max,
168            unit,
169            receivers,
170        ) = self.extract_fields()?;
171        Signal::validate(&name, length, min, max).map_err(Error::from)?;
172        Ok(Self {
173            name: Some(name),
174            start_bit: Some(_start_bit),
175            length: Some(length),
176            byte_order,
177            unsigned,
178            factor,
179            offset,
180            min,
181            max,
182            unit,
183            receivers,
184        })
185    }
186
187    pub fn build(self) -> Result<Signal<'static>> {
188        let (
189            name,
190            start_bit,
191            length,
192            byte_order,
193            unsigned,
194            factor,
195            offset,
196            min,
197            max,
198            unit,
199            receivers,
200        ) = self.extract_fields()?;
201        // Convert owned strings to static references by leaking Box<str>
202        let name_boxed: Box<str> = name.into_boxed_str();
203        let name_static: &'static str = Box::leak(name_boxed);
204        let unit_static: Option<&'static str> = if let Some(u) = unit {
205            let boxed: Box<str> = u.into_boxed_str();
206            Some(Box::leak(boxed))
207        } else {
208            None
209        };
210        // Validate before construction
211        Signal::validate(name_static, length, min, max).map_err(|e| match e {
212            crate::error::ParseError::Version(msg) => Error::Signal(String::from(msg)),
213            _ => Error::ParseError(e),
214        })?;
215        Ok(Signal::new(
216            name_static,
217            start_bit,
218            length,
219            byte_order,
220            unsigned,
221            factor,
222            offset,
223            min,
224            max,
225            unit_static,
226            receivers,
227        ))
228    }
229}