1#![doc = include_str!("../README.md")]
2
3use std::borrow::Cow;
4use std::convert::TryFrom;
5
6use derive_getters::Getters;
7use serde::{Deserialize, Serialize};
8
9pub mod parser;
10
11#[cfg(feature = "encodings")]
13pub use encoding_rs as encodings;
14
15#[cfg(feature = "encodings")]
17pub fn decode_cp1252(bytes: &[u8]) -> Option<Cow<'_, str>> {
18 let (cow, _, had_errors) = encodings::WINDOWS_1252.decode(bytes);
19 if had_errors {
20 None
21 } else {
22 Some(cow)
23 }
24}
25
26#[cfg(test)]
27mod tests {
28
29 use super::*;
30
31 const SAMPLE_DBC: &str = r#"
32VERSION "0.1"
33NS_ :
34 NS_DESC_
35 CM_
36 BA_DEF_
37 BA_
38 VAL_
39 CAT_DEF_
40 CAT_
41 FILTER
42 BA_DEF_DEF_
43 EV_DATA_
44 ENVVAR_DATA_
45 SGTYPE_
46 SGTYPE_VAL_
47 BA_DEF_SGTYPE_
48 BA_SGTYPE_
49 SIG_TYPE_REF_
50 VAL_TABLE_
51 SIG_GROUP_
52 SIG_VALTYPE_
53 SIGTYPE_VALTYPE_
54 BO_TX_BU_
55 BA_DEF_REL_
56 BA_REL_
57 BA_DEF_DEF_REL_
58 BU_SG_REL_
59 BU_EV_REL_
60 BU_BO_REL_
61 SG_MUL_VAL_
62BS_:
63BU_: PC
64BO_ 2000 WebData_2000: 4 Vector__XXX
65 SG_ Signal_8 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
66 SG_ Signal_7 : 16|8@1+ (1,0) [0|255] "" Vector__XXX
67 SG_ Signal_6 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
68 SG_ Signal_5 : 0|8@1+ (1,0) [0|255] "" Vector__XXX
69BO_ 1840 WebData_1840: 4 PC
70 SG_ Signal_4 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
71 SG_ Signal_3 : 16|8@1+ (1,0) [0|255] "" Vector__XXX
72 SG_ Signal_2 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
73 SG_ Signal_1 : 0|8@1+ (1,0) [0|0] "" Vector__XXX
74
75BO_ 3040 WebData_3040: 8 Vector__XXX
76 SG_ Signal_6 m2 : 0|4@1+ (1,0) [0|15] "" Vector__XXX
77 SG_ Signal_5 m3 : 16|8@1+ (1,0) [0|255] "kmh" Vector__XXX
78 SG_ Signal_4 m3 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
79 SG_ Signal_3 m3 : 0|4@1+ (1,0) [0|3] "" Vector__XXX
80 SG_ Signal_2 m1 : 3|12@0+ (1,0) [0|4095] "Byte" Vector__XXX
81 SG_ Signal_1 m0 : 0|4@1+ (1,0) [0|7] "Byte" Vector__XXX
82 SG_ Switch M : 4|4@1+ (1,0) [0|3] "" Vector__XXX
83
84EV_ Environment1: 0 [0|220] "" 0 6 DUMMY_NODE_VECTOR0 DUMMY_NODE_VECTOR2;
85EV_ Environment2: 0 [0|177] "" 0 7 DUMMY_NODE_VECTOR1 DUMMY_NODE_VECTOR2;
86ENVVAR_DATA_ SomeEnvVarData: 399;
87
88CM_ BO_ 1840 "Some Message comment";
89CM_ SG_ 1840 Signal_4 "asaklfjlsdfjlsdfgls
90HH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv";
91CM_ SG_ 5 TestSigLittleUnsigned1 "asaklfjlsdfjlsdfgls
92=0943503450KFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv";
93
94BA_DEF_DEF_ "BusType" "AS";
95
96BA_ "Attr" BO_ 4358435 283;
97BA_ "Attr" BO_ 56949545 344;
98
99VAL_ 2000 Signal_3 255 "NOP";
100
101SIG_VALTYPE_ 2000 Signal_8 : 1;
102"#;
103
104 #[test]
105 fn dbc_definition_test() {
106 match Dbc::try_from(SAMPLE_DBC) {
107 Ok(dbc_content) => println!("DBC Content{dbc_content:#?}"),
108 Err(e) => {
109 match e {
110 Error::Nom(nom::Err::Incomplete(needed)) => {
111 eprintln!("Error incomplete input, needed: {needed:?}");
112 }
113 Error::Nom(nom::Err::Error(error)) => {
114 eprintln!("Nom Error: {error:?}");
115 }
116 Error::Nom(nom::Err::Failure(ctx)) => eprintln!("Failure {ctx:?}"),
117 Error::Incomplete(dbc, remaining) => eprintln!(
118 "Not all data in buffer was read {dbc:#?}, remaining unparsed: {remaining}",
119 ),
120 Error::MultipleMultiplexors => eprintln!("Multiple multiplexors defined"),
121 }
122 panic!("Failed to read DBC");
123 }
124 }
125 }
126
127 #[test]
128 fn lookup_signal_comment() {
129 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
130 let comment = dbc_content
131 .signal_comment(MessageId::Standard(1840), "Signal_4")
132 .expect("Signal comment missing");
133 assert_eq!(
134 "asaklfjlsdfjlsdfgls\nHH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv",
135 comment
136 );
137 }
138
139 #[test]
140 fn lookup_signal_comment_none_when_missing() {
141 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
142 let comment = dbc_content.signal_comment(MessageId::Standard(1840), "Signal_2");
143 assert_eq!(None, comment);
144 }
145
146 #[test]
147 fn lookup_message_comment() {
148 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
149 let comment = dbc_content
150 .message_comment(MessageId::Standard(1840))
151 .expect("Message comment missing");
152 assert_eq!("Some Message comment", comment);
153 }
154
155 #[test]
156 fn lookup_message_comment_none_when_missing() {
157 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
158 let comment = dbc_content.message_comment(MessageId::Standard(2000));
159 assert_eq!(None, comment);
160 }
161
162 #[test]
163 fn lookup_value_descriptions_for_signal() {
164 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
165 let val_descriptions = dbc_content
166 .value_descriptions_for_signal(MessageId::Standard(2000), "Signal_3")
167 .expect("Message comment missing");
168
169 let exp = vec![ValDescription {
170 id: 255.0,
171 description: "NOP".to_string(),
172 }];
173 assert_eq!(exp, val_descriptions);
174 }
175
176 #[test]
177 fn lookup_value_descriptions_for_signal_none_when_missing() {
178 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
179 let val_descriptions =
180 dbc_content.value_descriptions_for_signal(MessageId::Standard(2000), "Signal_2");
181 assert_eq!(None, val_descriptions);
182 }
183
184 #[test]
185 fn lookup_extended_value_type_for_signal() {
186 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
187 let extended_value_type =
188 dbc_content.extended_value_type_for_signal(MessageId::Standard(2000), "Signal_8");
189 assert_eq!(
190 extended_value_type,
191 Some(&SignalExtendedValueType::IEEEfloat32Bit)
192 );
193 }
194
195 #[test]
196 fn lookup_extended_value_type_for_signal_none_when_missing() {
197 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
198 let extended_value_type =
199 dbc_content.extended_value_type_for_signal(MessageId::Standard(2000), "Signal_1");
200 assert_eq!(extended_value_type, None);
201 }
202
203 #[test]
204 fn lookup_signal_by_name() {
205 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
206 let signal = dbc_content.signal_by_name(MessageId::Standard(2000), "Signal_8");
207 assert!(signal.is_some());
208 }
209
210 #[test]
211 fn lookup_signal_by_name_none_when_missing() {
212 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
213 let signal = dbc_content.signal_by_name(MessageId::Standard(2000), "Signal_25");
214 assert_eq!(signal, None);
215 }
216
217 #[test]
218 fn lookup_multiplex_indicator_switch() {
219 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
220 let multiplexor_switch = dbc_content.message_multiplexor_switch(MessageId::Standard(3040));
221 assert!(multiplexor_switch.is_ok());
222 assert!(multiplexor_switch.as_ref().unwrap().is_some());
223 assert_eq!(multiplexor_switch.unwrap().unwrap().name(), "Switch");
224 }
225
226 #[test]
227 fn lookup_multiplex_indicator_switch_none_when_missing() {
228 let dbc_content = Dbc::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
229 let multiplexor_switch = dbc_content.message_multiplexor_switch(MessageId::Standard(1840));
230 assert!(multiplexor_switch.unwrap().is_none());
231 }
232
233 #[test]
234 fn extended_message_id_raw() {
235 let message_id = MessageId::Extended(2);
236 assert_eq!(message_id.raw(), 2 | 1 << 31);
237 let message_id = MessageId::Extended(2 ^ 29);
238 assert_eq!(message_id.raw(), 2 ^ 29 | 1 << 31);
239 }
240
241 #[test]
242 fn standard_message_id_raw() {
243 let message_id = MessageId::Standard(2);
244 assert_eq!(message_id.raw(), 2);
245 }
246}
247
248#[allow(clippy::large_enum_variant)]
250#[derive(Debug)]
251pub enum Error<'a> {
252 Incomplete(Dbc, &'a str),
255 Nom(nom::Err<nom::error::Error<&'a str>>),
257 MultipleMultiplexors,
259}
260
261#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
263pub struct Baudrate(u64);
264
265#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
269pub struct Signal {
270 name: String,
271 multiplexer_indicator: MultiplexIndicator,
272 pub start_bit: u64,
273 pub size: u64,
274 byte_order: ByteOrder,
275 value_type: ValueType,
276 pub factor: f64,
277 pub offset: f64,
278 pub min: f64,
279 pub max: f64,
280 unit: String,
281 receivers: Vec<String>,
282}
283
284#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
287pub enum MessageId {
288 Standard(u16),
289 Extended(u32),
292}
293
294impl MessageId {
295 pub fn raw(self) -> u32 {
297 match self {
298 MessageId::Standard(id) => u32::from(id),
299 MessageId::Extended(id) => id | 1 << 31,
300 }
301 }
302}
303
304#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
305pub enum Transmitter {
306 NodeName(String),
308 VectorXXX,
310}
311
312#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
313pub struct MessageTransmitter {
314 message_id: MessageId,
315 transmitter: Vec<Transmitter>,
316}
317
318#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
320pub struct Version(pub String);
321
322#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
323pub struct Symbol(pub String);
324
325#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
326pub enum MultiplexIndicator {
327 Multiplexor,
329 MultiplexedSignal(u64),
331 MultiplexorAndMultiplexedSignal(u64),
333 Plain,
335}
336
337#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
338pub enum ByteOrder {
339 LittleEndian,
340 BigEndian,
341}
342
343#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
344pub enum ValueType {
345 Signed,
346 Unsigned,
347}
348
349#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
350pub enum EnvType {
351 Float,
352 U64,
353 Data,
354}
355
356#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
357pub struct SignalType {
358 name: String,
359 signal_size: u64,
360 byte_order: ByteOrder,
361 value_type: ValueType,
362 factor: f64,
363 offset: f64,
364 min: f64,
365 max: f64,
366 unit: String,
367 default_value: f64,
368 value_table: String,
369}
370
371#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
372pub enum AccessType {
373 DummyNodeVector0,
374 DummyNodeVector1,
375 DummyNodeVector2,
376 DummyNodeVector3,
377}
378
379#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
380pub enum AccessNode {
381 VectorXXX,
382 Name(String),
383}
384
385#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
387pub enum SignalAttributeValue {
388 Text(String),
389 Int(i64),
390}
391
392#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
393pub enum AttributeValuedForObjectType {
394 Raw(AttributeValue),
395 NetworkNode(String, AttributeValue),
396 MessageDefinition(MessageId, Option<AttributeValue>),
397 Signal(MessageId, String, AttributeValue),
398 EnvVariable(String, AttributeValue),
399}
400
401#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
403pub enum AttributeValueType {
404 Int(i64, i64),
405 Hex(i64, i64),
406 Float(f64, f64),
407 String,
408 Enum(Vec<String>),
409}
410
411#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
412pub struct ValDescription {
413 id: f64,
414 description: String,
415}
416
417#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
419pub struct AttrDefault {
420 name: String,
421 value: AttributeValue,
422}
423
424#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
425pub enum AttributeValue {
426 U64(u64),
427 I64(i64),
428 Double(f64),
429 String(String),
430}
431
432#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
434pub struct ValueTable {
435 name: String,
436 descriptions: Vec<ValDescription>,
437}
438
439#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
440pub struct ExtendedMultiplexMapping {
441 min_value: u64,
442 max_value: u64,
443}
444
445#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
447pub struct ExtendedMultiplex {
448 message_id: MessageId,
449 signal_name: String,
450 multiplexor_signal_name: String,
451 mappings: Vec<ExtendedMultiplexMapping>,
452}
453
454#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
456pub enum Comment {
457 Node {
458 name: String,
459 comment: String,
460 },
461 Message {
462 id: MessageId,
463 comment: String,
464 },
465 Signal {
466 message_id: MessageId,
467 name: String,
468 comment: String,
469 },
470 EnvVar {
471 name: String,
472 comment: String,
473 },
474 Plain {
475 comment: String,
476 },
477}
478
479#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
481pub struct Message {
482 id: MessageId,
485 name: String,
486 size: u64,
487 transmitter: Transmitter,
488 signals: Vec<Signal>,
489}
490
491#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
492pub struct EnvironmentVariable {
493 name: String,
494 typ: EnvType,
495 min: i64,
496 max: i64,
497 unit: String,
498 initial_value: f64,
499 ev_id: i64,
500 access_type: AccessType,
501 access_nodes: Vec<AccessNode>,
502}
503
504#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
505pub struct EnvironmentVariableData {
506 env_var_name: String,
507 data_size: u64,
508}
509
510#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
512pub struct Node(pub Vec<String>);
513
514#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
515pub struct AttributeDefault {
516 name: String,
517 value: AttributeValue,
518}
519
520#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
521pub struct AttributeValueForObject {
522 name: String,
523 value: AttributeValuedForObjectType,
524}
525
526#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
527pub enum AttributeDefinition {
528 Message(String),
530 Node(String),
532 Signal(String),
534 EnvironmentVariable(String),
535 Plain(String),
537}
538
539#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
541pub enum ValueDescription {
542 Signal {
543 message_id: MessageId,
544 name: String,
545 value_descriptions: Vec<ValDescription>,
546 },
547 EnvironmentVariable {
548 name: String,
549 value_descriptions: Vec<ValDescription>,
550 },
551}
552
553#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
554pub struct SignalTypeRef {
555 message_id: MessageId,
556 signal_name: String,
557 signal_type_name: String,
558}
559
560#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
562pub struct SignalGroups {
563 message_id: MessageId,
564 name: String,
565 repetitions: u64,
566 signal_names: Vec<String>,
567}
568
569#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
570pub enum SignalExtendedValueType {
571 SignedOrUnsignedInteger,
572 IEEEfloat32Bit,
573 IEEEdouble64bit,
574}
575
576#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
577pub struct SignalExtendedValueTypeList {
578 message_id: MessageId,
579 signal_name: String,
580 signal_extended_value_type: SignalExtendedValueType,
581}
582
583#[derive(Clone, Debug, PartialEq, Getters, Serialize, Deserialize)]
584pub struct Dbc {
585 version: Version,
587 new_symbols: Vec<Symbol>,
588 bit_timing: Option<Vec<Baudrate>>,
590 nodes: Vec<Node>,
592 value_tables: Vec<ValueTable>,
594 messages: Vec<Message>,
596 message_transmitters: Vec<MessageTransmitter>,
597 environment_variables: Vec<EnvironmentVariable>,
598 environment_variable_data: Vec<EnvironmentVariableData>,
599 signal_types: Vec<SignalType>,
600 comments: Vec<Comment>,
602 attribute_definitions: Vec<AttributeDefinition>,
603 attribute_defaults: Vec<AttributeDefault>,
606 attribute_values: Vec<AttributeValueForObject>,
607 value_descriptions: Vec<ValueDescription>,
609 signal_type_refs: Vec<SignalTypeRef>,
616 signal_groups: Vec<SignalGroups>,
618 signal_extended_value_type_list: Vec<SignalExtendedValueTypeList>,
619 extended_multiplex: Vec<ExtendedMultiplex>,
621}
622
623impl Dbc {
624 #[allow(clippy::should_implement_trait)]
625 #[deprecated(since = "4.0.0", note = "please use `Dbc::try_from` instead")]
626 #[allow(clippy::result_large_err)]
627 pub fn from_str(dbc_in: &str) -> Result<Dbc, Error<'_>> {
628 let (remaining, dbc) = parser::dbc(dbc_in).map_err(Error::Nom)?;
629 if !remaining.is_empty() {
630 return Err(Error::Incomplete(dbc, remaining));
631 }
632 Ok(dbc)
633 }
634
635 pub fn signal_by_name(&self, message_id: MessageId, signal_name: &str) -> Option<&Signal> {
636 let message = self
637 .messages
638 .iter()
639 .find(|message| message.id == message_id);
640
641 if let Some(message) = message {
642 return message
643 .signals
644 .iter()
645 .find(|signal| signal.name == *signal_name);
646 }
647 None
648 }
649
650 pub fn message_comment(&self, message_id: MessageId) -> Option<&str> {
652 self.comments.iter().find_map(|x| match x {
653 Comment::Message {
654 id: ref x_message_id,
655 ref comment,
656 } => {
657 if *x_message_id == message_id {
658 Some(comment.as_str())
659 } else {
660 None
661 }
662 }
663 _ => None,
664 })
665 }
666
667 pub fn signal_comment(&self, message_id: MessageId, signal_name: &str) -> Option<&str> {
669 self.comments.iter().find_map(|x| match x {
670 Comment::Signal {
671 message_id: ref x_message_id,
672 name: ref x_signal_name,
673 comment,
674 } => {
675 if *x_message_id == message_id && x_signal_name == signal_name {
676 Some(comment.as_str())
677 } else {
678 None
679 }
680 }
681 _ => None,
682 })
683 }
684
685 pub fn value_descriptions_for_signal(
687 &self,
688 message_id: MessageId,
689 signal_name: &str,
690 ) -> Option<&[ValDescription]> {
691 self.value_descriptions.iter().find_map(|x| match x {
692 ValueDescription::Signal {
693 message_id: ref x_message_id,
694 name: ref x_signal_name,
695 ref value_descriptions,
696 } => {
697 if *x_message_id == message_id && x_signal_name == signal_name {
698 Some(value_descriptions.as_slice())
699 } else {
700 None
701 }
702 }
703 ValueDescription::EnvironmentVariable { .. } => None,
704 })
705 }
706
707 pub fn extended_value_type_for_signal(
709 &self,
710 message_id: MessageId,
711 signal_name: &str,
712 ) -> Option<&SignalExtendedValueType> {
713 self.signal_extended_value_type_list.iter().find_map(|x| {
714 let SignalExtendedValueTypeList {
715 message_id: ref x_message_id,
716 signal_name: ref x_signal_name,
717 ref signal_extended_value_type,
718 } = x;
719 if *x_message_id == message_id && x_signal_name == signal_name {
720 Some(signal_extended_value_type)
721 } else {
722 None
723 }
724 })
725 }
726
727 #[allow(clippy::result_large_err)]
730 pub fn message_multiplexor_switch(
731 &self,
732 message_id: MessageId,
733 ) -> Result<Option<&Signal>, Error<'_>> {
734 let message = self
735 .messages
736 .iter()
737 .find(|message| message.id == message_id);
738
739 if let Some(message) = message {
740 if self
741 .extended_multiplex
742 .iter()
743 .any(|ext_mp| ext_mp.message_id == message_id)
744 {
745 Err(Error::MultipleMultiplexors)
746 } else {
747 Ok(message
748 .signals
749 .iter()
750 .find(|signal| signal.multiplexer_indicator == MultiplexIndicator::Multiplexor))
751 }
752 } else {
753 Ok(None)
754 }
755 }
756}
757
758impl<'a> TryFrom<&'a str> for Dbc {
759 type Error = Error<'a>;
760
761 fn try_from(dbc_in: &'a str) -> Result<Self, Self::Error> {
762 let (remaining, dbc) = parser::dbc(dbc_in).map_err(Error::Nom)?;
763 if !remaining.is_empty() {
764 return Err(Error::Incomplete(dbc, remaining));
765 }
766 Ok(dbc)
767 }
768}