Skip to main content

can_dbc/ast/
message.rs

1use can_dbc_pest::{Pair, Rule};
2
3use crate::ast::{MessageId, Signal};
4use crate::parser::{
5    collect_expected, next_rule, next_string, node_name_or_none, parse_next_uint, single_inner,
6    validated_inner,
7};
8use crate::DbcError;
9
10/// CAN message (frame) details including signal details
11#[derive(Clone, Debug, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Message {
14    /// CAN id in header of CAN frame.
15    /// Must be unique in DBC file.
16    pub id: MessageId,
17    pub name: String,
18    pub size: u64,
19    pub transmitter: Option<String>,
20    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
21    pub signals: Vec<Signal>,
22}
23
24impl TryFrom<Pair<'_, Rule>> for Message {
25    type Error = DbcError;
26
27    /// Parse message: `BO_ message_id message_name: message_size transmitter`
28    fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
29        let mut pairs = validated_inner(value, Rule::message)?;
30
31        // Parse msg_var (contains msg_literal ~ message_id)
32        let msg_var_pair = next_rule(&mut pairs, Rule::msg_var)?;
33        let id = single_inner(msg_var_pair, Rule::message_id)?.try_into()?;
34        let name = next_string(&mut pairs, Rule::message_name)?;
35        let size = parse_next_uint(&mut pairs, Rule::message_size)?;
36
37        let transmitter = node_name_or_none(next_string(&mut pairs, Rule::transmitter)?);
38
39        let signals = collect_expected(&mut pairs, Rule::signal)?;
40
41        Ok(Self {
42            id,
43            name,
44            size,
45            transmitter,
46            signals,
47        })
48    }
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54    use crate::ast::{ByteOrder, MultiplexIndicator, ValueType};
55    use crate::test_helpers::*;
56    use crate::NumericValue;
57
58    #[test]
59    fn message_definition_test() {
60        let def = r#"
61BO_ 1 MCA_A1: 6 MFA
62 SG_ ABC_1 : 9|2@1+ (1,0) [0|0] "x" XYZ_OUS
63 SG_ BasL2 : 3|2@0- (1,0) [0|0] "x" DFA_FUS
64"#;
65
66        let exp = Message {
67            id: MessageId::Standard(1),
68            name: "MCA_A1".to_string(),
69            size: 6,
70            transmitter: Some("MFA".to_string()),
71            signals: vec![
72                Signal {
73                    name: "ABC_1".to_string(),
74                    start_bit: 9,
75                    size: 2,
76                    byte_order: ByteOrder::LittleEndian,
77                    value_type: ValueType::Unsigned,
78                    factor: 1.0,
79                    offset: 0.0,
80                    min: NumericValue::Uint(0),
81                    max: NumericValue::Uint(0),
82                    unit: "x".to_string(),
83                    multiplexer_indicator: MultiplexIndicator::Plain,
84                    receivers: vec!["XYZ_OUS".to_string()],
85                },
86                Signal {
87                    name: "BasL2".to_string(),
88                    start_bit: 3,
89                    size: 2,
90                    byte_order: ByteOrder::BigEndian,
91                    value_type: ValueType::Signed,
92                    factor: 1.0,
93                    offset: 0.0,
94                    min: NumericValue::Uint(0),
95                    max: NumericValue::Uint(0),
96                    unit: "x".to_string(),
97                    multiplexer_indicator: MultiplexIndicator::Plain,
98                    receivers: vec!["DFA_FUS".to_string()],
99                },
100            ],
101        };
102        let val = test_into::<Message>(def.trim_start(), Rule::message);
103        assert_eq!(val, exp);
104    }
105
106    #[test]
107    fn min_max_numeric_test() {
108        let def = r#"BO_ 1 MCA_A1: 6 MFA
109 SG_ uint : 9|2@1+ (1,0) [0|18446744073709551615] "x" XYZ_OUS
110 SG_ int : 3|2@0- (1,0) [-9223372036854775808|9223372036854775807] "x" DFA_FUS
111"#;
112
113        let exp = Message {
114            id: MessageId::Standard(1),
115            name: "MCA_A1".to_string(),
116            size: 6,
117            transmitter: Some("MFA".to_string()),
118            signals: vec![
119                Signal {
120                    name: "uint".to_string(),
121                    start_bit: 9,
122                    size: 2,
123                    byte_order: ByteOrder::LittleEndian,
124                    value_type: ValueType::Unsigned,
125                    factor: 1.0,
126                    offset: 0.0,
127                    min: NumericValue::Uint(0),
128                    max: NumericValue::Uint(18_446_744_073_709_551_615),
129                    unit: "x".to_string(),
130                    multiplexer_indicator: MultiplexIndicator::Plain,
131                    receivers: vec!["XYZ_OUS".to_string()],
132                },
133                Signal {
134                    name: "int".to_string(),
135                    start_bit: 3,
136                    size: 2,
137                    byte_order: ByteOrder::BigEndian,
138                    value_type: ValueType::Signed,
139                    factor: 1.0,
140                    offset: 0.0,
141                    min: NumericValue::Int(-9_223_372_036_854_775_808),
142                    max: NumericValue::Uint(9_223_372_036_854_775_807),
143                    unit: "x".to_string(),
144                    multiplexer_indicator: MultiplexIndicator::Plain,
145                    receivers: vec!["DFA_FUS".to_string()],
146                },
147            ],
148        };
149        let val = test_into::<Message>(def.trim_start(), Rule::message);
150        assert_eq!(val, exp);
151    }
152
153    #[test]
154    fn vector_placeholder_transmitter_test() {
155        let def = "BO_ 1 MCA_A1: 6 Vector__XXX";
156        let val = test_into::<Message>(def, Rule::message);
157        assert_eq!(val.transmitter, None);
158    }
159}