rrdbc/ast/
value_descriptions.rs

1use std::fmt;
2
3use nom::character::complete::i64;
4use nom::combinator::map;
5use nom::multi::many0;
6use nom::{IResult, Parser};
7
8use super::char_string::{parser_char_string, CharString};
9use super::common_parsers::spacey;
10use super::error::DbcParseError;
11
12/// A value description defines a textual description for a single value. This value may
13/// either be a signal raw value transferred on the bus or the value of an environment
14/// variable in a remaining bus simulation.
15///
16/// ```text
17/// value_description = unsigned_integer char_string ;
18/// ```
19///
20/// example:
21///
22/// ```text
23/// VAL_TABLE_ ABS_fault_info 2 "active faults stored" 1 "inactive faults stored" 0 "no faults stored" ;
24/// VAL_TABLE_ vt_WheelSpeedQualifier 5 "InvalidUnderVoltage" 4 "NotCalculated" 3 "ReducedMonitored" 2 "Faulty" 1 "Normal" 0 "NotInitialized" ;
25///
26/// VAL_ message_id signal_name [value_descriptions];
27/// VAL_ 2147487969 Value1 3 "Three" 2 "Two" 1 "One" 0 "Zero" ;
28/// VAL_ 2147487969 Value0 2 "Value2" 1 "Value1" 0 "Value0" ;
29///
30/// VAL_ env_var_name [value_descriptions];
31/// VAL_ RWEnvVar_wData 2 "Value2" 1 "Value1" 0 "Value0" ;
32/// VAL_ WriteOnlyEnvVar 2 "Value2" 1 "Value1" 0 "Value0" ;
33/// VAL_ ReadOnlyEnvVar 2 "Value2" 1 "Value1" 0 "Value0" ;
34/// ```
35#[derive(PartialEq, Debug, Clone)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub struct ValueDescriptionItem {
38    pub num: i64,
39    pub str: CharString,
40}
41
42impl fmt::Display for ValueDescriptionItem {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, r#"{} "{}""#, self.num, self.str)
45    }
46}
47
48#[derive(PartialEq, Debug, Clone)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50pub struct ValueDescriptions {
51    pub values: Vec<ValueDescriptionItem>,
52}
53
54impl fmt::Display for ValueDescriptions {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        for (i, item) in self.values.iter().enumerate() {
57            if i > 0 {
58                write!(f, " ")?;
59            }
60            write!(f, "{item}")?;
61        }
62        Ok(())
63    }
64}
65
66pub fn parser_value_description_item(
67    input: &str,
68) -> IResult<&str, ValueDescriptionItem, DbcParseError> {
69    map((spacey(i64), spacey(parser_char_string)), |(num, str)| {
70        ValueDescriptionItem { num, str }
71    })
72    .parse(input)
73}
74
75pub fn parser_value_descriptions(input: &str) -> IResult<&str, ValueDescriptions, DbcParseError> {
76    map(many0(spacey(parser_value_description_item)), |values| {
77        ValueDescriptions { values }
78    })
79    .parse(input)
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85
86    #[test]
87    fn test_parser_value_description_item_01() {
88        assert_eq!(
89            parser_value_description_item(r#"2 "active faults stored""#),
90            Ok((
91                "",
92                ValueDescriptionItem {
93                    num: 2,
94                    str: CharString("active faults stored".to_string())
95                }
96            )),
97        );
98    }
99
100    #[test]
101    fn test_parser_value_descriptions_01() {
102        assert_eq!(
103            parser_value_descriptions(r#"2 "active faults stored""#),
104            Ok((
105                "",
106                ValueDescriptions {
107                    values: vec![ValueDescriptionItem {
108                        num: 2,
109                        str: CharString("active faults stored".to_string())
110                    }]
111                }
112            )),
113        );
114    }
115
116    #[test]
117    fn test_parser_value_descriptions_02() {
118        assert_eq!(
119            parser_value_descriptions(
120                r#" 2 "active faults stored" 1 "inactive faults stored" 0 "no faults stored" "#
121            ),
122            Ok((
123                "",
124                ValueDescriptions {
125                    values: vec![
126                        ValueDescriptionItem {
127                            num: 2,
128                            str: CharString("active faults stored".to_string())
129                        },
130                        ValueDescriptionItem {
131                            num: 1,
132                            str: CharString("inactive faults stored".to_string())
133                        },
134                        ValueDescriptionItem {
135                            num: 0,
136                            str: CharString("no faults stored".to_string())
137                        }
138                    ]
139                }
140            )),
141        );
142    }
143
144    #[test]
145    fn test_value_description_string_01() {
146        assert_eq!(
147            ValueDescriptionItem {
148                num: 2,
149                str: CharString("active faults stored".to_string())
150            }
151            .to_string(),
152            r#"2 "active faults stored""#
153        );
154    }
155
156    #[test]
157    fn test_value_descriptions_string_01() {
158        assert_eq!(
159            ValueDescriptions {
160                values: vec![
161                    ValueDescriptionItem {
162                        num: 2,
163                        str: CharString("active faults stored".to_string())
164                    },
165                    ValueDescriptionItem {
166                        num: 1,
167                        str: CharString("inactive faults stored".to_string())
168                    },
169                    ValueDescriptionItem {
170                        num: 0,
171                        str: CharString("no faults stored".to_string())
172                    }
173                ]
174            }
175            .to_string(),
176            r#"2 "active faults stored" 1 "inactive faults stored" 0 "no faults stored""#
177        );
178    }
179
180    #[test]
181    fn test_value_descriptions_string_02() {
182        assert_eq!(ValueDescriptions { values: vec![] }.to_string(), "");
183    }
184}