can_dbc/ast/
value_description.rs1use can_dbc_pest::{Pair, Rule};
2
3use crate::ast::{MessageId, ValDescription};
4use crate::parser::{collect_expected, next_string, validated_inner, DbcError};
5
6#[derive(Clone, Debug, PartialEq)]
8#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
9pub enum ValueDescription {
10 Signal {
11 message_id: MessageId,
12 name: String,
13 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
14 value_descriptions: Vec<ValDescription>,
15 },
16 EnvironmentVariable {
17 name: String,
18 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
19 value_descriptions: Vec<ValDescription>,
20 },
21}
22
23impl TryFrom<Pair<'_, Rule>> for ValueDescription {
24 type Error = DbcError;
25
26 fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
28 let mut pairs = validated_inner(value, Rule::value_table_def)?;
29
30 let mut message_id = None;
32 if let Some(first_pair) = pairs.next() {
33 if first_pair.as_rule() == Rule::message_id {
34 message_id = Some(first_pair.try_into()?);
35 } else {
36 let name = first_pair.as_str().to_string();
38 let value_descriptions =
39 collect_expected(&mut pairs, Rule::table_value_description)?;
40 return Ok(Self::EnvironmentVariable {
41 name,
42 value_descriptions,
43 });
44 }
45 }
46
47 let name = next_string(&mut pairs, Rule::signal_name)?;
48 let value_descriptions = collect_expected(&mut pairs, Rule::table_value_description)?;
49
50 if let Some(message_id) = message_id {
51 Ok(Self::Signal {
52 message_id,
53 name,
54 value_descriptions,
55 })
56 } else {
57 Ok(Self::EnvironmentVariable {
58 name,
59 value_descriptions,
60 })
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::test_helpers::*;
69
70 #[test]
71 fn value_description_for_signal_test() {
72 let def = r#"
73VAL_ 837 UF_HZ_OI 255 "NOP";
74"#;
75 let exp = ValueDescription::Signal {
76 message_id: MessageId::Standard(837),
77 name: "UF_HZ_OI".to_string(),
78 value_descriptions: vec![ValDescription {
79 id: 255,
80 description: "NOP".to_string(),
81 }],
82 };
83 let val = test_into::<ValueDescription>(def.trim_start(), Rule::value_table_def);
84 assert_eq!(val, exp);
85 }
86
87 #[test]
88 fn value_description_for_env_var_test() {
89 let def = r#"
90VAL_ MY_ENV_VAR 255 "NOP";
91"#;
92 let exp = ValueDescription::EnvironmentVariable {
93 name: "MY_ENV_VAR".to_string(),
94 value_descriptions: vec![ValDescription {
95 id: 255,
96 description: "NOP".to_string(),
97 }],
98 };
99 let val = test_into::<ValueDescription>(def.trim_start(), Rule::value_table_def);
100 assert_eq!(val, exp);
101 }
102}