1use super::SignalList;
2use crate::{
3 ByteOrder, Error, MAX_NAME_SIZE, MAX_SIGNALS_PER_MESSAGE, Parser, Result, Signal,
4 compat::String, error::lang,
5};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub struct Message {
36 id: u32,
37 name: String<{ MAX_NAME_SIZE }>,
38 dlc: u8,
39 sender: String<{ MAX_NAME_SIZE }>,
40 signals: SignalList,
41}
42
43impl Message {
44 #[allow(clippy::similar_names)] fn bit_range(start_bit: u16, length: u16, byte_order: ByteOrder) -> (u16, u16) {
46 let start = start_bit;
47 let len = length;
48
49 match byte_order {
50 ByteOrder::LittleEndian => {
51 (start, start + len - 1)
54 }
55 ByteOrder::BigEndian => {
56 let byte_num = start / 8;
69 let bit_in_byte = start % 8;
70 let physical_msb = byte_num * 8 + (7 - bit_in_byte);
71
72 let lsb_be_bit = start + len - 1;
75 let lsb_byte_num = lsb_be_bit / 8;
76 let lsb_bit_in_byte = lsb_be_bit % 8;
77 let physical_lsb = lsb_byte_num * 8 + (7 - lsb_bit_in_byte);
78
79 if physical_lsb <= physical_msb {
81 (physical_lsb, physical_msb)
82 } else {
83 (physical_msb, physical_lsb)
84 }
85 }
86 }
87 }
88
89 #[allow(clippy::similar_names)] pub(crate) fn validate_internal(
91 id: u32,
92 name: &str,
93 dlc: u8,
94 sender: &str,
95 signals: &[Signal],
96 ) -> Result<()> {
97 const MAX_EXTENDED_ID: u32 = 0x1FFF_FFFF; if let Some(err) = crate::check_max_limit(
109 signals.len(),
110 MAX_SIGNALS_PER_MESSAGE,
111 Error::Validation(lang::MESSAGE_TOO_MANY_SIGNALS),
112 ) {
113 return Err(err);
114 }
115
116 if name.trim().is_empty() {
117 return Err(Error::Validation(lang::MESSAGE_NAME_EMPTY));
118 }
119
120 if sender.trim().is_empty() {
121 return Err(Error::Validation(lang::MESSAGE_SENDER_EMPTY));
122 }
123
124 if dlc == 0 {
129 return Err(Error::Validation(lang::MESSAGE_DLC_TOO_SMALL));
130 }
131 if dlc > 64 {
132 return Err(Error::Validation(lang::MESSAGE_DLC_TOO_LARGE));
133 }
134
135 if id > MAX_EXTENDED_ID {
139 return Err(Error::Validation(lang::MESSAGE_ID_OUT_OF_RANGE));
140 }
141
142 let max_bits = u16::from(dlc) * 8;
148 for signal in signals.iter() {
149 let (lsb, msb) =
151 Self::bit_range(signal.start_bit(), signal.length(), signal.byte_order());
152 let signal_max_bit = lsb.max(msb);
155 if signal_max_bit >= max_bits {
156 return Err(Error::Validation(lang::SIGNAL_EXTENDS_BEYOND_MESSAGE));
157 }
158 }
159
160 for (i, sig1) in signals.iter().enumerate() {
166 let (sig1_lsb, sig1_msb) =
167 Self::bit_range(sig1.start_bit(), sig1.length(), sig1.byte_order());
168
169 for sig2 in signals.iter().skip(i + 1) {
170 let (sig2_lsb, sig2_msb) =
171 Self::bit_range(sig2.start_bit(), sig2.length(), sig2.byte_order());
172
173 if sig1_lsb <= sig2_msb && sig2_lsb <= sig1_msb {
177 return Err(Error::Validation(lang::SIGNAL_OVERLAP));
178 }
179 }
180 }
181
182 Ok(())
183 }
184
185 #[cfg(feature = "std")]
186 pub(crate) fn new(
187 id: u32,
188 name: String<{ crate::MAX_NAME_SIZE }>,
189 dlc: u8,
190 sender: String<{ crate::MAX_NAME_SIZE }>,
191 signals: impl Into<SignalList>,
192 ) -> Self {
193 Self {
195 id,
196 name,
197 dlc,
198 sender,
199 signals: signals.into(),
200 }
201 }
202
203 pub(crate) fn new_from_signals(
204 id: u32,
205 name: &str,
206 dlc: u8,
207 sender: &str,
208 signals: &[Signal],
209 ) -> Self {
210 let name_str: String<{ crate::MAX_NAME_SIZE }> = String::try_from(name)
212 .map_err(|_| Error::Validation(lang::MAX_NAME_SIZE_EXCEEDED))
213 .unwrap();
214 let sender_str: String<{ crate::MAX_NAME_SIZE }> = String::try_from(sender)
215 .map_err(|_| Error::Validation(lang::MAX_NAME_SIZE_EXCEEDED))
216 .unwrap();
217 Self {
218 id,
219 name: name_str,
220 dlc,
221 sender: sender_str,
222 signals: SignalList::from_slice(signals),
223 }
224 }
225
226 pub(crate) fn parse(parser: &mut Parser, signals: &[Signal]) -> Result<Self> {
227 parser
229 .expect(crate::BO_.as_bytes())
230 .map_err(|_| Error::Expected("Expected BO_ keyword"))?;
231
232 let _ = parser.skip_whitespace();
234
235 let id = parser
237 .parse_u32()
238 .map_err(|_| Error::Message(crate::error::lang::MESSAGE_INVALID_ID))?;
239
240 parser.skip_whitespace().map_err(|_| Error::Expected("Expected whitespace"))?;
242
243 let name = parser
245 .parse_identifier()
246 .map_err(|_| Error::Message(crate::error::lang::MESSAGE_NAME_EMPTY))?;
247
248 let _ = parser.skip_whitespace();
250
251 parser.expect(b":").map_err(|_| Error::Expected("Expected colon"))?;
253
254 let _ = parser.skip_whitespace();
256
257 let dlc = parser
259 .parse_u8()
260 .map_err(|_| Error::Message(crate::error::lang::MESSAGE_INVALID_DLC))?;
261
262 parser.skip_whitespace().map_err(|_| Error::Expected("Expected whitespace"))?;
264
265 let sender = parser
267 .parse_identifier()
268 .map_err(|_| Error::Message(crate::error::lang::MESSAGE_SENDER_EMPTY))?;
269
270 parser.skip_newlines_and_spaces();
272 if !parser.is_empty() {
273 return Err(Error::Expected("Unexpected content after message sender"));
274 }
275
276 Self::validate_internal(id, name, dlc, sender, signals).map_err(|e| {
278 crate::error::map_val_error(e, crate::error::Error::Message, || {
279 crate::error::Error::Message(crate::error::lang::MESSAGE_ERROR_PREFIX)
280 })
281 })?;
282 Ok(Self::new_from_signals(id, name, dlc, sender, signals))
284 }
285
286 #[inline]
299 #[must_use]
300 pub fn id(&self) -> u32 {
301 self.id
302 }
303
304 #[inline]
317 #[must_use]
318 pub fn name(&self) -> &str {
319 self.name.as_str()
320 }
321
322 #[inline]
338 #[must_use]
339 pub fn dlc(&self) -> u8 {
340 self.dlc
341 }
342
343 #[inline]
344 #[must_use]
345 pub fn sender(&self) -> &str {
346 self.sender.as_str()
347 }
348
349 #[inline]
351 #[must_use]
352 pub fn signals(&self) -> &SignalList {
353 &self.signals
354 }
355
356 #[cfg(feature = "std")]
357 #[must_use]
358 pub fn to_dbc_string(&self) -> std::string::String {
359 format!(
360 "BO_ {} {} : {} {}",
361 self.id(),
362 self.name(),
363 self.dlc(),
364 self.sender()
365 )
366 }
367
368 #[cfg(feature = "std")]
369 #[must_use]
370 pub fn to_string_full(&self) -> std::string::String {
371 let mut result = std::string::String::with_capacity(200 + (self.signals.len() * 100));
372 result.push_str(&self.to_dbc_string());
373 result.push('\n');
374
375 for signal in self.signals().iter() {
376 result.push_str(&signal.to_dbc_string());
377 result.push('\n');
378 }
379
380 result
381 }
382}
383
384#[cfg(feature = "std")]
385impl core::fmt::Display for Message {
386 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
387 write!(f, "{}", self.to_string_full())
388 }
389}
390
391#[cfg(test)]
392mod tests {
393 #![allow(clippy::float_cmp)]
394 use super::*;
395 use crate::{Error, Parser};
396
397 #[test]
403 fn test_message_parse_valid() {
404 let data = b"BO_ 256 EngineData : 8 ECM";
405 let mut parser = Parser::new(data).unwrap();
406 let signals: &[Signal] = &[];
407 let message = Message::parse(&mut parser, signals).unwrap();
408 assert_eq!(message.id(), 256);
409 assert_eq!(message.name(), "EngineData");
410 assert_eq!(message.dlc(), 8);
411 assert_eq!(message.sender(), "ECM");
412 assert_eq!(message.signals().len(), 0);
413 }
414
415 #[test]
416 fn test_message_parse_invalid_id() {
417 let data = b"BO_ invalid EngineData : 8 ECM";
418 let mut parser = Parser::new(data).unwrap();
419 let signals: &[Signal] = &[];
420 let result = Message::parse(&mut parser, signals);
421 assert!(result.is_err());
422 match result.unwrap_err() {
423 Error::Message(_) => {
424 }
426 _ => panic!("Expected Error::Message"),
427 }
428 }
429
430 #[test]
431 fn test_message_parse_empty_name() {
432 let data = b"BO_ 256 : 8 ECM";
433 let mut parser = Parser::new(data).unwrap();
434 let signals: &[Signal] = &[];
435 let result = Message::parse(&mut parser, signals);
436 assert!(result.is_err());
437 match result.unwrap_err() {
438 Error::Message(_) => {
439 }
441 _ => panic!("Expected Error::Message"),
442 }
443 }
444
445 #[test]
446 fn test_message_parse_invalid_dlc() {
447 let data = b"BO_ 256 EngineData : invalid ECM";
448 let mut parser = Parser::new(data).unwrap();
449 let signals: &[Signal] = &[];
450 let result = Message::parse(&mut parser, signals);
451 assert!(result.is_err());
452 match result.unwrap_err() {
453 Error::Message(_) => {
454 }
456 _ => panic!("Expected Error::Message"),
457 }
458 }
459
460 #[test]
461 fn test_message_parse_empty_sender() {
462 let data = b"BO_ 256 EngineData : 8 ";
463 let mut parser = Parser::new(data).unwrap();
464 let signals: &[Signal] = &[];
465 let result = Message::parse(&mut parser, signals);
466 assert!(result.is_err());
467 match result.unwrap_err() {
468 Error::Message(_) => {
469 }
471 _ => panic!("Expected Error::Message"),
472 }
473 }
474
475 #[test]
476 fn test_message_parse_with_signals() {
477 let data = b"BO_ 256 EngineData : 8 ECM";
478 let mut parser = Parser::new(data).unwrap();
479
480 let signal1 = Signal::parse(
482 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
483 )
484 .unwrap();
485 let signal2 = Signal::parse(
486 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
487 )
488 .unwrap();
489
490 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
491 assert_eq!(message.id(), 256);
492 assert_eq!(message.name(), "EngineData");
493 assert_eq!(message.dlc(), 8);
494 assert_eq!(message.sender(), "ECM");
495 assert_eq!(message.signals().len(), 2);
496 }
497
498 #[test]
499 fn test_message_signals_iterator() {
500 let data = b"BO_ 256 EngineData : 8 ECM";
501 let mut parser = Parser::new(data).unwrap();
502
503 let signal1 = Signal::parse(
505 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
506 )
507 .unwrap();
508 let signal2 = Signal::parse(
509 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
510 )
511 .unwrap();
512
513 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
514 let mut signals_iter = message.signals().iter();
515 assert_eq!(signals_iter.next().unwrap().name(), "RPM");
516 assert_eq!(signals_iter.next().unwrap().name(), "Temp");
517 assert!(signals_iter.next().is_none());
518 }
519
520 #[test]
521 fn test_message_signal_count() {
522 let data = b"BO_ 256 EngineData : 8 ECM";
523 let mut parser = Parser::new(data).unwrap();
524
525 let signals: &[Signal] = &[];
526 let message = Message::parse(&mut parser, signals).unwrap();
527 assert_eq!(message.signals().len(), 0);
528
529 let data2 = b"BO_ 256 EngineData : 8 ECM";
531 let mut parser2 = Parser::new(data2).unwrap();
532 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 message = Message::parse(&mut parser2, &[signal1]).unwrap();
537 assert_eq!(message.signals().len(), 1);
538 }
539
540 #[test]
541 fn test_message_signal_at() {
542 let data = b"BO_ 256 EngineData : 8 ECM";
543 let mut parser = Parser::new(data).unwrap();
544
545 let signal1 = Signal::parse(
546 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
547 )
548 .unwrap();
549 let signal2 = Signal::parse(
550 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
551 )
552 .unwrap();
553
554 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
555 assert_eq!(message.signals().at(0).unwrap().name(), "RPM");
556 assert_eq!(message.signals().at(1).unwrap().name(), "Temp");
557 assert!(message.signals().at(2).is_none());
558 }
559
560 #[test]
561 fn test_message_find_signal() {
562 let data = b"BO_ 256 EngineData : 8 ECM";
563 let mut parser = Parser::new(data).unwrap();
564
565 let signal1 = Signal::parse(
566 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
567 )
568 .unwrap();
569 let signal2 = Signal::parse(
570 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
571 )
572 .unwrap();
573
574 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
575 assert_eq!(message.signals().find("RPM").unwrap().name(), "RPM");
576 assert_eq!(message.signals().find("Temp").unwrap().name(), "Temp");
577 assert!(message.signals().find("Nonexistent").is_none());
578 }
579
580 #[test]
581 fn test_message_multiple_signals_boundary_validation() {
582 let data = b"BO_ 256 EngineData : 8 ECM";
584 let mut parser = Parser::new(data).unwrap();
585
586 let signal1 =
589 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|16@0+ (1,0) [0|65535] \"\"").unwrap())
590 .unwrap();
591 let signal2 = Signal::parse(
593 &mut Parser::new(b"SG_ Signal2 : 16|16@0+ (1,0) [0|65535] \"\"").unwrap(),
594 )
595 .unwrap();
596 let signal3 = Signal::parse(
598 &mut Parser::new(b"SG_ Signal3 : 32|16@0+ (1,0) [0|65535] \"\"").unwrap(),
599 )
600 .unwrap();
601 let signal4 = Signal::parse(
603 &mut Parser::new(b"SG_ Signal4 : 48|16@0+ (1,0) [0|65535] \"\"").unwrap(),
604 )
605 .unwrap();
606
607 let message = Message::parse(&mut parser, &[signal1, signal2, signal3, signal4]).unwrap();
608 assert_eq!(message.signals().len(), 4);
609 }
610
611 #[test]
612 fn test_message_big_endian_bit_range_calculation() {
613 let data = b"BO_ 256 EngineData : 8 ECM";
619 let mut parser = Parser::new(data).unwrap();
620
621 let signal =
623 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@1+ (1,0) [0|255] \"\"").unwrap())
624 .unwrap();
625
626 let message = Message::parse(&mut parser, &[signal]).unwrap();
627 assert_eq!(message.signals().len(), 1);
629 }
630
631 #[test]
632 fn test_message_little_endian_bit_range_calculation() {
633 let data = b"BO_ 256 EngineData : 8 ECM";
636 let mut parser = Parser::new(data).unwrap();
637
638 let signal =
640 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap())
641 .unwrap();
642
643 let message = Message::parse(&mut parser, &[signal]).unwrap();
644 assert_eq!(message.signals().len(), 1);
646 }
647
648 #[test]
651 fn test_message_signals_is_empty() {
652 let data = b"BO_ 256 EngineData : 8 ECM";
653 let mut parser = Parser::new(data).unwrap();
654 let signals: &[Signal] = &[];
655 let message = Message::parse(&mut parser, signals).unwrap();
656 assert!(message.signals().is_empty());
657 assert_eq!(message.signals().len(), 0);
658 }
659
660 #[test]
661 fn test_message_signals_at_out_of_bounds() {
662 let data = b"BO_ 256 EngineData : 8 ECM";
663 let mut parser = Parser::new(data).unwrap();
664
665 let signal = Signal::parse(
666 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
667 )
668 .unwrap();
669
670 let message = Message::parse(&mut parser, &[signal]).unwrap();
671
672 assert!(message.signals().at(0).is_some());
674 assert_eq!(message.signals().at(0).unwrap().name(), "RPM");
675
676 assert!(message.signals().at(1).is_none());
678 assert!(message.signals().at(100).is_none());
679 assert!(message.signals().at(usize::MAX).is_none());
680 }
681
682 #[test]
683 fn test_message_signals_find_case_sensitive() {
684 let data = b"BO_ 256 EngineData : 8 ECM";
685 let mut parser = Parser::new(data).unwrap();
686
687 let signal1 = Signal::parse(
688 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
689 )
690 .unwrap();
691 let signal2 = Signal::parse(
692 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
693 )
694 .unwrap();
695
696 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
697
698 assert!(message.signals().find("RPM").is_some());
700 assert_eq!(message.signals().find("RPM").unwrap().name(), "RPM");
701
702 assert!(message.signals().find("rpm").is_none());
704 assert!(message.signals().find("Rpm").is_none());
705
706 assert!(message.signals().find("Temp").is_some());
708 assert_eq!(message.signals().find("Temp").unwrap().name(), "Temp");
709
710 assert!(message.signals().find("Nonexistent").is_none());
712 assert!(message.signals().find("").is_none());
713 }
714
715 #[test]
716 fn test_message_signals_find_empty_collection() {
717 let data = b"BO_ 256 EngineData : 8 ECM";
718 let mut parser = Parser::new(data).unwrap();
719 let signals: &[Signal] = &[];
720 let message = Message::parse(&mut parser, signals).unwrap();
721
722 assert!(message.signals().find("RPM").is_none());
723 assert!(message.signals().find("").is_none());
724 }
725
726 #[test]
727 fn test_message_getters_edge_cases() {
728 let data = b"BO_ 0 A : 1 B";
730 let mut parser = Parser::new(data).unwrap();
731 let signals: &[Signal] = &[];
732 let message = Message::parse(&mut parser, signals).unwrap();
733
734 assert_eq!(message.id(), 0);
735 assert_eq!(message.name(), "A");
736 assert_eq!(message.dlc(), 1);
737 assert_eq!(message.sender(), "B");
738 }
739
740 #[test]
741 fn test_message_signals_iterator_empty() {
742 let data = b"BO_ 256 EngineData : 8 ECM";
743 let mut parser = Parser::new(data).unwrap();
744 let signals: &[Signal] = &[];
745 let message = Message::parse(&mut parser, signals).unwrap();
746
747 let mut iter = message.signals().iter();
748 assert!(iter.next().is_none());
749 }
750
751 #[test]
752 fn test_message_signals_iterator_multiple() {
753 let data = b"BO_ 256 EngineData : 8 ECM";
754 let mut parser = Parser::new(data).unwrap();
755
756 let signal1 =
757 Signal::parse(&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap())
758 .unwrap();
759 let signal2 =
760 Signal::parse(&mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap())
761 .unwrap();
762 let signal3 =
763 Signal::parse(&mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap())
764 .unwrap();
765
766 let message = Message::parse(&mut parser, &[signal1, signal2, signal3]).unwrap();
767
768 let mut iter = message.signals().iter();
769 assert_eq!(iter.next().unwrap().name(), "Signal1");
770 assert_eq!(iter.next().unwrap().name(), "Signal2");
771 assert_eq!(iter.next().unwrap().name(), "Signal3");
772 assert!(iter.next().is_none());
773 }
774
775 #[cfg(feature = "std")]
777 mod tests_std {
778 use super::*;
779
780 #[test]
781 fn test_message_can_2_0a_dlc_limits() {
782 for dlc in 1..=8 {
785 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
786 let mut parser = Parser::new(data.as_bytes()).unwrap();
787 let signals: &[Signal] = &[];
788 let message = Message::parse(&mut parser, signals).unwrap();
789 assert_eq!(message.dlc(), dlc);
790 }
791 }
792
793 #[test]
794 fn test_message_can_2_0b_dlc_limits() {
795 for dlc in 1..=8 {
798 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
799 let mut parser = Parser::new(data.as_bytes()).unwrap();
800 let signals: &[Signal] = &[];
801 let message = Message::parse(&mut parser, signals).unwrap();
802 assert_eq!(message.dlc(), dlc);
803 }
804 }
805
806 #[test]
807 fn test_message_can_fd_dlc_limits() {
808 for dlc in [1, 8, 12, 16, 20, 24, 32, 48, 64] {
811 let data = format!("BO_ 256 EngineData : {} ECM", dlc);
812 let mut parser = Parser::new(data.as_bytes()).unwrap();
813 let signals: &[Signal] = &[];
814 let message = Message::parse(&mut parser, signals).unwrap();
815 assert_eq!(message.dlc(), dlc);
816 }
817 }
818 #[test]
819 fn test_message_to_dbc_string() {
820 let data = b"BO_ 256 EngineData : 8 ECM";
821 let mut parser = Parser::new(data).unwrap();
822 let signals: &[Signal] = &[];
823 let message = Message::parse(&mut parser, signals).unwrap();
824 let dbc_string = message.to_dbc_string();
825 assert_eq!(dbc_string, "BO_ 256 EngineData : 8 ECM");
826 }
827
828 #[test]
829 fn test_message_to_string_full() {
830 let data = b"BO_ 256 EngineData : 8 ECM";
831 let mut parser = Parser::new(data).unwrap();
832
833 let signal1 = Signal::parse(
834 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
835 )
836 .unwrap();
837 let signal2 = Signal::parse(
838 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
839 )
840 .unwrap();
841
842 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
843 let dbc_string = message.to_string_full();
844 assert!(dbc_string.contains("BO_ 256 EngineData : 8 ECM"));
845 assert!(dbc_string.contains("SG_ RPM"));
846 assert!(dbc_string.contains("SG_ Temp"));
847 }
848
849 #[test]
850 fn test_message_to_dbc_string_empty_signals() {
851 let data = b"BO_ 256 EngineData : 8 ECM";
852 let mut parser = Parser::new(data).unwrap();
853 let signals: &[Signal] = &[];
854 let message = Message::parse(&mut parser, signals).unwrap();
855
856 let dbc_string = message.to_dbc_string();
857 assert_eq!(dbc_string, "BO_ 256 EngineData : 8 ECM");
858
859 let dbc_string_with_signals = message.to_string_full();
860 assert_eq!(dbc_string_with_signals, "BO_ 256 EngineData : 8 ECM\n");
861 }
862
863 #[test]
864 fn test_message_to_dbc_string_special_characters() {
865 let data = b"BO_ 1234 Test_Message_With_Underscores : 4 Sender_Node";
866 let mut parser = Parser::new(data).unwrap();
867 let signals: &[Signal] = &[];
868 let message = Message::parse(&mut parser, signals).unwrap();
869
870 let dbc_string = message.to_dbc_string();
871 assert_eq!(
872 dbc_string,
873 "BO_ 1234 Test_Message_With_Underscores : 4 Sender_Node"
874 );
875 }
876
877 #[test]
878 fn test_message_to_dbc_string_extended_id() {
879 let data = b"BO_ 536870911 ExtendedID : 8 ECM";
881 let mut parser = Parser::new(data).unwrap();
882 let signals: &[Signal] = &[];
883 let message = Message::parse(&mut parser, signals).unwrap();
884
885 let dbc_string = message.to_dbc_string();
886 assert_eq!(dbc_string, "BO_ 536870911 ExtendedID : 8 ECM");
887 }
888
889 #[test]
890 fn test_message_to_dbc_string_dlc_edge_cases() {
891 let data = b"BO_ 256 MinDLC : 1 ECM";
893 let mut parser = Parser::new(data).unwrap();
894 let signals: &[Signal] = &[];
895 let message = Message::parse(&mut parser, signals).unwrap();
896 assert_eq!(message.to_dbc_string(), "BO_ 256 MinDLC : 1 ECM");
897
898 let data2 = b"BO_ 257 MaxDLC : 64 ECM";
900 let mut parser2 = Parser::new(data2).unwrap();
901 let signals_empty: &[Signal] = &[];
902 let message2 = Message::parse(&mut parser2, signals_empty).unwrap();
903 assert_eq!(message2.to_dbc_string(), "BO_ 257 MaxDLC : 64 ECM");
904 }
905
906 #[test]
907 fn test_message_display_trait() {
908 let data = b"BO_ 256 EngineData : 8 ECM";
909 let mut parser = Parser::new(data).unwrap();
910
911 let signal = Signal::parse(
913 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\" *").unwrap(),
914 )
915 .unwrap();
916
917 let message = Message::parse(&mut parser, &[signal]).unwrap();
918
919 let display_str = format!("{}", message);
920 assert!(display_str.contains("BO_ 256 EngineData : 8 ECM"));
921 assert!(display_str.contains("SG_ RPM"));
922 }
923
924 #[test]
925 fn test_message_to_string_full_multiple() {
926 let data = b"BO_ 256 EngineData : 8 ECM";
927 let mut parser = Parser::new(data).unwrap();
928
929 let signal1 = Signal::parse(
931 &mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\" *").unwrap(),
932 )
933 .unwrap();
934
935 let signal2 = Signal::parse(
936 &mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\" *").unwrap(),
937 )
938 .unwrap();
939
940 let message = Message::parse(&mut parser, &[signal1, signal2]).unwrap();
941
942 let dbc_string = message.to_string_full();
943 assert!(dbc_string.contains("BO_ 256 EngineData : 8 ECM"));
944 assert!(dbc_string.contains("SG_ RPM"));
945 assert!(dbc_string.contains("SG_ Temp"));
946 let lines: Vec<&str> = dbc_string.lines().collect();
948 assert!(lines.len() >= 3); }
950
951 #[test]
952 fn test_message_signals_iterator_collect() {
953 let data = b"BO_ 256 EngineData : 8 ECM";
954 let mut parser = Parser::new(data).unwrap();
955
956 let signal1 = Signal::parse(
957 &mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
958 )
959 .unwrap();
960 let signal2 = Signal::parse(
961 &mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
962 )
963 .unwrap();
964 let signal3 = Signal::parse(
965 &mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap(),
966 )
967 .unwrap();
968
969 let message = Message::parse(&mut parser, &[signal1, signal2, signal3]).unwrap();
970
971 let names: Vec<&str> = message.signals().iter().map(|s| s.name()).collect();
973 assert_eq!(names, vec!["Signal1", "Signal2", "Signal3"]);
974 }
975 }
976}