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 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 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}