1use crate::{
2 Dbc, Error, ExtendedMultiplexing, MAX_EXTENDED_MULTIPLEXING, MAX_MESSAGES,
3 MAX_SIGNALS_PER_MESSAGE, Message, Nodes, Parser, Result, Signal, Version,
4 compat::Vec,
5 dbc::{Messages, Validate},
6};
7#[cfg(feature = "std")]
8use crate::{ValueDescriptions, dbc::ValueDescriptionsMap};
9#[cfg(feature = "std")]
10use std::collections::BTreeMap;
11
12impl Dbc {
13 pub fn parse(data: &str) -> Result<Self> {
32 let mut parser = Parser::new(data.as_bytes())?;
33
34 let mut messages_buffer: Vec<Message, { MAX_MESSAGES }> = Vec::new();
35
36 let mut message_count_actual = 0;
37
38 use crate::{
40 BA_, BA_DEF_, BA_DEF_DEF_, BO_, BO_TX_BU_, BS_, BU_, CM_, EV_, NS_, SG_, SG_MUL_VAL_,
41 SIG_GROUP_, SIG_VALTYPE_, VAL_, VAL_TABLE_, VERSION,
42 };
43
44 let mut version: Option<Version> = None;
45 let mut nodes: Option<Nodes> = None;
46
47 #[cfg(feature = "std")]
49 type ValueDescriptionsBufferEntry = (
50 Option<u32>,
51 std::string::String,
52 std::vec::Vec<(u64, std::string::String)>,
53 );
54 #[cfg(feature = "std")]
55 let mut value_descriptions_buffer: std::vec::Vec<ValueDescriptionsBufferEntry> =
56 std::vec::Vec::new();
57
58 let mut extended_multiplexing_buffer: Vec<
60 ExtendedMultiplexing,
61 { MAX_EXTENDED_MULTIPLEXING },
62 > = Vec::new();
63
64 loop {
65 parser.skip_newlines_and_spaces();
67 if parser.starts_with(b"//") {
68 parser.skip_to_end_of_line();
69 continue;
70 }
71
72 let keyword_result = parser.peek_next_keyword();
73 let keyword = match keyword_result {
74 Ok(kw) => kw,
75 Err(Error::UnexpectedEof) => break,
76 Err(Error::Expected(_)) => {
77 if parser.starts_with(b"//") {
78 parser.skip_to_end_of_line();
79 continue;
80 }
81 return Err(keyword_result.unwrap_err());
82 }
83 Err(e) => return Err(e),
84 };
85
86 let pos_at_keyword = parser.pos();
88
89 match keyword {
90 NS_ => {
91 parser
93 .expect(crate::NS_.as_bytes())
94 .map_err(|_| Error::Expected("Failed to consume NS_ keyword"))?;
95 parser.skip_newlines_and_spaces();
96 let _ = parser.expect(b":").ok();
97 loop {
98 parser.skip_newlines_and_spaces();
99 if parser.is_empty() {
100 break;
101 }
102 if parser.starts_with(b" ") || parser.starts_with(b"\t") {
103 parser.skip_to_end_of_line();
104 continue;
105 }
106 if parser.starts_with(b"//") {
107 parser.skip_to_end_of_line();
108 continue;
109 }
110 if parser.starts_with(BS_.as_bytes())
111 || parser.starts_with(BU_.as_bytes())
112 || parser.starts_with(BO_.as_bytes())
113 || parser.starts_with(SG_.as_bytes())
114 || parser.starts_with(VERSION.as_bytes())
115 {
116 break;
117 }
118 parser.skip_to_end_of_line();
119 }
120 continue;
121 }
122 CM_ | BS_ | VAL_TABLE_ | BA_DEF_ | BA_DEF_DEF_ | BA_ | SIG_GROUP_
123 | SIG_VALTYPE_ | EV_ | BO_TX_BU_ => {
124 let _ = parser.expect(keyword.as_bytes()).ok();
126 parser.skip_to_end_of_line();
127 continue;
128 }
129 SG_MUL_VAL_ => {
130 parser
132 .expect(SG_MUL_VAL_.as_bytes())
133 .map_err(|_| Error::Expected("Failed to consume SG_MUL_VAL_ keyword"))?;
134
135 if let Some(ext_mux) = ExtendedMultiplexing::parse(&mut parser) {
137 if extended_multiplexing_buffer.push(ext_mux).is_err() {
138 return Err(Error::Validation(Error::EXTENDED_MULTIPLEXING_TOO_MANY));
140 }
141 } else {
142 parser.skip_to_end_of_line();
144 }
145 continue;
146 }
147 VAL_ => {
148 #[cfg(feature = "std")]
149 {
150 let _ = parser.expect(crate::VAL_.as_bytes()).ok();
152 parser.skip_newlines_and_spaces();
156 let message_id = match parser.parse_i64() {
157 Ok(id) => {
158 if id == -1 {
160 None
161 } else if id >= 0 && id <= u32::MAX as i64 {
162 Some(id as u32)
163 } else {
164 parser.skip_to_end_of_line();
165 continue;
166 }
167 }
168 Err(_) => {
169 parser.skip_to_end_of_line();
170 continue;
171 }
172 };
173 parser.skip_newlines_and_spaces();
174 let signal_name = match parser.parse_identifier() {
175 Ok(name) => name.to_string(),
176 Err(_) => {
177 parser.skip_to_end_of_line();
178 continue;
179 }
180 };
181 let mut entries: std::vec::Vec<(u64, std::string::String)> =
183 std::vec::Vec::new();
184 loop {
185 parser.skip_newlines_and_spaces();
186 if parser.starts_with(b";") {
188 parser.expect(b";").ok();
189 break;
190 }
191 let value = match parser.parse_i64() {
195 Ok(v) => {
196 if v == -1 { 0xFFFF_FFFFu64 } else { v as u64 }
198 }
199 Err(_) => {
200 parser.skip_to_end_of_line();
201 break;
202 }
203 };
204 parser.skip_newlines_and_spaces();
205 if parser.expect(b"\"").is_err() {
207 parser.skip_to_end_of_line();
208 break;
209 }
210 let description_bytes = match parser.take_until_quote(false, 1024) {
211 Ok(bytes) => bytes,
212 Err(_) => {
213 parser.skip_to_end_of_line();
214 break;
215 }
216 };
217 let description = match core::str::from_utf8(description_bytes) {
218 Ok(s) => s.to_string(),
219 Err(_) => {
220 parser.skip_to_end_of_line();
221 break;
222 }
223 };
224 entries.push((value, description));
225 }
226 if !entries.is_empty() {
227 value_descriptions_buffer.push((message_id, signal_name, entries));
228 }
229 }
230 #[cfg(not(feature = "std"))]
231 {
232 let _ = parser.expect(crate::VAL_.as_bytes()).ok();
234 parser.skip_to_end_of_line();
235 }
236 continue;
237 }
238 VERSION => {
239 version = Some(Version::parse(&mut parser)?);
241 continue;
242 }
243 BU_ => {
244 parser.skip_to_end_of_line();
246 let bu_input = &data.as_bytes()[pos_at_keyword..parser.pos()];
247 let mut bu_parser = Parser::new(bu_input)?;
248 nodes = Some(Nodes::parse(&mut bu_parser)?);
249 continue;
250 }
251 BO_ => {
252 if message_count_actual >= MAX_MESSAGES {
254 return Err(Error::Nodes(Error::NODES_TOO_MANY));
255 }
256
257 let message_start_pos = pos_at_keyword;
259
260 let header_line_end = {
263 let mut temp_parser = Parser::new(&data.as_bytes()[pos_at_keyword..])?;
265 temp_parser.expect(crate::BO_.as_bytes()).ok();
267 temp_parser.skip_whitespace().ok();
268 temp_parser.parse_u32().ok(); temp_parser.skip_whitespace().ok();
270 temp_parser.parse_identifier().ok(); temp_parser.skip_whitespace().ok();
272 temp_parser.expect(b":").ok(); temp_parser.skip_whitespace().ok();
274 temp_parser.parse_u8().ok(); temp_parser.skip_whitespace().ok();
276 temp_parser.parse_identifier().ok(); pos_at_keyword + temp_parser.pos()
278 };
279
280 parser.skip_to_end_of_line(); let mut signals_array: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }> = Vec::new();
284
285 loop {
287 parser.skip_newlines_and_spaces();
288
289 let keyword_result = parser.peek_next_keyword();
292 let keyword = match keyword_result {
293 Ok(kw) => kw,
294 Err(Error::UnexpectedEof) => break,
295 Err(_) => break, };
297
298 if keyword != SG_ {
300 break; }
302
303 if signals_array.len() >= MAX_SIGNALS_PER_MESSAGE {
305 return Err(Error::Message(Error::MESSAGE_TOO_MANY_SIGNALS));
306 }
307
308 match Signal::parse(&mut parser) {
310 Ok(signal) => {
311 signals_array.push(signal).map_err(|_| {
312 Error::Receivers(Error::SIGNAL_RECEIVERS_TOO_MANY)
313 })?;
314 if parser.at_newline() {
317 parser.skip_to_end_of_line();
318 }
319 }
320 Err(_) => {
321 parser.skip_to_end_of_line();
323 break;
324 }
325 }
326 }
327
328 let message_input = &data.as_bytes()[message_start_pos..header_line_end];
332 let mut message_parser = Parser::new(message_input)?;
333
334 let message = Message::parse(&mut message_parser, signals_array.as_slice())?;
336
337 messages_buffer
338 .push(message)
339 .map_err(|_| Error::Message(Error::NODES_TOO_MANY))?;
340 message_count_actual += 1;
341 continue;
342 }
343 SG_ => {
344 parser.skip_to_end_of_line();
346 continue;
347 }
348 _ => {
349 parser.skip_to_end_of_line();
350 continue;
351 }
352 }
353 }
354
355 let nodes = nodes.unwrap_or_default();
357
358 let version = version.or_else(|| {
360 static EMPTY_VERSION: &[u8] = b"VERSION \"\"";
361 let mut parser = Parser::new(EMPTY_VERSION).ok()?;
362 Version::parse(&mut parser).ok()
363 });
364
365 #[cfg(feature = "std")]
367 let value_descriptions_map = {
368 let mut map: BTreeMap<(Option<u32>, std::string::String), ValueDescriptions> =
369 BTreeMap::new();
370 for (message_id, signal_name, entries) in value_descriptions_buffer {
371 let key = (message_id, signal_name);
372 let value_descriptions = ValueDescriptions::from_slice(&entries);
373 map.insert(key, value_descriptions);
374 }
375 ValueDescriptionsMap::from_map(map)
376 };
377
378 let messages_slice: &[Message] = messages_buffer.as_slice();
380
381 #[cfg(feature = "std")]
383 Validate::validate(&nodes, messages_slice, Some(&value_descriptions_map)).map_err(|e| {
384 crate::error::map_val_error(e, Error::Message, || {
385 Error::Message(Error::MESSAGE_ERROR_PREFIX)
386 })
387 })?;
388 #[cfg(not(feature = "std"))]
389 Validate::validate(&nodes, messages_slice).map_err(|e| {
390 crate::error::map_val_error(e, Error::Message, || {
391 Error::Message(Error::MESSAGE_ERROR_PREFIX)
392 })
393 })?;
394
395 let messages = Messages::new(messages_slice)?;
397 #[cfg(feature = "std")]
398 let dbc = Dbc::new(
399 version,
400 nodes,
401 messages,
402 value_descriptions_map,
403 extended_multiplexing_buffer,
404 );
405 #[cfg(not(feature = "std"))]
406 let dbc = Dbc::new(version, nodes, messages, extended_multiplexing_buffer);
407 Ok(dbc)
408 }
409
410 pub fn parse_bytes(data: &[u8]) -> Result<Self> {
423 let content =
424 core::str::from_utf8(data).map_err(|_e| Error::Expected(Error::INVALID_UTF8))?;
425 Dbc::parse(content)
426 }
427}
428
429#[cfg(test)]
430mod tests {
431 use crate::Dbc;
432
433 #[test]
434 fn test_parse_basic() {
435 let dbc_content = r#"VERSION "1.0"
436
437BU_: ECM
438
439BO_ 256 Engine : 8 ECM
440 SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm"
441"#;
442 let dbc = Dbc::parse(dbc_content).unwrap();
443 assert_eq!(dbc.version().map(|v| v.as_str()), Some("1.0"));
444 assert!(dbc.nodes().contains("ECM"));
445 assert_eq!(dbc.messages().len(), 1);
446 }
447
448 #[test]
449 fn test_parse_bytes() {
450 let dbc_bytes = b"VERSION \"1.0\"\n\nBU_: ECM\n\nBO_ 256 Engine : 8 ECM";
451 let dbc = Dbc::parse_bytes(dbc_bytes).unwrap();
452 assert_eq!(dbc.version().map(|v| v.as_str()), Some("1.0"));
453 assert!(dbc.nodes().contains("ECM"));
454 assert_eq!(dbc.messages().len(), 1);
455 }
456
457 #[test]
458 fn test_parse_empty_nodes() {
459 let dbc_content = r#"VERSION "1.0"
460
461BU_:
462
463BO_ 256 Engine : 8 ECM
464"#;
465 let dbc = Dbc::parse(dbc_content).unwrap();
466 assert!(dbc.nodes().is_empty());
467 }
468
469 #[test]
470 fn test_parse_no_version() {
471 let dbc_content = r#"BU_: ECM
472
473BO_ 256 Engine : 8 ECM
474"#;
475 let dbc = Dbc::parse(dbc_content).unwrap();
476 assert!(dbc.version().is_some());
478 }
479
480 #[test]
481 fn parses_real_dbc() {
482 let data = r#"VERSION "1.0"
483
484BU_: ECM TCM
485
486BO_ 256 Engine : 8 ECM
487 SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm"
488 SG_ Temp : 16|8@0- (1,-40) [-40|215] "°C"
489
490BO_ 512 Brake : 4 TCM
491 SG_ Pressure : 0|16@1+ (0.1,0) [0|1000] "bar""#;
492
493 let dbc = Dbc::parse(data).unwrap();
494 assert_eq!(dbc.messages().len(), 2);
495 let mut messages_iter = dbc.messages().iter();
496 let msg0 = messages_iter.next().unwrap();
497 assert_eq!(msg0.signals().len(), 2);
498 let mut signals_iter = msg0.signals().iter();
499 assert_eq!(signals_iter.next().unwrap().name(), "RPM");
500 assert_eq!(signals_iter.next().unwrap().name(), "Temp");
501 let msg1 = messages_iter.next().unwrap();
502 assert_eq!(msg1.signals().len(), 1);
503 assert_eq!(msg1.signals().iter().next().unwrap().name(), "Pressure");
504 }
505
506 #[test]
507 fn test_parse_duplicate_message_id() {
508 use crate::Error;
509 let data = r#"VERSION "1.0"
511
512BU_: ECM
513
514BO_ 256 EngineData1 : 8 ECM
515 SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm"
516
517BO_ 256 EngineData2 : 8 ECM
518 SG_ Temp : 16|8@0- (1,-40) [-40|215] "°C"
519"#;
520
521 let result = Dbc::parse(data);
522 assert!(result.is_err());
523 match result.unwrap_err() {
524 Error::Message(msg) => {
525 assert!(msg.contains(Error::DUPLICATE_MESSAGE_ID));
526 }
527 _ => panic!("Expected Error::Message"),
528 }
529 }
530
531 #[test]
532 fn test_parse_sender_not_in_nodes() {
533 use crate::Error;
534 let data = r#"VERSION "1.0"
536
537BU_: ECM
538
539BO_ 256 EngineData : 8 TCM
540 SG_ RPM : 0|16@0+ (0.25,0) [0|8000] "rpm"
541"#;
542
543 let result = Dbc::parse(data);
544 assert!(result.is_err());
545 match result.unwrap_err() {
546 Error::Message(msg) => {
547 assert!(msg.contains(Error::SENDER_NOT_IN_NODES));
548 }
549 _ => panic!("Expected Error::Message"),
550 }
551 }
552
553 #[test]
554 fn test_parse_empty_file() {
555 use crate::Error;
556 let result = Dbc::parse("");
558 assert!(result.is_err());
559 match result.unwrap_err() {
560 Error::UnexpectedEof => {
561 }
563 _ => panic!("Expected Error::UnexpectedEof"),
564 }
565 }
566
567 #[test]
568 fn test_parse_bytes_invalid_utf8() {
569 use crate::Error;
570 let invalid_bytes = &[0xFF, 0xFE, 0xFD];
572 let result = Dbc::parse_bytes(invalid_bytes);
573 assert!(result.is_err());
574 match result.unwrap_err() {
575 Error::Expected(msg) => {
576 assert_eq!(msg, Error::INVALID_UTF8);
577 }
578 _ => panic!("Expected Error::Expected with INVALID_UTF8"),
579 }
580 }
581
582 #[test]
583 fn test_parse_without_version_with_comment() {
584 let data = r#"// This is a comment
586BU_: ECM
587
588BO_ 256 Engine : 8 ECM
589 SG_ RPM : 0|16@1+ (0.25,0) [0|8000] "rpm"
590"#;
591 let dbc = Dbc::parse(data).unwrap();
592 assert_eq!(dbc.version().map(|v| v.as_str()), Some(""));
593 }
594
595 #[test]
596 fn test_parse_with_strict_boundary_check() {
597 let data = r#"VERSION "1.0"
599
600BU_: ECM
601
602BO_ 256 Test : 8 ECM
603 SG_ CHECKSUM : 63|8@1+ (1,0) [0|255] ""
604"#;
605
606 let result = Dbc::parse(data);
608 assert!(result.is_err());
609 }
610
611 #[cfg(feature = "std")]
612 #[test]
613 fn test_parse_val_value_descriptions() {
614 let data = r#"VERSION ""
615
616NS_ :
617
618BS_:
619
620BU_: Node1 Node2
621
622BO_ 100 Message1 : 8 Node1
623 SG_ Signal : 32|8@1- (1,0) [-1|4] "Gear" Node2
624
625VAL_ 100 Signal -1 "Reverse" 0 "Neutral" 1 "First" 2 "Second" 3 "Third" 4 "Fourth" ;
626"#;
627
628 let dbc = match Dbc::parse(data) {
629 Ok(dbc) => dbc,
630 Err(e) => panic!("Failed to parse DBC: {:?}", e),
631 };
632
633 assert_eq!(dbc.messages().len(), 1);
635 let message = dbc.messages().iter().find(|m| m.id() == 100).unwrap();
636 assert_eq!(message.name(), "Message1");
637 assert_eq!(message.sender(), "Node1");
638
639 let value_descriptions = dbc
641 .value_descriptions_for_signal(100, "Signal")
642 .expect("Value descriptions should exist");
643 assert_eq!(value_descriptions.get(0xFFFFFFFF), Some("Reverse")); assert_eq!(value_descriptions.get(0), Some("Neutral"));
645 assert_eq!(value_descriptions.get(1), Some("First"));
646 assert_eq!(value_descriptions.get(2), Some("Second"));
647 assert_eq!(value_descriptions.get(3), Some("Third"));
648 assert_eq!(value_descriptions.get(4), Some("Fourth"));
649 }
650
651 #[cfg(feature = "std")]
652 #[test]
653 fn test_parse_val_global_value_descriptions() {
654 let data = r#"VERSION "1.0"
656
657NS_ :
658
659 VAL_
660
661BS_:
662
663BU_: ECU DASH
664
665BO_ 256 EngineData: 8 ECU
666 SG_ EngineRPM : 0|16@1+ (0.125,0) [0|8000] "rpm" Vector__XXX
667 SG_ DI_gear : 24|3@1+ (1,0) [0|7] "" Vector__XXX
668
669BO_ 512 DashboardDisplay: 8 DASH
670 SG_ DI_gear : 0|3@1+ (1,0) [0|7] "" Vector__XXX
671 SG_ SpeedDisplay : 8|16@1+ (0.01,0) [0|300] "km/h" Vector__XXX
672
673VAL_ -1 DI_gear 0 "INVALID" 1 "P" 2 "R" 3 "N" 4 "D" 5 "S" 6 "L" 7 "SNA" ;
674"#;
675
676 let dbc = match Dbc::parse(data) {
677 Ok(dbc) => dbc,
678 Err(e) => panic!("Failed to parse DBC: {:?}", e),
679 };
680
681 assert_eq!(dbc.messages().len(), 2);
683
684 let engine_msg = dbc.messages().iter().find(|m| m.id() == 256).unwrap();
686 assert_eq!(engine_msg.name(), "EngineData");
687 assert_eq!(engine_msg.sender(), "ECU");
688 let di_gear_signal1 = engine_msg.signals().find("DI_gear").unwrap();
689 assert_eq!(di_gear_signal1.name(), "DI_gear");
690 assert_eq!(di_gear_signal1.start_bit(), 24);
691
692 let dash_msg = dbc.messages().iter().find(|m| m.id() == 512).unwrap();
694 assert_eq!(dash_msg.name(), "DashboardDisplay");
695 assert_eq!(dash_msg.sender(), "DASH");
696 let di_gear_signal2 = dash_msg.signals().find("DI_gear").unwrap();
697 assert_eq!(di_gear_signal2.name(), "DI_gear");
698 assert_eq!(di_gear_signal2.start_bit(), 0);
699
700 let value_descriptions1 = dbc
702 .value_descriptions_for_signal(256, "DI_gear")
703 .expect("Global value descriptions should exist for DI_gear in message 256");
704
705 assert_eq!(value_descriptions1.get(0), Some("INVALID"));
706 assert_eq!(value_descriptions1.get(1), Some("P"));
707 assert_eq!(value_descriptions1.get(2), Some("R"));
708 assert_eq!(value_descriptions1.get(3), Some("N"));
709 assert_eq!(value_descriptions1.get(4), Some("D"));
710 assert_eq!(value_descriptions1.get(5), Some("S"));
711 assert_eq!(value_descriptions1.get(6), Some("L"));
712 assert_eq!(value_descriptions1.get(7), Some("SNA"));
713
714 let value_descriptions2 = dbc
716 .value_descriptions_for_signal(512, "DI_gear")
717 .expect("Global value descriptions should exist for DI_gear in message 512");
718
719 assert_eq!(value_descriptions2.get(0), Some("INVALID"));
721 assert_eq!(value_descriptions2.get(1), Some("P"));
722 assert_eq!(value_descriptions2.get(2), Some("R"));
723 assert_eq!(value_descriptions2.get(3), Some("N"));
724 assert_eq!(value_descriptions2.get(4), Some("D"));
725 assert_eq!(value_descriptions2.get(5), Some("S"));
726 assert_eq!(value_descriptions2.get(6), Some("L"));
727 assert_eq!(value_descriptions2.get(7), Some("SNA"));
728
729 assert_eq!(value_descriptions1.len(), value_descriptions2.len());
732 assert_eq!(value_descriptions1.len(), 8);
733
734 assert_eq!(dbc.value_descriptions_for_signal(256, "EngineRPM"), None);
736 assert_eq!(dbc.value_descriptions_for_signal(512, "SpeedDisplay"), None);
737 }
738}