Skip to main content

can_dbc/ast/
message.rs

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