1use crate::{MAX_SIGNALS_PER_MESSAGE, Signal, compat::Vec};
2
3#[derive(Debug, Clone, PartialEq, Eq, Hash)]
7pub struct Signals {
8 signals: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>,
9}
10
11impl From<&[Signal]> for Signals {
12 fn from(signals: &[Signal]) -> Self {
13 Self::from_slice(signals)
14 }
15}
16
17#[cfg(feature = "std")]
18impl From<std::vec::Vec<Signal>> for Signals {
19 fn from(signals: std::vec::Vec<Signal>) -> Self {
20 Self::from_slice(&signals)
21 }
22}
23
24impl From<Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>> for Signals {
25 fn from(signals: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>) -> Self {
26 Self::from_slice(signals.as_slice())
27 }
28}
29
30impl Signals {
31 pub(crate) fn from_slice(signals: &[Signal]) -> Self {
33 let count = signals.len().min(MAX_SIGNALS_PER_MESSAGE);
34 let signals_vec: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }> =
35 signals.iter().take(count).cloned().collect();
36 Self {
37 signals: signals_vec,
38 }
39 }
40
41 #[inline]
56 #[must_use = "iterator is lazy and does nothing unless consumed"]
57 pub fn iter(&self) -> impl Iterator<Item = &Signal> + '_ {
58 self.signals.iter()
59 }
60
61 #[inline]
74 #[must_use = "return value should be used"]
75 pub fn len(&self) -> usize {
76 self.signals.len()
77 }
78
79 #[inline]
92 #[must_use = "return value should be used"]
93 pub fn is_empty(&self) -> bool {
94 self.len() == 0
95 }
96
97 #[inline]
112 #[must_use = "return value should be used"]
113 pub fn at(&self, index: usize) -> Option<&Signal> {
114 self.signals.get(index)
115 }
116
117 #[must_use = "return value should be used"]
133 pub fn find(&self, name: &str) -> Option<&Signal> {
134 self.iter().find(|s| s.name() == name)
135 }
136}
137
138#[cfg(test)]
139mod tests {
140 use super::Signals;
141 use crate::{Parser, Signal};
142
143 #[cfg(feature = "std")]
145 mod test_from_slice {
146 use super::*;
147
148 #[test]
149 fn test_signals_from_slice() {
150 let signal1 = Signal::parse(
151 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
152 )
153 .unwrap();
154 let signal2 = Signal::parse(
155 &mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
156 )
157 .unwrap();
158
159 let signals = Signals::from_slice(&[signal1, signal2]);
160 assert_eq!(signals.len(), 2);
161 assert!(!signals.is_empty());
162 assert_eq!(signals.at(0).unwrap().name(), "Signal1");
163 assert_eq!(signals.at(1).unwrap().name(), "Signal2");
164 }
165
166 #[test]
167 fn test_signals_from_signals_slice_empty() {
168 let signals = Signals::from_slice(&[]);
169 assert_eq!(signals.len(), 0);
170 assert!(signals.is_empty());
171 assert!(signals.at(0).is_none());
172 }
173
174 #[test]
175 fn test_signals_from_slice_multiple() {
176 let signal1 = Signal::parse(
178 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
179 )
180 .unwrap();
181 let signal2 = Signal::parse(
182 &mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
183 )
184 .unwrap();
185 let signal3 = Signal::parse(
186 &mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap(),
187 )
188 .unwrap();
189
190 let signals = Signals::from_slice(&[signal1, signal2, signal3]);
191 assert_eq!(signals.len(), 3);
192 assert_eq!(signals.at(0).unwrap().name(), "Signal1");
193 assert_eq!(signals.at(1).unwrap().name(), "Signal2");
194 assert_eq!(signals.at(2).unwrap().name(), "Signal3");
195 }
196 }
197
198 mod test_iter {
200 use super::*;
201
202 #[test]
203 fn test_signals_iter() {
204 let signal1 = Signal::parse(
205 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
206 )
207 .unwrap();
208 let signal2 = Signal::parse(
209 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
210 )
211 .unwrap();
212
213 let signals = Signals::from_slice(&[signal1, signal2]);
214 let mut iter = signals.iter();
215 assert_eq!(iter.next().unwrap().name(), "RPM");
216 assert_eq!(iter.next().unwrap().name(), "Temp");
217 assert!(iter.next().is_none());
218 }
219
220 #[test]
221 fn test_signals_iter_empty() {
222 let signals = Signals::from_slice(&[]);
223 let mut iter = signals.iter();
224 assert!(iter.next().is_none());
225 }
226
227 #[test]
228 fn test_signals_iter_multiple() {
229 let signal1 = Signal::parse(
230 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
231 )
232 .unwrap();
233 let signal2 = Signal::parse(
234 &mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
235 )
236 .unwrap();
237 let signal3 = Signal::parse(
238 &mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap(),
239 )
240 .unwrap();
241
242 let signals = Signals::from_slice(&[signal1, signal2, signal3]);
243 let mut iter = signals.iter();
244 assert_eq!(iter.next().unwrap().name(), "Signal1");
245 assert_eq!(iter.next().unwrap().name(), "Signal2");
246 assert_eq!(iter.next().unwrap().name(), "Signal3");
247 assert!(iter.next().is_none());
248 }
249 }
250
251 mod test_len {
253 use super::*;
254
255 #[test]
256 fn test_signals_len() {
257 let signals = Signals::from_slice(&[]);
258 assert_eq!(signals.len(), 0);
259
260 let signal1 = Signal::parse(
261 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
262 )
263 .unwrap();
264 let signals = Signals::from_slice(&[signal1]);
265 assert_eq!(signals.len(), 1);
266 }
267 }
268
269 mod test_is_empty {
271 use super::*;
272
273 #[test]
274 fn test_signals_is_empty() {
275 let signals = Signals::from_slice(&[]);
276 assert!(signals.is_empty());
277 assert_eq!(signals.len(), 0);
278
279 let signal1 = Signal::parse(
280 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
281 )
282 .unwrap();
283 let signals = Signals::from_slice(&[signal1]);
284 assert!(!signals.is_empty());
285 }
286 }
287
288 mod test_at {
290 use super::*;
291
292 #[test]
293 fn test_signals_at() {
294 let signal1 = Signal::parse(
295 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
296 )
297 .unwrap();
298 let signal2 = Signal::parse(
299 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
300 )
301 .unwrap();
302
303 let signals = Signals::from_slice(&[signal1, signal2]);
304 assert_eq!(signals.at(0).unwrap().name(), "RPM");
305 assert_eq!(signals.at(1).unwrap().name(), "Temp");
306 assert!(signals.at(2).is_none());
307 }
308
309 #[test]
310 fn test_signals_at_out_of_bounds() {
311 let signal = Signal::parse(
312 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
313 )
314 .unwrap();
315
316 let signals = Signals::from_slice(&[signal]);
317
318 assert!(signals.at(0).is_some());
320 assert_eq!(signals.at(0).unwrap().name(), "RPM");
321
322 assert!(signals.at(1).is_none());
324 assert!(signals.at(100).is_none());
325 assert!(signals.at(usize::MAX).is_none());
326 }
327 }
328
329 mod test_find {
331 use super::*;
332
333 #[test]
334 fn test_signals_find() {
335 let signal1 = Signal::parse(
336 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
337 )
338 .unwrap();
339 let signal2 = Signal::parse(
340 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
341 )
342 .unwrap();
343
344 let signals = Signals::from_slice(&[signal1, signal2]);
345 assert_eq!(signals.find("RPM").unwrap().name(), "RPM");
346 assert_eq!(signals.find("Temp").unwrap().name(), "Temp");
347 assert!(signals.find("Nonexistent").is_none());
348 }
349
350 #[test]
351 fn test_signals_find_case_sensitive() {
352 let signal1 = Signal::parse(
353 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
354 )
355 .unwrap();
356 let signal2 = Signal::parse(
357 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
358 )
359 .unwrap();
360
361 let signals = Signals::from_slice(&[signal1, signal2]);
362
363 assert!(signals.find("RPM").is_some());
365 assert_eq!(signals.find("RPM").unwrap().name(), "RPM");
366
367 assert!(signals.find("rpm").is_none());
369 assert!(signals.find("Rpm").is_none());
370
371 assert!(signals.find("Temp").is_some());
373 assert_eq!(signals.find("Temp").unwrap().name(), "Temp");
374
375 assert!(signals.find("Nonexistent").is_none());
377 assert!(signals.find("").is_none());
378 }
379
380 #[test]
381 fn test_signals_find_empty_collection() {
382 let signals = Signals::from_slice(&[]);
383 assert!(signals.find("RPM").is_none());
384 assert!(signals.find("").is_none());
385 }
386
387 #[test]
388 fn test_signals_find_not_found() {
389 let signal1 = Signal::parse(
390 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
391 )
392 .unwrap();
393
394 let signals = Signals::from_slice(&[signal1]);
395 assert!(signals.find("Nonexistent").is_none());
396 assert!(signals.find("").is_none());
397 assert!(signals.find("signal1").is_none()); }
399
400 #[test]
401 fn test_signals_find_first_match() {
402 let signal1 = Signal::parse(
403 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
404 )
405 .unwrap();
406 let signal2 = Signal::parse(
407 &mut Parser::new(b"SG_ Signal1 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
408 )
409 .unwrap(); let signals = Signals::from_slice(&[signal1, signal2]);
412 let found = signals.find("Signal1");
414 assert!(found.is_some());
415 assert_eq!(found.unwrap().start_bit(), 0); }
417 }
418}