1use crate::{
2 ByteOrder, Parser, Signal,
3 error::{ParseError, ParseResult},
4};
5
6use super::Signals;
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
36pub struct Message<'a> {
37 id: u32,
38 name: &'a str,
39 dlc: u8,
40 sender: &'a str,
41 signals: Signals<'a>,
42}
43
44impl<'a> Message<'a> {
45 #[allow(clippy::similar_names)] fn calculate_bit_range(start_bit: u16, length: u16, byte_order: ByteOrder) -> (u16, u16) {
47 let start = start_bit;
48 let len = length;
49
50 match byte_order {
51 ByteOrder::LittleEndian => {
52 (start, start + len - 1)
55 }
56 ByteOrder::BigEndian => {
57 let byte_num = start / 8;
70 let bit_in_byte = start % 8;
71 let physical_msb = byte_num * 8 + (7 - bit_in_byte);
72
73 let lsb_be_bit = start + len - 1;
76 let lsb_byte_num = lsb_be_bit / 8;
77 let lsb_bit_in_byte = lsb_be_bit % 8;
78 let physical_lsb = lsb_byte_num * 8 + (7 - lsb_bit_in_byte);
79
80 if physical_lsb <= physical_msb {
82 (physical_lsb, physical_msb)
83 } else {
84 (physical_msb, physical_lsb)
85 }
86 }
87 }
88 }
89
90 #[allow(clippy::similar_names)] pub(crate) fn validate_internal(
92 id: u32,
93 name: &str,
94 dlc: u8,
95 sender: &str,
96 signals: &[Option<Signal<'a>>],
97 signal_count: usize,
98 options: crate::ParseOptions,
99 ) -> ParseResult<()> {
100 const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF; const MAX_SIGNALS_PER_MESSAGE: usize = crate::Signals::max_capacity();
112 if signal_count > MAX_SIGNALS_PER_MESSAGE {
113 return Err(ParseError::Message(
114 crate::error::lang::MESSAGE_TOO_MANY_SIGNALS,
115 ));
116 }
117
118 if name.trim().is_empty() {
119 return Err(ParseError::Message(crate::error::lang::MESSAGE_NAME_EMPTY));
120 }
121
122 if sender.trim().is_empty() {
123 return Err(ParseError::Message(
124 crate::error::lang::MESSAGE_SENDER_EMPTY,
125 ));
126 }
127
128 if dlc == 0 {
133 return Err(ParseError::Message(
134 crate::error::lang::MESSAGE_DLC_TOO_SMALL,
135 ));
136 }
137 if dlc > 64 {
138 return Err(ParseError::Message(
139 crate::error::lang::MESSAGE_DLC_TOO_LARGE,
140 ));
141 }
142
143 if id > MAX_EXTENDED_ID {
147 return Err(ParseError::Message(
148 crate::error::lang::MESSAGE_ID_OUT_OF_RANGE,
149 ));
150 }
151
152 let max_bits = u16::from(dlc) * 8;
158 for signal in signals.iter().take(signal_count).filter_map(|opt| opt.as_ref()) {
159 let (lsb, msb) =
161 Self::calculate_bit_range(signal.start_bit(), signal.length(), signal.byte_order());
162 let signal_max_bit = lsb.max(msb);
165 if signal_max_bit >= max_bits {
166 if options.strict_boundary_check {
168 return Err(ParseError::Message(
169 crate::error::lang::SIGNAL_LENGTH_TOO_LARGE,
170 ));
171 }
172 }
174 }
175
176 let signals_slice = &signals[..signal_count];
182 for (i, sig1_opt) in signals_slice.iter().enumerate() {
183 let sig1 = match sig1_opt {
184 Some(s) => s,
185 None => continue, };
187 let (sig1_lsb, sig1_msb) =
188 Self::calculate_bit_range(sig1.start_bit(), sig1.length(), sig1.byte_order());
189
190 for sig2_opt in signals_slice.iter().skip(i + 1) {
191 let sig2 = match sig2_opt {
192 Some(s) => s,
193 None => continue, };
195 let (sig2_lsb, sig2_msb) =
196 Self::calculate_bit_range(sig2.start_bit(), sig2.length(), sig2.byte_order());
197
198 if sig1_lsb <= sig2_msb && sig2_lsb <= sig1_msb {
202 return Err(ParseError::Message(crate::error::lang::SIGNAL_OVERLAP));
203 }
204 }
205 }
206
207 Ok(())
208 }
209
210 #[cfg(any(feature = "alloc", feature = "kernel"))]
211 pub(crate) fn new(
212 id: u32,
213 name: &'a str,
214 dlc: u8,
215 sender: &'a str,
216 signals: &'a [Signal<'a>],
217 ) -> Self {
218 Self {
220 id,
221 name,
222 dlc,
223 sender,
224 signals: Signals::from_signals_slice(signals),
225 }
226 }
227
228 pub(crate) fn new_from_options(
229 id: u32,
230 name: &'a str,
231 dlc: u8,
232 sender: &'a str,
233 signals: &[Option<Signal<'a>>],
234 signal_count: usize,
235 ) -> Self {
236 Self {
238 id,
239 name,
240 dlc,
241 sender,
242 signals: Signals::from_options_slice(signals, signal_count),
243 }
244 }
245
246 pub(crate) fn parse<'b: 'a>(
247 parser: &mut Parser<'b>,
248 signals: &[Option<Signal<'a>>],
249 signal_count: usize,
250 options: crate::ParseOptions,
251 ) -> ParseResult<Self> {
252 parser
254 .expect(crate::BO_.as_bytes())
255 .map_err(|_| ParseError::Expected("Expected BO_ keyword"))?;
256
257 let _ = parser.skip_whitespace();
259
260 let id = parser
262 .parse_u32()
263 .map_err(|_| ParseError::Message(crate::error::lang::MESSAGE_INVALID_ID))?;
264
265 parser
267 .skip_whitespace()
268 .map_err(|_| ParseError::Expected("Expected whitespace"))?;
269
270 let name = parser
272 .parse_identifier()
273 .map_err(|_| ParseError::Message(crate::error::lang::MESSAGE_NAME_EMPTY))?;
274
275 let _ = parser.skip_whitespace();
277
278 parser.expect(b":").map_err(|_| ParseError::Expected("Expected colon"))?;
280
281 let _ = parser.skip_whitespace();
283
284 let dlc = parser
286 .parse_u8()
287 .map_err(|_| ParseError::Message(crate::error::lang::MESSAGE_INVALID_DLC))?;
288
289 parser
291 .skip_whitespace()
292 .map_err(|_| ParseError::Expected("Expected whitespace"))?;
293
294 let sender = parser
296 .parse_identifier()
297 .map_err(|_| ParseError::Message(crate::error::lang::MESSAGE_SENDER_EMPTY))?;
298
299 parser.skip_newlines_and_spaces();
301 if !parser.is_empty() {
302 return Err(ParseError::Expected(
303 "Unexpected content after message sender",
304 ));
305 }
306
307 Self::validate_internal(
309 id,
310 name,
311 dlc,
312 sender,
313 &signals[..signal_count],
314 signal_count,
315 options,
316 )?;
317 Ok(Self::new_from_options(
319 id,
320 name,
321 dlc,
322 sender,
323 signals,
324 signal_count,
325 ))
326 }
327
328 #[inline]
341 #[must_use]
342 pub fn id(&self) -> u32 {
343 self.id
344 }
345
346 #[inline]
359 #[must_use]
360 pub fn name(&self) -> &'a str {
361 self.name
362 }
363
364 #[inline]
380 #[must_use]
381 pub fn dlc(&self) -> u8 {
382 self.dlc
383 }
384
385 #[inline]
386 #[must_use]
387 pub fn sender(&self) -> &'a str {
388 self.sender
389 }
390
391 #[inline]
393 #[must_use]
394 pub fn signals(&self) -> &Signals<'a> {
395 &self.signals
396 }
397
398 #[cfg(feature = "alloc")]
399 #[must_use]
400 pub fn to_dbc_string(&self) -> alloc::string::String {
401 use alloc::format;
402 format!(
403 "BO_ {} {} : {} {}",
404 self.id(),
405 self.name(),
406 self.dlc(),
407 self.sender()
408 )
409 }
410
411 #[cfg(feature = "alloc")]
412 #[must_use]
413 pub fn to_dbc_string_with_signals(&self) -> alloc::string::String {
414 use alloc::string::String;
415 let mut result = String::with_capacity(200 + (self.signals.len() * 100));
416 result.push_str(&self.to_dbc_string());
417 result.push('\n');
418
419 for signal in self.signals().iter() {
420 result.push_str(&signal.to_dbc_string());
421 result.push('\n');
422 }
423
424 result
425 }
426}
427
428#[cfg(feature = "alloc")]
429impl<'a> core::fmt::Display for Message<'a> {
430 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
431 write!(f, "{}", self.to_dbc_string_with_signals())
432 }
433}
434
435#[cfg(test)]
436mod tests {
437 #![allow(clippy::float_cmp)]
438 use super::*;
439 use crate::{Parser, error::ParseError};
440 #[cfg(any(feature = "alloc", feature = "kernel"))]
441 use alloc::{format, vec};
442 #[test]
449 fn test_message_parse_valid() {
450 let data = b"BO_ 256 EngineData : 8 ECM";
451 let mut parser = Parser::new(data).unwrap();
452 const MAX_CAP: usize = crate::Signals::max_capacity();
453 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
454 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
455 assert_eq!(message.id(), 256);
456 assert_eq!(message.name(), "EngineData");
457 assert_eq!(message.dlc(), 8);
458 assert_eq!(message.sender(), "ECM");
459 assert_eq!(message.signals().len(), 0);
460 }
461
462 #[test]
463 fn test_message_parse_invalid_id() {
464 let data = b"BO_ invalid EngineData : 8 ECM";
465 let mut parser = Parser::new(data).unwrap();
466 const MAX_CAP: usize = crate::Signals::max_capacity();
467 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
468 let result = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new());
469 assert!(result.is_err());
470 match result.unwrap_err() {
471 ParseError::Message(_) => {
472 }
474 _ => panic!("Expected ParseError::Message"),
475 }
476 }
477
478 #[test]
479 fn test_message_parse_empty_name() {
480 let data = b"BO_ 256 : 8 ECM";
481 let mut parser = Parser::new(data).unwrap();
482 const MAX_CAP: usize = crate::Signals::max_capacity();
483 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
484 let result = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new());
485 assert!(result.is_err());
486 match result.unwrap_err() {
487 ParseError::Message(_) => {
488 }
490 _ => panic!("Expected ParseError::Message"),
491 }
492 }
493
494 #[test]
495 fn test_message_parse_invalid_dlc() {
496 let data = b"BO_ 256 EngineData : invalid ECM";
497 let mut parser = Parser::new(data).unwrap();
498 const MAX_CAP: usize = crate::Signals::max_capacity();
499 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
500 let result = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new());
501 assert!(result.is_err());
502 match result.unwrap_err() {
503 ParseError::Message(_) => {
504 }
506 _ => panic!("Expected ParseError::Message"),
507 }
508 }
509
510 #[test]
511 fn test_message_parse_empty_sender() {
512 let data = b"BO_ 256 EngineData : 8 ";
513 let mut parser = Parser::new(data).unwrap();
514 const MAX_CAP: usize = crate::Signals::max_capacity();
515 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
516 let result = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new());
517 assert!(result.is_err());
518 match result.unwrap_err() {
519 ParseError::Message(_) => {
520 }
522 _ => panic!("Expected ParseError::Message"),
523 }
524 }
525
526 #[test]
527 fn test_message_parse_with_signals() {
528 let data = b"BO_ 256 EngineData : 8 ECM";
529 let mut parser = Parser::new(data).unwrap();
530
531 let signal1 = Signal::parse(
533 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
534 )
535 .unwrap();
536 let signal2 = Signal::parse(
537 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
538 )
539 .unwrap();
540
541 const MAX_CAP: usize = crate::Signals::max_capacity();
542 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
543 signals[0] = Some(signal1);
544 signals[1] = Some(signal2);
545
546 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
547 assert_eq!(message.id(), 256);
548 assert_eq!(message.name(), "EngineData");
549 assert_eq!(message.dlc(), 8);
550 assert_eq!(message.sender(), "ECM");
551 assert_eq!(message.signals().len(), 2);
552 }
553
554 #[test]
555 fn test_message_signals_iterator() {
556 let data = b"BO_ 256 EngineData : 8 ECM";
557 let mut parser = Parser::new(data).unwrap();
558
559 let signal1 = Signal::parse(
561 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
562 )
563 .unwrap();
564 let signal2 = Signal::parse(
565 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
566 )
567 .unwrap();
568
569 const MAX_CAP: usize = crate::Signals::max_capacity();
570 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
571 signals[0] = Some(signal1);
572 signals[1] = Some(signal2);
573
574 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
575 let mut signals_iter = message.signals().iter();
576 assert_eq!(signals_iter.next().unwrap().name(), "RPM");
577 assert_eq!(signals_iter.next().unwrap().name(), "Temp");
578 assert!(signals_iter.next().is_none());
579 }
580
581 #[test]
582 fn test_message_signal_count() {
583 let data = b"BO_ 256 EngineData : 8 ECM";
584 let mut parser = Parser::new(data).unwrap();
585
586 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
587 [const { None }; crate::Signals::max_capacity()];
588 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
589 assert_eq!(message.signals().len(), 0);
590
591 let data2 = b"BO_ 256 EngineData : 8 ECM";
593 let mut parser2 = Parser::new(data2).unwrap();
594 let signal1 = Signal::parse(
595 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
596 )
597 .unwrap();
598 const MAX_CAP: usize = crate::Signals::max_capacity();
599 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
600 signals[0] = Some(signal1);
601 let message =
602 Message::parse(&mut parser2, &signals, 1, crate::ParseOptions::new()).unwrap();
603 assert_eq!(message.signals().len(), 1);
604 }
605
606 #[test]
607 fn test_message_signal_at() {
608 let data = b"BO_ 256 EngineData : 8 ECM";
609 let mut parser = Parser::new(data).unwrap();
610
611 let signal1 = Signal::parse(
612 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
613 )
614 .unwrap();
615 let signal2 = Signal::parse(
616 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
617 )
618 .unwrap();
619
620 const MAX_CAP: usize = crate::Signals::max_capacity();
621 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
622 signals[0] = Some(signal1);
623 signals[1] = Some(signal2);
624
625 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
626 assert_eq!(message.signals().at(0).unwrap().name(), "RPM");
627 assert_eq!(message.signals().at(1).unwrap().name(), "Temp");
628 assert!(message.signals().at(2).is_none());
629 }
630
631 #[test]
632 fn test_message_find_signal() {
633 let data = b"BO_ 256 EngineData : 8 ECM";
634 let mut parser = Parser::new(data).unwrap();
635
636 let signal1 = Signal::parse(
637 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
638 )
639 .unwrap();
640 let signal2 = Signal::parse(
641 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
642 )
643 .unwrap();
644
645 const MAX_CAP: usize = crate::Signals::max_capacity();
646 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
647 signals[0] = Some(signal1);
648 signals[1] = Some(signal2);
649
650 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
651 assert_eq!(message.signals().find("RPM").unwrap().name(), "RPM");
652 assert_eq!(message.signals().find("Temp").unwrap().name(), "Temp");
653 assert!(message.signals().find("Nonexistent").is_none());
654 }
655
656 #[test]
657 #[cfg(feature = "alloc")]
658 fn test_message_to_dbc_string() {
659 let data = b"BO_ 256 EngineData : 8 ECM";
660 let mut parser = Parser::new(data).unwrap();
661 const MAX_CAP: usize = crate::Signals::max_capacity();
662 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
663 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
664 let dbc_string = message.to_dbc_string();
665 assert_eq!(dbc_string, "BO_ 256 EngineData : 8 ECM");
666 }
667
668 #[test]
669 #[cfg(feature = "alloc")]
670 fn test_message_to_dbc_string_with_signals() {
671 let data = b"BO_ 256 EngineData : 8 ECM";
672 let mut parser = Parser::new(data).unwrap();
673
674 let signal1 = Signal::parse(
675 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
676 )
677 .unwrap();
678 let signal2 = Signal::parse(
679 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
680 )
681 .unwrap();
682
683 const MAX_CAP: usize = crate::Signals::max_capacity();
684 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
685 signals[0] = Some(signal1);
686 signals[1] = Some(signal2);
687
688 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
689 let dbc_string = message.to_dbc_string_with_signals();
690 assert!(dbc_string.contains("BO_ 256 EngineData : 8 ECM"));
691 assert!(dbc_string.contains("SG_ RPM"));
692 assert!(dbc_string.contains("SG_ Temp"));
693 }
694
695 #[test]
696 #[cfg(any(feature = "alloc", feature = "kernel"))]
697 fn test_message_can_2_0a_dlc_limits() {
698 use alloc::format;
699 for dlc in 1..=8 {
702 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
703 let mut parser = Parser::new(data.as_bytes()).unwrap();
704 const MAX_CAP: usize = crate::Signals::max_capacity();
705 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
706 let message =
707 Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
708 assert_eq!(message.dlc(), dlc);
709 }
710 }
711
712 #[test]
713 #[cfg(any(feature = "alloc", feature = "kernel"))]
714 fn test_message_can_2_0b_dlc_limits() {
715 use alloc::format;
716 for dlc in 1..=8 {
719 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
720 let mut parser = Parser::new(data.as_bytes()).unwrap();
721 const MAX_CAP: usize = crate::Signals::max_capacity();
722 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
723 let message =
724 Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
725 assert_eq!(message.dlc(), dlc);
726 }
727 }
728
729 #[test]
730 #[cfg(any(feature = "alloc", feature = "kernel"))]
731 fn test_message_can_fd_dlc_limits() {
732 use alloc::format;
733 for dlc in [1, 8, 12, 16, 20, 24, 32, 48, 64] {
736 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
737 let mut parser = Parser::new(data.as_bytes()).unwrap();
738 const MAX_CAP: usize = crate::Signals::max_capacity();
739 let signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
740 let message =
741 Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
742 assert_eq!(message.dlc(), dlc);
743 }
744 }
745
746 #[test]
747 fn test_message_multiple_signals_boundary_validation() {
748 let data = b"BO_ 256 EngineData : 8 ECM";
750 let mut parser = Parser::new(data).unwrap();
751
752 let signal1 =
755 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|16@0+ (1,0) [0|65535] \"\"").unwrap())
756 .unwrap();
757 let signal2 = Signal::parse(
759 &mut Parser::new(b"SG_ Signal2 : 16|16@0+ (1,0) [0|65535] \"\"").unwrap(),
760 )
761 .unwrap();
762 let signal3 = Signal::parse(
764 &mut Parser::new(b"SG_ Signal3 : 32|16@0+ (1,0) [0|65535] \"\"").unwrap(),
765 )
766 .unwrap();
767 let signal4 = Signal::parse(
769 &mut Parser::new(b"SG_ Signal4 : 48|16@0+ (1,0) [0|65535] \"\"").unwrap(),
770 )
771 .unwrap();
772
773 const MAX_CAP: usize = crate::Signals::max_capacity();
774 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
775 signals[0] = Some(signal1);
776 signals[1] = Some(signal2);
777 signals[2] = Some(signal3);
778 signals[3] = Some(signal4);
779
780 let message = Message::parse(&mut parser, &signals, 4, crate::ParseOptions::new()).unwrap();
781 assert_eq!(message.signals().len(), 4);
782 }
783
784 #[test]
785 fn test_message_big_endian_bit_range_calculation() {
786 let data = b"BO_ 256 EngineData : 8 ECM";
792 let mut parser = Parser::new(data).unwrap();
793
794 let signal =
796 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@1+ (1,0) [0|255] \"\"").unwrap())
797 .unwrap();
798
799 const MAX_CAP: usize = crate::Signals::max_capacity();
800 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
801 signals[0] = Some(signal);
802
803 let message = Message::parse(&mut parser, &signals, 1, crate::ParseOptions::new()).unwrap();
804 assert_eq!(message.signals().len(), 1);
806 }
807
808 #[test]
809 fn test_message_little_endian_bit_range_calculation() {
810 let data = b"BO_ 256 EngineData : 8 ECM";
813 let mut parser = Parser::new(data).unwrap();
814
815 let signal =
817 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap())
818 .unwrap();
819
820 const MAX_CAP: usize = crate::Signals::max_capacity();
821 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
822 signals[0] = Some(signal);
823
824 let message = Message::parse(&mut parser, &signals, 1, crate::ParseOptions::new()).unwrap();
825 assert_eq!(message.signals().len(), 1);
827 }
828
829 #[test]
832 fn test_parse_with_lenient_boundary_check() {
833 let data = b"BO_ 256 Test : 8 ECM";
835 let mut parser = Parser::new(data).unwrap();
836
837 let signal =
839 Signal::parse(&mut Parser::new(b"SG_ CHECKSUM : 63|8@1+ (1,0) [0|255] \"\"").unwrap())
840 .unwrap();
841
842 const MAX_CAP: usize = crate::Signals::max_capacity();
843 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
844 signals[0] = Some(signal);
845
846 let result = Message::parse(&mut parser, &signals, 1, crate::ParseOptions::new());
848 assert!(result.is_err());
849
850 let mut parser2 = Parser::new(data).unwrap();
852 let message =
853 Message::parse(&mut parser2, &signals, 1, crate::ParseOptions::lenient()).unwrap();
854 assert_eq!(message.signals().len(), 1);
855 assert_eq!(message.signals().at(0).unwrap().name(), "CHECKSUM");
856 }
857
858 #[test]
859 #[cfg(feature = "alloc")]
860 fn test_message_to_dbc_string_empty_signals() {
861 let data = b"BO_ 256 EngineData : 8 ECM";
862 let mut parser = Parser::new(data).unwrap();
863 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
864 [const { None }; crate::Signals::max_capacity()];
865 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
866
867 let dbc_string = message.to_dbc_string();
868 assert_eq!(dbc_string, "BO_ 256 EngineData : 8 ECM");
869
870 let dbc_string_with_signals = message.to_dbc_string_with_signals();
871 assert_eq!(dbc_string_with_signals, "BO_ 256 EngineData : 8 ECM\n");
872 }
873
874 #[test]
875 #[cfg(feature = "alloc")]
876 fn test_message_to_dbc_string_special_characters() {
877 let data = b"BO_ 1234 Test_Message_With_Underscores : 4 Sender_Node";
878 let mut parser = Parser::new(data).unwrap();
879 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
880 [const { None }; crate::Signals::max_capacity()];
881 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
882
883 let dbc_string = message.to_dbc_string();
884 assert_eq!(
885 dbc_string,
886 "BO_ 1234 Test_Message_With_Underscores : 4 Sender_Node"
887 );
888 }
889
890 #[test]
891 #[cfg(feature = "alloc")]
892 fn test_message_to_dbc_string_extended_id() {
893 let data = b"BO_ 536870911 ExtendedID : 8 ECM";
895 let mut parser = Parser::new(data).unwrap();
896 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
897 [const { None }; crate::Signals::max_capacity()];
898 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
899
900 let dbc_string = message.to_dbc_string();
901 assert_eq!(dbc_string, "BO_ 536870911 ExtendedID : 8 ECM");
902 }
903
904 #[test]
905 #[cfg(feature = "alloc")]
906 fn test_message_to_dbc_string_dlc_edge_cases() {
907 let data = b"BO_ 256 MinDLC : 1 ECM";
909 let mut parser = Parser::new(data).unwrap();
910 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
911 [const { None }; crate::Signals::max_capacity()];
912 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
913 assert_eq!(message.to_dbc_string(), "BO_ 256 MinDLC : 1 ECM");
914
915 let data2 = b"BO_ 257 MaxDLC : 64 ECM";
917 let mut parser2 = Parser::new(data2).unwrap();
918 let message2 =
919 Message::parse(&mut parser2, &signals, 0, crate::ParseOptions::new()).unwrap();
920 assert_eq!(message2.to_dbc_string(), "BO_ 257 MaxDLC : 64 ECM");
921 }
922
923 #[test]
924 fn test_message_signals_is_empty() {
925 let data = b"BO_ 256 EngineData : 8 ECM";
926 let mut parser = Parser::new(data).unwrap();
927 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
928 [const { None }; crate::Signals::max_capacity()];
929 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
930 assert!(message.signals().is_empty());
931 assert_eq!(message.signals().len(), 0);
932 }
933
934 #[test]
935 fn test_message_signals_at_out_of_bounds() {
936 let data = b"BO_ 256 EngineData : 8 ECM";
937 let mut parser = Parser::new(data).unwrap();
938
939 let signal = Signal::parse(
940 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
941 )
942 .unwrap();
943
944 const MAX_CAP: usize = crate::Signals::max_capacity();
945 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
946 signals[0] = Some(signal);
947
948 let message = Message::parse(&mut parser, &signals, 1, crate::ParseOptions::new()).unwrap();
949
950 assert!(message.signals().at(0).is_some());
952 assert_eq!(message.signals().at(0).unwrap().name(), "RPM");
953
954 assert!(message.signals().at(1).is_none());
956 assert!(message.signals().at(100).is_none());
957 assert!(message.signals().at(usize::MAX).is_none());
958 }
959
960 #[test]
961 fn test_message_signals_find_case_sensitive() {
962 let data = b"BO_ 256 EngineData : 8 ECM";
963 let mut parser = Parser::new(data).unwrap();
964
965 let signal1 = Signal::parse(
966 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
967 )
968 .unwrap();
969 let signal2 = Signal::parse(
970 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
971 )
972 .unwrap();
973
974 const MAX_CAP: usize = crate::Signals::max_capacity();
975 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
976 signals[0] = Some(signal1);
977 signals[1] = Some(signal2);
978
979 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
980
981 assert!(message.signals().find("RPM").is_some());
983 assert_eq!(message.signals().find("RPM").unwrap().name(), "RPM");
984
985 assert!(message.signals().find("rpm").is_none());
987 assert!(message.signals().find("Rpm").is_none());
988
989 assert!(message.signals().find("Temp").is_some());
991 assert_eq!(message.signals().find("Temp").unwrap().name(), "Temp");
992
993 assert!(message.signals().find("Nonexistent").is_none());
995 assert!(message.signals().find("").is_none());
996 }
997
998 #[test]
999 fn test_message_signals_find_empty_collection() {
1000 let data = b"BO_ 256 EngineData : 8 ECM";
1001 let mut parser = Parser::new(data).unwrap();
1002 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
1003 [const { None }; crate::Signals::max_capacity()];
1004 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
1005
1006 assert!(message.signals().find("RPM").is_none());
1007 assert!(message.signals().find("").is_none());
1008 }
1009
1010 #[test]
1011 #[cfg(feature = "alloc")]
1012 fn test_message_display_trait() {
1013 use alloc::format;
1014 let data = b"BO_ 256 EngineData : 8 ECM";
1015 let mut parser = Parser::new(data).unwrap();
1016
1017 let signal = Signal::parse(
1019 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\" *").unwrap(),
1020 )
1021 .unwrap();
1022
1023 const MAX_CAP: usize = crate::Signals::max_capacity();
1024 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
1025 signals[0] = Some(signal);
1026
1027 let message = Message::parse(&mut parser, &signals, 1, crate::ParseOptions::new()).unwrap();
1028
1029 let display_str = format!("{}", message);
1030 assert!(display_str.contains("BO_ 256 EngineData : 8 ECM"));
1031 assert!(display_str.contains("SG_ RPM"));
1032 }
1033
1034 #[test]
1035 #[cfg(feature = "alloc")]
1036 fn test_message_to_dbc_string_with_signals_multiple() {
1037 let data = b"BO_ 256 EngineData : 8 ECM";
1038 let mut parser = Parser::new(data).unwrap();
1039
1040 let signal1 = Signal::parse(
1042 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\" *").unwrap(),
1043 )
1044 .unwrap();
1045
1046 let signal2 = Signal::parse(
1047 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\" *").unwrap(),
1048 )
1049 .unwrap();
1050
1051 const MAX_CAP: usize = crate::Signals::max_capacity();
1052 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
1053 signals[0] = Some(signal1);
1054 signals[1] = Some(signal2);
1055
1056 let message = Message::parse(&mut parser, &signals, 2, crate::ParseOptions::new()).unwrap();
1057
1058 let dbc_string = message.to_dbc_string_with_signals();
1059 assert!(dbc_string.contains("BO_ 256 EngineData : 8 ECM"));
1060 assert!(dbc_string.contains("SG_ RPM"));
1061 assert!(dbc_string.contains("SG_ Temp"));
1062 #[cfg(any(feature = "alloc", feature = "kernel"))]
1064 use crate::compat::Vec;
1065 let lines: Vec<&str> = dbc_string.lines().collect();
1066 assert!(lines.len() >= 3); }
1068
1069 #[test]
1070 fn test_message_getters_edge_cases() {
1071 let data = b"BO_ 0 A : 1 B";
1073 let mut parser = Parser::new(data).unwrap();
1074 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
1075 [const { None }; crate::Signals::max_capacity()];
1076 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
1077
1078 assert_eq!(message.id(), 0);
1079 assert_eq!(message.name(), "A");
1080 assert_eq!(message.dlc(), 1);
1081 assert_eq!(message.sender(), "B");
1082 }
1083
1084 #[test]
1085 fn test_message_signals_iterator_empty() {
1086 let data = b"BO_ 256 EngineData : 8 ECM";
1087 let mut parser = Parser::new(data).unwrap();
1088 let signals: [Option<Signal>; crate::Signals::max_capacity()] =
1089 [const { None }; crate::Signals::max_capacity()];
1090 let message = Message::parse(&mut parser, &signals, 0, crate::ParseOptions::new()).unwrap();
1091
1092 let mut iter = message.signals().iter();
1093 assert!(iter.next().is_none());
1094 }
1095
1096 #[test]
1097 fn test_message_signals_iterator_multiple() {
1098 let data = b"BO_ 256 EngineData : 8 ECM";
1099 let mut parser = Parser::new(data).unwrap();
1100
1101 let signal1 =
1102 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap())
1103 .unwrap();
1104 let signal2 =
1105 Signal::parse(&mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap())
1106 .unwrap();
1107 let signal3 =
1108 Signal::parse(&mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap())
1109 .unwrap();
1110
1111 const MAX_CAP: usize = crate::Signals::max_capacity();
1112 let mut signals: [Option<Signal>; MAX_CAP] = [const { None }; MAX_CAP];
1113 signals[0] = Some(signal1);
1114 signals[1] = Some(signal2);
1115 signals[2] = Some(signal3);
1116
1117 let message = Message::parse(&mut parser, &signals, 3, crate::ParseOptions::new()).unwrap();
1118
1119 let mut iter = message.signals().iter();
1120 assert_eq!(iter.next().unwrap().name(), "Signal1");
1121 assert_eq!(iter.next().unwrap().name(), "Signal2");
1122 assert_eq!(iter.next().unwrap().name(), "Signal3");
1123 assert!(iter.next().is_none());
1124
1125 #[cfg(any(feature = "alloc", feature = "kernel"))]
1127 {
1128 use crate::compat::Vec;
1129 use alloc::vec;
1130 let names: Vec<&str> = message.signals().iter().map(|s| s.name()).collect();
1131 #[cfg(feature = "kernel")]
1133 let names: alloc::vec::Vec<&str> = names.into();
1134 assert_eq!(names, vec!["Signal1", "Signal2", "Signal3"]);
1135 }
1136 }
1137}