1use crate::{
2 ByteOrder, Parser, Receivers,
3 error::{ParseError, ParseResult},
4};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct Signal<'a> {
8 name: &'a str,
9 start_bit: u16,
10 length: u16,
11 byte_order: ByteOrder,
12 unsigned: bool,
13 factor: f64,
14 offset: f64,
15 min: f64,
16 max: f64,
17 unit: Option<&'a str>,
18 receivers: Receivers<'a>,
19}
20
21impl<'a> Signal<'a> {
22 pub(crate) fn validate(name: &str, length: u16, min: f64, max: f64) -> ParseResult<()> {
23 if name.trim().is_empty() {
24 return Err(ParseError::Version(crate::error::lang::SIGNAL_NAME_EMPTY));
25 }
26
27 if length == 0 {
33 #[cfg(feature = "alloc")]
34 {
35 use crate::error::{messages, version_error_from_string};
36 let msg = messages::signal_length_too_small(name, length);
37 return Err(version_error_from_string(msg));
38 }
39 #[cfg(not(feature = "alloc"))]
40 {
41 return Err(ParseError::Version(
42 crate::error::lang::SIGNAL_LENGTH_TOO_SMALL,
43 ));
44 }
45 }
46 if length > 512 {
47 #[cfg(feature = "alloc")]
48 {
49 use crate::error::{messages, version_error_from_string};
50 let msg = messages::signal_length_too_large(name, length);
51 return Err(version_error_from_string(msg));
52 }
53 #[cfg(not(feature = "alloc"))]
54 {
55 return Err(ParseError::Version(
56 crate::error::lang::SIGNAL_LENGTH_TOO_LARGE,
57 ));
58 }
59 }
60
61 if min > max {
69 return Err(ParseError::Version(
71 crate::error::lang::FORMAT_INVALID_RANGE,
72 ));
73 }
74
75 Ok(())
76 }
77
78 #[allow(clippy::too_many_arguments)] #[allow(dead_code)] pub(crate) fn new(
81 name: &'a str,
82 start_bit: u16,
83 length: u16,
84 byte_order: ByteOrder,
85 unsigned: bool,
86 factor: f64,
87 offset: f64,
88 min: f64,
89 max: f64,
90 unit: Option<&'a str>,
91 receivers: Receivers<'a>,
92 ) -> Self {
93 Self {
95 name,
96 start_bit,
97 length,
98 byte_order,
99 unsigned,
100 factor,
101 offset,
102 min,
103 max,
104 unit,
105 receivers,
106 }
107 }
108
109 fn parse_position<'b>(
110 parser: &mut Parser<'b>,
111 #[cfg_attr(not(feature = "alloc"), allow(unused_variables))] signal_name: &str,
112 ) -> ParseResult<(u16, u16, ByteOrder, bool)> {
113 let start_bit = match parser.parse_u32() {
115 Ok(v) => v as u16,
116 Err(_) => {
117 #[cfg(feature = "alloc")]
118 {
119 use crate::error::{messages, version_error_from_string};
120 let msg = messages::signal_start_bit_invalid(signal_name, 0);
121 return Err(version_error_from_string(msg));
122 }
123 #[cfg(not(feature = "alloc"))]
124 {
125 return Err(ParseError::Version(
126 crate::error::lang::SIGNAL_PARSE_INVALID_START_BIT,
127 ));
128 }
129 }
130 };
131
132 if start_bit > 511 {
134 #[cfg(feature = "alloc")]
135 {
136 use crate::error::{messages, version_error_from_string};
137 let msg = messages::signal_start_bit_invalid(signal_name, start_bit);
138 return Err(version_error_from_string(msg));
139 }
140 #[cfg(not(feature = "alloc"))]
141 {
142 return Err(ParseError::Version(
143 crate::error::lang::SIGNAL_PARSE_INVALID_START_BIT,
144 ));
145 }
146 }
147
148 parser.expect(b"|").map_err(|_| ParseError::Expected("Expected pipe"))?;
150
151 let length = parser
153 .parse_u32()
154 .map_err(|_| ParseError::Version(crate::error::lang::SIGNAL_PARSE_INVALID_LENGTH))?
155 as u16;
156
157 parser.expect(b"@").map_err(|_| ParseError::Expected("Expected @"))?;
159
160 let bo_byte = if parser.expect(b"0").is_ok() {
163 b'0'
164 } else if parser.expect(b"1").is_ok() {
165 b'1'
166 } else {
167 return Err(ParseError::Expected("Expected byte order"));
168 };
169
170 let byte_order = match bo_byte {
171 b'0' => ByteOrder::BigEndian, b'1' => ByteOrder::LittleEndian, _ => return Err(ParseError::InvalidChar(bo_byte as char)),
174 };
175
176 let sign_byte = if parser.expect(b"+").is_ok() {
178 b'+'
179 } else if parser.expect(b"-").is_ok() {
180 b'-'
181 } else {
182 return Err(ParseError::Expected("Expected sign (+ or -)"));
183 };
184
185 let unsigned = match sign_byte {
186 b'+' => true,
187 b'-' => false,
188 _ => return Err(ParseError::InvalidChar(sign_byte as char)),
189 };
190
191 Ok((start_bit, length, byte_order, unsigned))
192 }
193
194 fn parse_factor_offset<'b>(parser: &mut Parser<'b>) -> ParseResult<(f64, f64)> {
195 parser
197 .expect(b"(")
198 .map_err(|_| ParseError::Expected("Expected opening parenthesis"))?;
199
200 parser.skip_newlines_and_spaces();
202
203 let pos_before = parser.pos();
207 let factor = match parser.parse_f64() {
208 Ok(val) => val,
209 Err(_) => {
210 if parser.pos() == pos_before {
212 0.0 } else {
214 return Err(ParseError::Version(
216 crate::error::lang::SIGNAL_PARSE_INVALID_FACTOR,
217 ));
218 }
219 }
220 };
221
222 parser.expect(b",").map_err(|_| ParseError::Expected("Expected comma"))?;
224
225 parser.skip_newlines_and_spaces();
227
228 let pos_before = parser.pos();
230 let offset = match parser.parse_f64() {
231 Ok(val) => val,
232 Err(_) => {
233 if parser.pos() == pos_before {
235 0.0 } else {
237 return Err(ParseError::Version(
238 crate::error::lang::SIGNAL_PARSE_INVALID_OFFSET,
239 ));
240 }
241 }
242 };
243
244 parser.skip_newlines_and_spaces();
246
247 parser
249 .expect(b")")
250 .map_err(|_| ParseError::Expected("Expected closing parenthesis"))?;
251
252 Ok((factor, offset))
253 }
254
255 fn parse_range<'b>(parser: &mut Parser<'b>) -> ParseResult<(f64, f64)> {
256 parser
258 .expect(b"[")
259 .map_err(|_| ParseError::Expected("Expected opening bracket"))?;
260
261 parser.skip_newlines_and_spaces();
263
264 let pos_before = parser.pos();
266 let min = match parser.parse_f64() {
267 Ok(val) => val,
268 Err(_) => {
269 if parser.pos() == pos_before {
271 0.0 } else {
273 return Err(ParseError::Version(
274 crate::error::lang::SIGNAL_PARSE_INVALID_MIN,
275 ));
276 }
277 }
278 };
279
280 parser.expect(b"|").map_err(|_| ParseError::Expected("Expected pipe"))?;
282
283 parser.skip_newlines_and_spaces();
285
286 let pos_before = parser.pos();
288 let max = match parser.parse_f64() {
289 Ok(val) => val,
290 Err(_) => {
291 if parser.pos() == pos_before {
293 0.0 } else {
295 return Err(ParseError::Version(
296 crate::error::lang::SIGNAL_PARSE_INVALID_MAX,
297 ));
298 }
299 }
300 };
301
302 parser.skip_newlines_and_spaces();
304
305 parser
307 .expect(b"]")
308 .map_err(|_| ParseError::Expected("Expected closing bracket"))?;
309
310 Ok((min, max))
311 }
312
313 fn parse_unit<'b: 'a>(parser: &mut Parser<'b>) -> ParseResult<Option<&'a str>> {
314 const MAX_UNIT_LENGTH: u16 = 256;
315
316 parser
318 .expect(b"\"")
319 .map_err(|_| ParseError::Expected("Expected opening quote"))?;
320
321 let unit_bytes = parser.take_until_quote(false, MAX_UNIT_LENGTH).map_err(|e| match e {
323 ParseError::MaxStrLength(_) => {
324 ParseError::Version(crate::error::lang::SIGNAL_PARSE_UNIT_TOO_LONG)
325 }
326 _ => ParseError::Expected("Expected closing quote"),
327 })?;
328
329 let unit_str = core::str::from_utf8(unit_bytes)
331 .map_err(|_| ParseError::Expected("Invalid UTF-8 in unit"))?;
332
333 let unit = if unit_str.is_empty() {
334 None
335 } else {
336 Some(unit_str)
337 };
338
339 Ok(unit)
340 }
341
342 pub(crate) fn parse<'b: 'a>(parser: &mut Parser<'b>) -> ParseResult<Self> {
343 let _ = parser.expect(crate::SG_.as_bytes()).ok(); parser.skip_newlines_and_spaces();
351
352 let name = parser
354 .parse_identifier()
355 .map_err(|_| ParseError::Version(crate::error::lang::SIGNAL_NAME_EMPTY))?;
356
357 parser.skip_newlines_and_spaces();
361
362 if parser.expect(b"m").is_ok() || parser.expect(b"M").is_ok() {
365 loop {
367 let _pos_before = parser.pos();
368 if parser.expect(b"0").is_ok()
370 || parser.expect(b"1").is_ok()
371 || parser.expect(b"2").is_ok()
372 || parser.expect(b"3").is_ok()
373 || parser.expect(b"4").is_ok()
374 || parser.expect(b"5").is_ok()
375 || parser.expect(b"6").is_ok()
376 || parser.expect(b"7").is_ok()
377 || parser.expect(b"8").is_ok()
378 || parser.expect(b"9").is_ok()
379 {
380 } else {
382 break;
384 }
385 }
386 parser.skip_newlines_and_spaces();
388 }
389
390 parser.expect(b":").map_err(|_| ParseError::Expected("Expected colon"))?;
392
393 parser.skip_newlines_and_spaces();
395
396 let (start_bit, length, byte_order, unsigned) = Self::parse_position(parser, name)?;
398
399 parser.skip_newlines_and_spaces();
401
402 let (factor, offset) = Self::parse_factor_offset(parser)?;
404
405 parser.skip_newlines_and_spaces();
407
408 let (min, max) = Self::parse_range(parser)?;
410
411 parser.skip_newlines_and_spaces();
413
414 let unit = Self::parse_unit(parser)?;
416
417 let _ = parser.skip_whitespace().ok(); let receivers = Receivers::parse(parser)?;
423
424 Self::validate(name, length, min, max)?;
426 Ok(Self {
428 name,
429 start_bit,
430 length,
431 byte_order,
432 unsigned,
433 factor,
434 offset,
435 min,
436 max,
437 unit,
438 receivers,
439 })
440 }
441
442 #[inline]
443 #[must_use = "return value should be checked"]
444 pub fn name(&self) -> &str {
445 self.name
446 }
447
448 #[inline]
449 #[must_use]
450 pub fn start_bit(&self) -> u16 {
451 self.start_bit
452 }
453
454 #[inline]
455 #[must_use]
456 pub fn length(&self) -> u16 {
457 self.length
458 }
459
460 #[inline]
461 #[must_use]
462 pub fn byte_order(&self) -> ByteOrder {
463 self.byte_order
464 }
465
466 #[inline]
467 #[must_use]
468 pub fn is_unsigned(&self) -> bool {
469 self.unsigned
470 }
471
472 #[inline]
473 #[must_use]
474 pub fn factor(&self) -> f64 {
475 self.factor
476 }
477
478 #[inline]
479 #[must_use]
480 pub fn offset(&self) -> f64 {
481 self.offset
482 }
483
484 #[inline]
485 #[must_use]
486 pub fn min(&self) -> f64 {
487 self.min
488 }
489
490 #[inline]
491 #[must_use]
492 pub fn max(&self) -> f64 {
493 self.max
494 }
495
496 #[inline]
497 #[must_use]
498 pub fn unit(&self) -> Option<&'a str> {
499 self.unit
500 }
501
502 #[inline]
503 #[must_use]
504 pub fn receivers(&self) -> &Receivers<'a> {
505 &self.receivers
506 }
507
508 #[cfg(feature = "alloc")]
509 #[must_use]
510 pub fn to_dbc_string(&self) -> alloc::string::String {
511 use alloc::{
512 format,
513 string::{String, ToString},
514 };
515 let mut result = String::with_capacity(100); result.push_str(" SG_ ");
518 result.push_str(self.name());
519 result.push_str(" : ");
520 result.push_str(&self.start_bit().to_string());
521 result.push('|');
522 result.push_str(&self.length().to_string());
523 result.push('@');
524
525 match self.byte_order() {
528 ByteOrder::BigEndian => result.push('0'), ByteOrder::LittleEndian => result.push('1'), }
531
532 if self.is_unsigned() {
534 result.push('+');
535 } else {
536 result.push('-');
537 }
538
539 result.push_str(" (");
541 result.push_str(&format!("{}", self.factor()));
542 result.push(',');
543 result.push_str(&format!("{}", self.offset()));
544 result.push(')');
545
546 result.push_str(" [");
548 result.push_str(&format!("{}", self.min()));
549 result.push('|');
550 result.push_str(&format!("{}", self.max()));
551 result.push(']');
552
553 result.push(' ');
555 if let Some(unit) = self.unit() {
556 result.push('"');
557 result.push_str(unit);
558 result.push('"');
559 } else {
560 result.push_str("\"\"");
561 }
562
563 match self.receivers() {
565 Receivers::Broadcast => {
566 result.push(' ');
567 result.push('*');
568 }
569 Receivers::Nodes(_, count) => {
570 if *count > 0 {
571 result.push(' ');
572 for (i, node) in self.receivers().iter().enumerate() {
573 if i > 0 {
574 result.push(' ');
575 }
576 result.push_str(node);
577 }
578 }
579 }
580 Receivers::None => {
581 }
583 }
584
585 result
586 }
587}
588
589impl<'a> Eq for Signal<'a> {}
591
592impl<'a> core::hash::Hash for Signal<'a> {
594 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
595 self.name.hash(state);
596 self.start_bit.hash(state);
597 self.length.hash(state);
598 self.byte_order.hash(state);
599 self.unsigned.hash(state);
600 self.factor.to_bits().hash(state);
602 self.offset.to_bits().hash(state);
603 self.min.to_bits().hash(state);
604 self.max.to_bits().hash(state);
605 self.unit.hash(state);
606 self.receivers.hash(state);
607 }
608}
609
610#[cfg(feature = "alloc")]
611impl<'a> core::fmt::Display for Signal<'a> {
612 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
613 write!(f, "{}", self.to_dbc_string())
614 }
615}
616
617#[cfg(test)]
618mod tests {
619 #![allow(clippy::float_cmp)]
620 use super::*;
621 use crate::{
622 Parser,
623 error::{ParseError, lang},
624 };
625
626 #[test]
630 fn test_parse_valid_signal() {
631 let line = r#"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm" TCM"#;
632 let mut parser = Parser::new(line.as_bytes()).unwrap();
633 let sig = Signal::parse(&mut parser).unwrap();
634 assert_eq!(sig.name(), "RPM");
635 assert_eq!(sig.start_bit(), 0);
636 assert_eq!(sig.length(), 16);
637 assert_eq!(sig.byte_order(), ByteOrder::BigEndian); assert!(sig.is_unsigned());
639 assert_eq!(sig.factor(), 0.25);
640 assert_eq!(sig.offset(), 0.);
641 assert_eq!(sig.min(), 0.);
642 assert_eq!(sig.max(), 8000.);
643 assert_eq!(sig.unit(), Some("rpm"));
644 let mut receivers_iter = sig.receivers().iter();
646 assert_eq!(receivers_iter.next(), Some("TCM"));
647 assert_eq!(receivers_iter.next(), None);
648 }
649
650 #[test]
651 fn test_parse_signal_with_empty_unit_and_broadcast() {
652 let line = r#"SG_ ABSActive : 16|1@0+ (1,0) [0|1] "" *"#;
653 let mut parser = Parser::new(line.as_bytes()).unwrap();
654 let sig = Signal::parse(&mut parser).unwrap();
655 assert_eq!(sig.name(), "ABSActive");
656 assert_eq!(sig.start_bit(), 16);
657 assert_eq!(sig.length(), 1);
658 assert_eq!(sig.byte_order(), ByteOrder::BigEndian); assert!(sig.is_unsigned());
660 assert_eq!(sig.factor(), 1.);
661 assert_eq!(sig.offset(), 0.);
662 assert_eq!(sig.min(), 0.);
663 assert_eq!(sig.max(), 1.);
664 assert_eq!(sig.unit(), None);
665 assert_eq!(sig.receivers(), &Receivers::Broadcast);
666 }
667
668 #[test]
669 fn test_parse_signal_with_negative_offset_and_min() {
670 let line = r#"SG_ Temperature : 16|8@0- (1,-40) [-40|215] "°C" TCM BCM"#;
671 let mut parser = Parser::new(line.as_bytes()).unwrap();
672 let sig = Signal::parse(&mut parser).unwrap();
673 assert_eq!(sig.name(), "Temperature");
674 assert_eq!(sig.start_bit(), 16);
675 assert_eq!(sig.length(), 8);
676 assert_eq!(sig.byte_order(), ByteOrder::BigEndian); assert!(!sig.is_unsigned());
678 assert_eq!(sig.factor(), 1.);
679 assert_eq!(sig.offset(), -40.);
680 assert_eq!(sig.min(), -40.);
681 assert_eq!(sig.max(), 215.);
682 assert_eq!(sig.unit(), Some("°C"));
683 let mut receivers_iter = sig.receivers().iter();
685 assert_eq!(receivers_iter.next(), Some("TCM"));
686 assert_eq!(receivers_iter.next(), Some("BCM"));
687 assert_eq!(receivers_iter.next(), None);
688 }
689
690 #[test]
691 fn test_parse_signal_with_percent_unit() {
692 let line = r#"SG_ ThrottlePosition : 24|8@0+ (0.392157,0) [0|100] "%" *"#;
693 let mut parser = Parser::new(line.as_bytes()).unwrap();
694 let sig = Signal::parse(&mut parser).unwrap();
695 assert_eq!(sig.name(), "ThrottlePosition");
696 assert_eq!(sig.start_bit(), 24);
697 assert_eq!(sig.length(), 8);
698 assert_eq!(sig.byte_order(), ByteOrder::BigEndian); assert!(sig.is_unsigned());
700 assert_eq!(sig.factor(), 0.392_157);
701 assert_eq!(sig.offset(), 0.);
702 assert_eq!(sig.min(), 0.);
703 assert_eq!(sig.max(), 100.);
704 assert_eq!(sig.unit(), Some("%"));
705 assert_eq!(sig.receivers(), &Receivers::Broadcast);
706 }
707
708 #[test]
709 fn test_parse_signal_missing_factors_and_limits() {
710 let line = r#"SG_ Simple : 10|4@0+ ( , ) [ | ] "" *"#;
712 let mut parser = Parser::new(line.as_bytes()).unwrap();
713 let sig = Signal::parse(&mut parser).unwrap();
714 assert_eq!(sig.name(), "Simple");
715 assert_eq!(sig.start_bit(), 10);
716 assert_eq!(sig.length(), 4);
717 assert_eq!(sig.byte_order(), ByteOrder::BigEndian); assert!(sig.is_unsigned());
719 assert_eq!(sig.factor(), 0.);
720 assert_eq!(sig.offset(), 0.);
721 assert_eq!(sig.min(), 0.);
722 assert_eq!(sig.max(), 0.);
723 assert_eq!(sig.unit(), None);
724 assert_eq!(sig.receivers(), &Receivers::Broadcast);
725 }
726
727 #[test]
728 fn test_parse_signal_missing_start_bit() {
729 let line = r#"SG_ RPM : |16@0+ (0.25,0) [0|8000] "rpm" TCM"#;
730 let mut parser = Parser::new(line.as_bytes()).unwrap();
731 let err = Signal::parse(&mut parser).unwrap_err();
732 match err {
733 ParseError::Version(msg) => {
734 assert!(
736 msg.contains(lang::SIGNAL_PARSE_INVALID_START_BIT)
737 || msg.contains("Signal 'RPM'")
738 );
739 }
740 _ => panic!("Expected ParseError"),
741 }
742 }
743
744 #[test]
745 fn test_parse_signal_invalid_range() {
746 let line = r#"SG_ Test : 0|8@0+ (1,0) [100|50] "unit" *"#;
748 let mut parser = Parser::new(line.as_bytes()).unwrap();
749 let err = Signal::parse(&mut parser).unwrap_err();
750 match err {
751 ParseError::Version(msg) => {
752 let template_text = lang::FORMAT_INVALID_RANGE.split("{}").next().unwrap();
754 assert!(msg.contains(template_text.trim_end_matches(':').trim_end()));
755 }
756 e => panic!("Expected ParseError::Version, got: {:?}", e),
757 }
758 }
759
760 #[test]
761 fn test_parse_signal_overflow() {
762 let line = r#"SG_ Test : 60|10@0+ (1,0) [0|100] "unit" *"#;
766 let mut parser = Parser::new(line.as_bytes()).unwrap();
767 let signal = Signal::parse(&mut parser).unwrap();
768 assert_eq!(signal.start_bit(), 60);
769 assert_eq!(signal.length(), 10);
770 }
772
773 #[test]
774 fn test_parse_signal_length_too_large() {
775 let line = r#"SG_ Test : 0|513@0+ (1,0) [0|100] "unit" *"#;
777 let mut parser = Parser::new(line.as_bytes()).unwrap();
778 let err = Signal::parse(&mut parser).unwrap_err();
779 match err {
780 ParseError::Version(msg) => {
781 assert!(
783 msg.contains(lang::SIGNAL_LENGTH_TOO_LARGE)
784 || msg.contains("Signal 'Test'")
785 || msg.contains("513")
786 );
787 }
788 e => panic!("Expected ParseError::Version, got: {:?}", e),
789 }
790 }
791
792 #[test]
793 fn test_parse_signal_zero_length() {
794 let line = r#"SG_ Test : 0|0@0+ (1,0) [0|100] "unit" *"#;
796 let mut parser = Parser::new(line.as_bytes()).unwrap();
797 let err = Signal::parse(&mut parser).unwrap_err();
798 match err {
799 ParseError::Version(msg) => {
800 assert!(
802 msg.contains(lang::SIGNAL_LENGTH_TOO_SMALL)
803 || msg.contains("Signal 'Test'")
804 || msg.contains("0 bits")
805 );
806 }
807 e => panic!("Expected ParseError::Version, got: {:?}", e),
808 }
809 }
810
811 #[test]
812 fn test_parse_signal_missing_length() {
813 let line = r#"SG_ RPM : 0|@0+ (0.25,0) [0|8000] "rpm" TCM"#;
814 let mut parser = Parser::new(line.as_bytes()).unwrap();
815 let err = Signal::parse(&mut parser).unwrap_err();
816 match err {
817 ParseError::Version(msg) => assert!(msg.contains(lang::SIGNAL_PARSE_INVALID_LENGTH)),
818 e => panic!("Expected ParseError::Version, got: {:?}", e),
819 }
820 }
821
822 #[cfg(any(feature = "alloc", feature = "kernel"))]
824 mod tests_with_alloc {
825 #[cfg(feature = "alloc")]
826 use super::*;
827
828 #[test]
829 #[cfg(feature = "alloc")] fn test_signal_to_dbc_string_round_trip() {
831 use alloc::vec;
832 let test_cases = vec![
834 (
835 r#"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm" *"#,
836 " SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\" *",
837 ),
838 (
839 r#"SG_ Temperature : 16|8@1- (1,-40) [-40|215] "°C" TCM BCM"#,
840 " SG_ Temperature : 16|8@1- (1,-40) [-40|215] \"°C\" TCM BCM",
841 ),
842 (
843 r#"SG_ Flag : 24|1@0+ (1,0) [0|1] "" *"#,
844 " SG_ Flag : 24|1@0+ (1,0) [0|1] \"\" *",
845 ),
846 ];
847
848 for (input_line, expected_output) in test_cases {
849 let mut parser = Parser::new(input_line.as_bytes()).unwrap();
851 let signal = Signal::parse(&mut parser).unwrap();
852
853 let dbc_string = signal.to_dbc_string();
855 assert_eq!(dbc_string, expected_output);
856
857 let mut parser2 = Parser::new(dbc_string.as_bytes()).unwrap();
859 parser2.expect(b" SG_ ").unwrap();
861 let signal2 = Signal::parse(&mut parser2).unwrap();
862
863 assert_eq!(signal.name(), signal2.name());
865 assert_eq!(signal.start_bit(), signal2.start_bit());
866 assert_eq!(signal.length(), signal2.length());
867 assert_eq!(signal.byte_order(), signal2.byte_order());
868 assert_eq!(signal.is_unsigned(), signal2.is_unsigned());
869 assert_eq!(signal.factor(), signal2.factor());
870 assert_eq!(signal.offset(), signal2.offset());
871 assert_eq!(signal.min(), signal2.min());
872 assert_eq!(signal.max(), signal2.max());
873 assert_eq!(signal.unit(), signal2.unit());
874 }
875 }
876 }
877
878 }