1#[cfg(feature = "with-serde")]
39extern crate serde;
40#[cfg(feature = "with-serde")]
41#[macro_use]
42extern crate serde_derive;
43
44use std::convert::TryFrom;
45
46use derive_getters::Getters;
47
48pub mod parser;
49
50#[cfg(test)]
51mod tests {
52
53 use super::*;
54
55 const SAMPLE_DBC: &str = r#"
56VERSION "0.1"
57NS_ :
58 NS_DESC_
59 CM_
60 BA_DEF_
61 BA_
62 VAL_
63 CAT_DEF_
64 CAT_
65 FILTER
66 BA_DEF_DEF_
67 EV_DATA_
68 ENVVAR_DATA_
69 SGTYPE_
70 SGTYPE_VAL_
71 BA_DEF_SGTYPE_
72 BA_SGTYPE_
73 SIG_TYPE_REF_
74 VAL_TABLE_
75 SIG_GROUP_
76 SIG_VALTYPE_
77 SIGTYPE_VALTYPE_
78 BO_TX_BU_
79 BA_DEF_REL_
80 BA_REL_
81 BA_DEF_DEF_REL_
82 BU_SG_REL_
83 BU_EV_REL_
84 BU_BO_REL_
85 SG_MUL_VAL_
86BS_:
87BU_: PC
88BO_ 2000 WebData_2000: 4 Vector__XXX
89 SG_ Signal_8 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
90 SG_ Signal_7 : 16|8@1+ (1,0) [0|255] "" Vector__XXX
91 SG_ Signal_6 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
92 SG_ Signal_5 : 0|8@1+ (1,0) [0|255] "" Vector__XXX
93BO_ 1840 WebData_1840: 4 PC
94 SG_ Signal_4 : 24|8@1+ (1,0) [0|255] "" Vector__XXX
95 SG_ Signal_3 : 16|8@1+ (1,0) [0|255] "" Vector__XXX
96 SG_ Signal_2 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
97 SG_ Signal_1 : 0|8@1+ (1,0) [0|0] "" Vector__XXX
98
99BO_ 3040 WebData_3040: 8 Vector__XXX
100 SG_ Signal_6 m2 : 0|4@1+ (1,0) [0|15] "" Vector__XXX
101 SG_ Signal_5 m3 : 16|8@1+ (1,0) [0|255] "kmh" Vector__XXX
102 SG_ Signal_4 m3 : 8|8@1+ (1,0) [0|255] "" Vector__XXX
103 SG_ Signal_3 m3 : 0|4@1+ (1,0) [0|3] "" Vector__XXX
104 SG_ Signal_2 m1 : 3|12@0+ (1,0) [0|4095] "Byte" Vector__XXX
105 SG_ Signal_1 m0 : 0|4@1+ (1,0) [0|7] "Byte" Vector__XXX
106 SG_ Switch M : 4|4@1+ (1,0) [0|3] "" Vector__XXX
107
108EV_ Environment1: 0 [0|220] "" 0 6 DUMMY_NODE_VECTOR0 DUMMY_NODE_VECTOR2;
109EV_ Environment2: 0 [0|177] "" 0 7 DUMMY_NODE_VECTOR1 DUMMY_NODE_VECTOR2;
110ENVVAR_DATA_ SomeEnvVarData: 399;
111
112CM_ BO_ 1840 "Some Message comment";
113CM_ SG_ 1840 Signal_4 "asaklfjlsdfjlsdfgls
114HH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv";
115CM_ SG_ 5 TestSigLittleUnsigned1 "asaklfjlsdfjlsdfgls
116=0943503450KFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv";
117
118BA_DEF_DEF_ "BusType" "AS";
119
120BA_ "Attr" BO_ 4358435 283;
121BA_ "Attr" BO_ 56949545 344;
122
123VAL_ 2000 Signal_3 255 "NOP";
124
125SIG_VALTYPE_ 2000 Signal_8 : 1;
126"#;
127
128 #[test]
129 fn dbc_definition_test() {
130 match DBC::try_from(SAMPLE_DBC) {
131 Ok(dbc_content) => println!("DBC Content{:#?}", dbc_content),
132 Err(e) => {
133 match e {
134 Error::Nom(nom::Err::Incomplete(needed)) => {
135 eprintln!("Error incomplete input, needed: {:?}", needed)
136 }
137 Error::Nom(nom::Err::Error(error)) => {
138 eprintln!("Nom Error: {:?}", error);
139 }
140 Error::Nom(nom::Err::Failure(ctx)) => eprintln!("Failure {:?}", ctx),
141 Error::Incomplete(dbc, remaining) => eprintln!(
142 "Not all data in buffer was read {:#?}, remaining unparsed: {}",
143 dbc, remaining
144 ),
145 Error::MultipleMultiplexors => eprintln!("Multiple multiplexors defined"),
146 }
147 panic!("Failed to read DBC");
148 }
149 }
150 }
151
152 #[test]
153 fn lookup_signal_comment() {
154 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
155 let comment = dbc_content
156 .signal_comment(MessageId::Standard(1840), "Signal_4")
157 .expect("Signal comment missing");
158 assert_eq!(
159 "asaklfjlsdfjlsdfgls\nHH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv",
160 comment
161 );
162 }
163
164 #[test]
165 fn lookup_signal_comment_none_when_missing() {
166 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
167 let comment = dbc_content.signal_comment(MessageId::Standard(1840), "Signal_2");
168 assert_eq!(None, comment);
169 }
170
171 #[test]
172 fn lookup_message_comment() {
173 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
174 let comment = dbc_content
175 .message_comment(MessageId::Standard(1840))
176 .expect("Message comment missing");
177 assert_eq!("Some Message comment", comment);
178 }
179
180 #[test]
181 fn lookup_message_comment_none_when_missing() {
182 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
183 let comment = dbc_content.message_comment(MessageId::Standard(2000));
184 assert_eq!(None, comment);
185 }
186
187 #[test]
188 fn lookup_value_descriptions_for_signal() {
189 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
190 let val_descriptions = dbc_content
191 .value_descriptions_for_signal(MessageId::Standard(2000), "Signal_3")
192 .expect("Message comment missing");
193
194 let exp = vec![ValDescription {
195 a: 255.0,
196 b: "NOP".to_string(),
197 }];
198 assert_eq!(exp, val_descriptions);
199 }
200
201 #[test]
202 fn lookup_value_descriptions_for_signal_none_when_missing() {
203 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
204 let val_descriptions =
205 dbc_content.value_descriptions_for_signal(MessageId::Standard(2000), "Signal_2");
206 assert_eq!(None, val_descriptions);
207 }
208
209 #[test]
210 fn lookup_extended_value_type_for_signal() {
211 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
212 let extended_value_type =
213 dbc_content.extended_value_type_for_signal(MessageId::Standard(2000), "Signal_8");
214 assert_eq!(
215 extended_value_type,
216 Some(&SignalExtendedValueType::IEEEfloat32Bit)
217 );
218 }
219
220 #[test]
221 fn lookup_extended_value_type_for_signal_none_when_missing() {
222 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
223 let extended_value_type =
224 dbc_content.extended_value_type_for_signal(MessageId::Standard(2000), "Signal_1");
225 assert_eq!(extended_value_type, None);
226 }
227
228 #[test]
229 fn lookup_signal_by_name() {
230 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
231 let signal = dbc_content.signal_by_name(MessageId::Standard(2000), "Signal_8");
232 assert!(signal.is_some());
233 }
234
235 #[test]
236 fn lookup_signal_by_name_none_when_missing() {
237 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
238 let signal = dbc_content.signal_by_name(MessageId::Standard(2000), "Signal_25");
239 assert_eq!(signal, None);
240 }
241
242 #[test]
243 fn lookup_multiplex_indicator_switch() {
244 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
245 let multiplexor_switch = dbc_content.message_multiplexor_switch(MessageId::Standard(3040));
246 assert!(multiplexor_switch.is_ok());
247 assert!(multiplexor_switch.as_ref().unwrap().is_some());
248 assert_eq!(multiplexor_switch.unwrap().unwrap().name(), "Switch");
249 }
250
251 #[test]
252 fn lookup_multiplex_indicator_switch_none_when_missing() {
253 let dbc_content = DBC::try_from(SAMPLE_DBC).expect("Failed to parse DBC");
254 let multiplexor_switch = dbc_content.message_multiplexor_switch(MessageId::Standard(1840));
255 assert!(multiplexor_switch.unwrap().is_none());
256 }
257
258 #[test]
259 fn extended_message_id_raw() {
260 let message_id = MessageId::Extended(2);
261 assert_eq!(message_id.raw(), 2 | 1 << 31);
262 let message_id = MessageId::Extended(2 ^ 29);
263 assert_eq!(message_id.raw(), 2 ^ 29 | 1 << 31);
264 }
265
266 #[test]
267 fn standard_message_id_raw() {
268 let message_id = MessageId::Standard(2);
269 assert_eq!(message_id.raw(), 2);
270 }
271}
272
273#[allow(clippy::large_enum_variant)]
275#[derive(Debug)]
276pub enum Error<'a> {
277 Incomplete(DBC, &'a str),
280 Nom(nom::Err<nom::error::Error<&'a str>>),
282 MultipleMultiplexors,
284}
285
286#[derive(Copy, Clone, Debug, PartialEq)]
288#[cfg_attr(feature = "serde", derive(Serialize))]
289pub struct Baudrate(u64);
290
291#[derive(Clone, Debug, PartialEq, Getters)]
295#[cfg_attr(feature = "serde", derive(Serialize))]
296pub struct Signal {
297 name: String,
298 multiplexer_indicator: MultiplexIndicator,
299 pub start_bit: u64,
300 pub signal_size: u64,
301 byte_order: ByteOrder,
302 value_type: ValueType,
303 pub factor: f64,
304 pub offset: f64,
305 pub min: f64,
306 pub max: f64,
307 unit: String,
308 receivers: Vec<String>,
309}
310
311#[derive(Copy, Clone, Debug, PartialEq)]
314#[cfg_attr(feature = "serde", derive(Serialize))]
315pub enum MessageId {
316 Standard(u16),
317 Extended(u32),
320}
321
322impl MessageId {
323 pub fn raw(&self) -> u32 {
325 match self {
326 MessageId::Standard(id) => *id as u32,
327 MessageId::Extended(id) => *id | 1 << 31,
328 }
329 }
330}
331
332#[derive(Clone, Debug, PartialEq)]
333#[cfg_attr(feature = "serde", derive(Serialize))]
334pub enum Transmitter {
335 NodeName(String),
337 VectorXXX,
339}
340
341#[derive(Clone, Debug, PartialEq, Getters)]
342#[cfg_attr(feature = "serde", derive(Serialize))]
343pub struct MessageTransmitter {
344 message_id: MessageId,
345 transmitter: Vec<Transmitter>,
346}
347
348#[derive(Clone, Debug, PartialEq)]
350#[cfg_attr(feature = "serde", derive(Serialize))]
351pub struct Version(pub String);
352
353#[derive(Clone, Debug, PartialEq)]
354#[cfg_attr(feature = "serde", derive(Serialize))]
355pub struct Symbol(pub String);
356
357#[derive(Copy, Clone, Debug, PartialEq)]
358#[cfg_attr(feature = "serde", derive(Serialize))]
359pub enum MultiplexIndicator {
360 Multiplexor,
362 MultiplexedSignal(u64),
364 MultiplexorAndMultiplexedSignal(u64),
366 Plain,
368}
369
370#[derive(Copy, Clone, Debug, PartialEq)]
371#[cfg_attr(feature = "serde", derive(Serialize))]
372pub enum ByteOrder {
373 LittleEndian,
374 BigEndian,
375}
376
377#[derive(Copy, Clone, Debug, PartialEq)]
378#[cfg_attr(feature = "serde", derive(Serialize))]
379pub enum ValueType {
380 Signed,
381 Unsigned,
382}
383
384#[derive(Copy, Clone, Debug, PartialEq)]
385#[cfg_attr(feature = "serde", derive(Serialize))]
386pub enum EnvType {
387 EnvTypeFloat,
388 EnvTypeu64,
389 EnvTypeData,
390}
391
392#[derive(Clone, Debug, PartialEq, Getters)]
393#[cfg_attr(feature = "serde", derive(Serialize))]
394pub struct SignalType {
395 signal_type_name: String,
396 signal_size: u64,
397 byte_order: ByteOrder,
398 value_type: ValueType,
399 factor: f64,
400 offset: f64,
401 min: f64,
402 max: f64,
403 unit: String,
404 default_value: f64,
405 value_table: String,
406}
407
408#[derive(Copy, Clone, Debug, PartialEq)]
409#[cfg_attr(feature = "serde", derive(Serialize))]
410pub enum AccessType {
411 DummyNodeVector0,
412 DummyNodeVector1,
413 DummyNodeVector2,
414 DummyNodeVector3,
415}
416
417#[derive(Clone, Debug, PartialEq)]
418#[cfg_attr(feature = "serde", derive(Serialize))]
419pub enum AccessNode {
420 AccessNodeVectorXXX,
421 AccessNodeName(String),
422}
423
424#[derive(Clone, Debug, PartialEq)]
425#[cfg_attr(feature = "serde", derive(Serialize))]
426pub enum SignalAttributeValue {
427 Text(String),
428 Int(i64),
429}
430
431#[derive(Clone, Debug, PartialEq)]
432#[cfg_attr(feature = "serde", derive(Serialize))]
433pub enum AttributeValuedForObjectType {
434 RawAttributeValue(AttributeValue),
435 NetworkNodeAttributeValue(String, AttributeValue),
436 MessageDefinitionAttributeValue(MessageId, Option<AttributeValue>),
437 SignalAttributeValue(MessageId, String, AttributeValue),
438 EnvVariableAttributeValue(String, AttributeValue),
439}
440
441#[derive(Clone, Debug, PartialEq)]
442#[cfg_attr(feature = "serde", derive(Serialize))]
443pub enum AttributeValueType {
444 AttributeValueTypeInt(i64, i64),
445 AttributeValueTypeHex(i64, i64),
446 AttributeValueTypeFloat(f64, f64),
447 AttributeValueTypeString,
448 AttributeValueTypeEnum(Vec<String>),
449}
450
451#[derive(Clone, Debug, PartialEq, Getters)]
452#[cfg_attr(feature = "serde", derive(Serialize))]
453pub struct ValDescription {
454 a: f64,
455 b: String,
456}
457
458#[derive(Clone, Debug, PartialEq, Getters)]
459#[cfg_attr(feature = "serde", derive(Serialize))]
460pub struct AttrDefault {
461 name: String,
462 value: AttributeValue,
463}
464
465#[cfg_attr(feature = "serde", derive(Serialize))]
466#[derive(Clone, Debug, PartialEq)]
467pub enum AttributeValue {
468 AttributeValueU64(u64),
469 AttributeValueI64(i64),
470 AttributeValueF64(f64),
471 AttributeValueCharString(String),
472}
473
474#[derive(Clone, Debug, PartialEq, Getters)]
476#[cfg_attr(feature = "serde", derive(Serialize))]
477pub struct ValueTable {
478 value_table_name: String,
479 value_descriptions: Vec<ValDescription>,
480}
481
482#[derive(Clone, Debug, PartialEq, Getters)]
483#[cfg_attr(feature = "serde", derive(Serialize))]
484pub struct ExtendedMultiplexMapping {
485 min_value: u64,
486 max_value: u64,
487}
488#[derive(Clone, Debug, PartialEq, Getters)]
490#[cfg_attr(feature = "serde", derive(Serialize))]
491pub struct ExtendedMultiplex {
492 message_id: MessageId,
493 signal_name: String,
494 multiplexor_signal_name: String,
495 mappings: Vec<ExtendedMultiplexMapping>,
496}
497
498#[derive(Clone, Debug, PartialEq)]
500#[cfg_attr(feature = "serde", derive(Serialize))]
501pub enum Comment {
502 Node {
503 node_name: String,
504 comment: String,
505 },
506 Message {
507 message_id: MessageId,
508 comment: String,
509 },
510 Signal {
511 message_id: MessageId,
512 signal_name: String,
513 comment: String,
514 },
515 EnvVar {
516 env_var_name: String,
517 comment: String,
518 },
519 Plain {
520 comment: String,
521 },
522}
523
524#[derive(Clone, Debug, PartialEq, Getters)]
526#[cfg_attr(feature = "serde", derive(Serialize))]
527pub struct Message {
528 message_id: MessageId,
531 message_name: String,
532 message_size: u64,
533 transmitter: Transmitter,
534 signals: Vec<Signal>,
535}
536
537#[derive(Clone, Debug, PartialEq, Getters)]
538#[cfg_attr(feature = "serde", derive(Serialize))]
539pub struct EnvironmentVariable {
540 env_var_name: String,
541 env_var_type: EnvType,
542 min: i64,
543 max: i64,
544 unit: String,
545 initial_value: f64,
546 ev_id: i64,
547 access_type: AccessType,
548 access_nodes: Vec<AccessNode>,
549}
550
551#[derive(Clone, Debug, PartialEq, Getters)]
552#[cfg_attr(feature = "serde", derive(Serialize))]
553pub struct EnvironmentVariableData {
554 env_var_name: String,
555 data_size: u64,
556}
557
558#[derive(Clone, Debug, PartialEq)]
560#[cfg_attr(feature = "serde", derive(Serialize))]
561pub struct Node(pub Vec<String>);
562
563#[derive(Clone, Debug, PartialEq, Getters)]
564#[cfg_attr(feature = "serde", derive(Serialize))]
565pub struct AttributeDefault {
566 attribute_name: String,
567 attribute_value: AttributeValue,
568}
569
570#[derive(Clone, Debug, PartialEq, Getters)]
571#[cfg_attr(feature = "serde", derive(Serialize))]
572pub struct AttributeValueForObject {
573 attribute_name: String,
574 attribute_value: AttributeValuedForObjectType,
575}
576
577#[derive(Clone, Debug, PartialEq)]
578#[cfg_attr(feature = "serde", derive(Serialize))]
579pub enum AttributeDefinition {
580 Message(String),
582 Node(String),
584 Signal(String),
586 EnvironmentVariable(String),
587 Plain(String),
589}
590
591#[derive(Clone, Debug, PartialEq)]
593#[cfg_attr(feature = "serde", derive(Serialize))]
594pub enum ValueDescription {
595 Signal {
596 message_id: MessageId,
597 signal_name: String,
598 value_descriptions: Vec<ValDescription>,
599 },
600 EnvironmentVariable {
601 env_var_name: String,
602 value_descriptions: Vec<ValDescription>,
603 },
604}
605
606#[derive(Clone, Debug, PartialEq, Getters)]
607#[cfg_attr(feature = "serde", derive(Serialize))]
608pub struct SignalTypeRef {
609 message_id: MessageId,
610 signal_name: String,
611 signal_type_name: String,
612}
613
614#[derive(Clone, Debug, PartialEq, Getters)]
616#[cfg_attr(feature = "serde", derive(Serialize))]
617pub struct SignalGroups {
618 message_id: MessageId,
619 signal_group_name: String,
620 repetitions: u64,
621 signal_names: Vec<String>,
622}
623
624#[derive(Copy, Clone, Debug, PartialEq)]
625#[cfg_attr(feature = "serde", derive(Serialize))]
626pub enum SignalExtendedValueType {
627 SignedOrUnsignedInteger,
628 IEEEfloat32Bit,
629 IEEEdouble64bit,
630}
631
632#[derive(Clone, Debug, PartialEq, Getters)]
633#[cfg_attr(feature = "serde", derive(Serialize))]
634pub struct SignalExtendedValueTypeList {
635 message_id: MessageId,
636 signal_name: String,
637 signal_extended_value_type: SignalExtendedValueType,
638}
639
640#[derive(Clone, Debug, PartialEq, Getters)]
641#[cfg_attr(feature = "serde", derive(Serialize))]
642pub struct DBC {
643 version: Version,
645 new_symbols: Vec<Symbol>,
646 bit_timing: Option<Vec<Baudrate>>,
648 nodes: Vec<Node>,
650 value_tables: Vec<ValueTable>,
652 messages: Vec<Message>,
654 message_transmitters: Vec<MessageTransmitter>,
655 environment_variables: Vec<EnvironmentVariable>,
656 environment_variable_data: Vec<EnvironmentVariableData>,
657 signal_types: Vec<SignalType>,
658 comments: Vec<Comment>,
660 attribute_definitions: Vec<AttributeDefinition>,
661 attribute_defaults: Vec<AttributeDefault>,
664 attribute_values: Vec<AttributeValueForObject>,
665 value_descriptions: Vec<ValueDescription>,
667 signal_type_refs: Vec<SignalTypeRef>,
674 signal_groups: Vec<SignalGroups>,
676 signal_extended_value_type_list: Vec<SignalExtendedValueTypeList>,
677 extended_multiplex: Vec<ExtendedMultiplex>,
679}
680
681impl DBC {
682 #[allow(clippy::result_large_err)]
684 pub fn from_slice(buffer: &[u8]) -> Result<DBC, Error> {
685 let dbc_in = std::str::from_utf8(buffer).unwrap();
686 Self::try_from(dbc_in)
687 }
688
689 #[allow(clippy::should_implement_trait)]
690 #[deprecated(since = "4.0.0", note = "please use `DBC::try_from` instead")]
691 #[allow(clippy::result_large_err)]
692 pub fn from_str(dbc_in: &str) -> Result<DBC, Error> {
693 let (remaining, dbc) = parser::dbc(dbc_in).map_err(Error::Nom)?;
694 if !remaining.is_empty() {
695 return Err(Error::Incomplete(dbc, remaining));
696 }
697 Ok(dbc)
698 }
699
700 pub fn signal_by_name(&self, message_id: MessageId, signal_name: &str) -> Option<&Signal> {
701 let message = self
702 .messages
703 .iter()
704 .find(|message| message.message_id == message_id);
705
706 if let Some(message) = message {
707 return message
708 .signals
709 .iter()
710 .find(|signal| signal.name == *signal_name);
711 }
712 None
713 }
714
715 pub fn message_comment(&self, message_id: MessageId) -> Option<&str> {
717 self.comments
718 .iter()
719 .filter_map(|x| match x {
720 Comment::Message {
721 message_id: ref x_message_id,
722 ref comment,
723 } => {
724 if *x_message_id == message_id {
725 Some(comment.as_str())
726 } else {
727 None
728 }
729 }
730 _ => None,
731 })
732 .next()
733 }
734
735 pub fn signal_comment(&self, message_id: MessageId, signal_name: &str) -> Option<&str> {
737 self.comments
738 .iter()
739 .filter_map(|x| match x {
740 Comment::Signal {
741 message_id: ref x_message_id,
742 signal_name: ref x_signal_name,
743 comment,
744 } => {
745 if *x_message_id == message_id && x_signal_name == signal_name {
746 Some(comment.as_str())
747 } else {
748 None
749 }
750 }
751 _ => None,
752 })
753 .next()
754 }
755
756 pub fn value_descriptions_for_signal(
758 &self,
759 message_id: MessageId,
760 signal_name: &str,
761 ) -> Option<&[ValDescription]> {
762 self.value_descriptions
763 .iter()
764 .filter_map(|x| match x {
765 ValueDescription::Signal {
766 message_id: ref x_message_id,
767 signal_name: ref x_signal_name,
768 ref value_descriptions,
769 } => {
770 if *x_message_id == message_id && x_signal_name == signal_name {
771 Some(value_descriptions.as_slice())
772 } else {
773 None
774 }
775 }
776 _ => None,
777 })
778 .next()
779 }
780
781 pub fn extended_value_type_for_signal(
783 &self,
784 message_id: MessageId,
785 signal_name: &str,
786 ) -> Option<&SignalExtendedValueType> {
787 self.signal_extended_value_type_list
788 .iter()
789 .filter_map(|x| {
790 let SignalExtendedValueTypeList {
791 message_id: ref x_message_id,
792 signal_name: ref x_signal_name,
793 ref signal_extended_value_type,
794 } = x;
795 if *x_message_id == message_id && x_signal_name == signal_name {
796 Some(signal_extended_value_type)
797 } else {
798 None
799 }
800 })
801 .next()
802 }
803
804 #[allow(clippy::result_large_err)]
807 pub fn message_multiplexor_switch(
808 &self,
809 message_id: MessageId,
810 ) -> Result<Option<&Signal>, Error> {
811 let message = self
812 .messages
813 .iter()
814 .find(|message| message.message_id == message_id);
815
816 if let Some(message) = message {
817 if self
818 .extended_multiplex
819 .iter()
820 .any(|ext_mp| ext_mp.message_id == message_id)
821 {
822 Err(Error::MultipleMultiplexors)
823 } else {
824 Ok(message
825 .signals
826 .iter()
827 .find(|signal| signal.multiplexer_indicator == MultiplexIndicator::Multiplexor))
828 }
829 } else {
830 Ok(None)
831 }
832 }
833}
834
835impl<'a> TryFrom<&'a str> for DBC {
836 type Error = Error<'a>;
837
838 fn try_from(dbc_in: &'a str) -> Result<Self, Self::Error> {
839 let (remaining, dbc) = parser::dbc(dbc_in).map_err(Error::Nom)?;
840 if !remaining.is_empty() {
841 return Err(Error::Incomplete(dbc, remaining));
842 }
843 Ok(dbc)
844 }
845}