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