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#[derive(Clone, Debug, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Message {
14 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 fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
29 let mut pairs = validated_inner(value, Rule::message)?;
30
31 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}