can_dbc/ast/
attribute_definition.rs

1use can_dbc_pest::{Pair, Rule};
2
3use crate::parser::{expect_empty, inner_str, next, next_optional_rule, next_rule, DbcError};
4use crate::AttributeValueType;
5
6#[derive(Clone, Debug, PartialEq)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub enum AttributeDefinition {
9    Message(String, AttributeValueType),
10    Node(String, AttributeValueType),
11    Signal(String, AttributeValueType),
12    EnvironmentVariable(String, AttributeValueType),
13    Plain(String, AttributeValueType),
14}
15
16impl TryFrom<Pair<'_, Rule>> for AttributeDefinition {
17    type Error = DbcError;
18
19    /// Parse attribute definition: `BA_DEF_ [object_type] attribute_name attribute_type [min max];`
20    fn try_from(pair: Pair<'_, Rule>) -> Result<Self, Self::Error> {
21        let rule = pair.as_rule();
22        let expected = match rule {
23            Rule::attr_def => Rule::object_type,
24            Rule::ba_def_rel => Rule::rel_object_type,
25            v => Err(DbcError::ExpectedOneOfRules(
26                vec![Rule::attr_def, Rule::ba_def_rel],
27                v,
28            ))?,
29        };
30        let mut pairs = pair.into_inner();
31        let object_type = if let Some(v) = next_optional_rule(&mut pairs, expected) {
32            v.as_str().to_string()
33        } else {
34            String::new()
35        };
36
37        let name = inner_str(next_rule(&mut pairs, Rule::attribute_name)?);
38        let value = next(&mut pairs)?.try_into()?;
39        expect_empty(&pairs)?;
40
41        Ok(match object_type.as_str() {
42            "SG_" | "BU_SG_REL_" => Self::Signal(name, value),
43            "BO_" | "BU_BO_REL_" => Self::Message(name, value),
44            "BU_" => Self::Node(name, value),
45            "EV_" | "BU_EV_REL_" => Self::EnvironmentVariable(name, value),
46            _ => Self::Plain(name, value),
47        })
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::ast::{AttributeValueType, NumericValue};
55    use crate::test_helpers::*;
56
57    #[test]
58    fn attribute_definition_bo_test() {
59        let def = r#"
60BA_DEF_ BO_ "BaDef1BO" INT 0 1000000;
61"#;
62        let exp = AttributeDefinition::Message(
63            "BaDef1BO".to_string(),
64            AttributeValueType::Int(NumericValue::Uint(0), NumericValue::Uint(1_000_000)),
65        );
66        let val = test_into::<AttributeDefinition>(def.trim_start(), Rule::attr_def);
67        assert_eq!(val, exp);
68    }
69
70    #[test]
71    fn attribute_definition_bo_txt_test() {
72        let def = r#"
73BA_DEF_ BO_  "GenMsgSendType" STRING ;
74"#;
75        let exp =
76            AttributeDefinition::Message("GenMsgSendType".to_string(), AttributeValueType::String);
77        let val = test_into::<AttributeDefinition>(def.trim_start(), Rule::attr_def);
78        assert_eq!(val, exp);
79    }
80
81    #[test]
82    fn attribute_definition_bu_test() {
83        let def = r#"
84BA_DEF_ BU_ "BuDef1BO" INT 0 1000000;
85"#;
86        let exp = AttributeDefinition::Node(
87            "BuDef1BO".to_string(),
88            AttributeValueType::Int(NumericValue::Uint(0), NumericValue::Uint(1_000_000)),
89        );
90        let val = test_into::<AttributeDefinition>(def.trim_start(), Rule::attr_def);
91        assert_eq!(val, exp);
92    }
93
94    #[test]
95    fn attribute_definition_sg_test() {
96        let def = r#"
97BA_DEF_ SG_ "SgDef1BO" INT 0 1000000;
98"#;
99        let exp = AttributeDefinition::Signal(
100            "SgDef1BO".to_string(),
101            AttributeValueType::Int(NumericValue::Uint(0), NumericValue::Uint(1_000_000)),
102        );
103        let val = test_into::<AttributeDefinition>(def.trim_start(), Rule::attr_def);
104        assert_eq!(val, exp);
105    }
106
107    #[test]
108    fn attribute_definition_ev_test() {
109        let def = r#"
110BA_DEF_ EV_ "EvDef1BO" INT 0 1000000;
111"#;
112        let exp = AttributeDefinition::EnvironmentVariable(
113            "EvDef1BO".to_string(),
114            AttributeValueType::Int(NumericValue::Uint(0), NumericValue::Uint(1_000_000)),
115        );
116        let val = test_into::<AttributeDefinition>(def.trim_start(), Rule::attr_def);
117        assert_eq!(val, exp);
118    }
119}