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#[derive(Clone, Debug, PartialEq)]
11#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
12pub struct Message {
13 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 fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
28 let mut pairs = validated_inner(value, Rule::message)?;
29
30 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
61 #[test]
62 fn message_definition_test() {
63 let def = r#"
64BO_ 1 MCA_A1: 6 MFA
65 SG_ ABC_1 : 9|2@1+ (1,0) [0|0] "x" XYZ_OUS
66 SG_ BasL2 : 3|2@0- (1,0) [0|0] "x" DFA_FUS
67"#;
68
69 let exp = Message {
70 id: MessageId::Standard(1),
71 name: "MCA_A1".to_string(),
72 size: 6,
73 transmitter: Transmitter::NodeName("MFA".to_string()),
74 signals: vec![
75 Signal {
76 name: "ABC_1".to_string(),
77 start_bit: 9,
78 size: 2,
79 byte_order: ByteOrder::LittleEndian,
80 value_type: ValueType::Unsigned,
81 factor: 1.0,
82 offset: 0.0,
83 min: 0.0,
84 max: 0.0,
85 unit: "x".to_string(),
86 multiplexer_indicator: MultiplexIndicator::Plain,
87 receivers: vec!["XYZ_OUS".to_string()],
88 },
89 Signal {
90 name: "BasL2".to_string(),
91 start_bit: 3,
92 size: 2,
93 byte_order: ByteOrder::BigEndian,
94 value_type: ValueType::Signed,
95 factor: 1.0,
96 offset: 0.0,
97 min: 0.0,
98 max: 0.0,
99 unit: "x".to_string(),
100 multiplexer_indicator: MultiplexIndicator::Plain,
101 receivers: vec!["DFA_FUS".to_string()],
102 },
103 ],
104 };
105 let val = test_into::<Message>(def.trim_start(), Rule::message);
106 assert_eq!(val, exp);
107 }
108}