1use can_dbc_pest::{Pair, Rule};
2
3use crate::ast::{ByteOrder, MultiplexIndicator, ValueType};
4use crate::parser::{
5 collect_strings, next, next_optional_rule, next_rule, next_string, parse_min_max_float,
6 parse_next_float, parse_next_inner_str, parse_next_uint, validated_inner,
7};
8use crate::DbcError;
9
10#[derive(Clone, Debug, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15pub struct Signal {
16 pub name: String,
17 pub multiplexer_indicator: MultiplexIndicator,
18 pub start_bit: u64,
19 pub size: u64,
20 pub byte_order: ByteOrder,
21 pub value_type: ValueType,
22 pub factor: f64,
23 pub offset: f64,
24 pub min: f64,
25 pub max: f64,
26 pub unit: String,
27 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
28 pub receivers: Vec<String>,
29}
30
31impl TryFrom<Pair<'_, Rule>> for Signal {
33 type Error = DbcError;
34
35 fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
36 let mut pairs = validated_inner(value, Rule::signal)?;
37
38 next_rule(&mut pairs, Rule::signal_nl_ident)?; let name = next_string(&mut pairs, Rule::signal_name)?;
40 let multiplexer_indicator =
41 if let Some(v) = next_optional_rule(&mut pairs, Rule::multiplexer_indicator) {
42 v.as_str().try_into()?
43 } else {
44 MultiplexIndicator::Plain
45 };
46 let start_bit = parse_next_uint(&mut pairs, Rule::start_bit)?;
47 let size = parse_next_uint(&mut pairs, Rule::signal_size)?;
48 let byte_order = next(&mut pairs)?.try_into()?;
49 let value_type = next(&mut pairs)?.try_into()?;
50 let factor = parse_next_float(&mut pairs, Rule::factor)?;
51 let offset = parse_next_float(&mut pairs, Rule::offset)?;
52 let (min, max) = parse_min_max_float(next_rule(&mut pairs, Rule::min_max)?)?;
53 let unit = parse_next_inner_str(&mut pairs, Rule::unit)?;
54 let receivers = collect_strings(&mut pairs, Rule::node_name)?;
55
56 Ok(Self {
57 name,
58 multiplexer_indicator,
59 start_bit,
60 size,
61 byte_order,
62 value_type,
63 factor,
64 offset,
65 min,
66 max,
67 unit,
68 receivers,
69 })
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76 use crate::test_helpers::*;
77
78 #[test]
79 fn signal_test() {
80 let def = r#"
81 SG_ NAME : 3|2@1- (1,0) [0|0] "x" UFA
82"#;
83
84 let exp = Signal {
85 name: "NAME".to_string(),
86 start_bit: 3,
87 size: 2,
88 byte_order: ByteOrder::LittleEndian,
89 value_type: ValueType::Signed,
90 factor: 1.0,
91 offset: 0.0,
92 min: 0.0,
93 max: 0.0,
94 unit: "x".to_string(),
95 multiplexer_indicator: MultiplexIndicator::Plain,
96 receivers: vec!["UFA".to_string()],
97 };
98 let val = test_into::<Signal>(def, Rule::signal);
99 assert_eq!(val, exp);
100 }
101
102 #[test]
103 fn signal_definition_test() {
104 let def = "\r\n \r\n SG_ BasL2 : 3|2@0- (1,0) [0|0] \"x\" DFA_FUS\r\n";
106
107 let exp = Signal {
108 name: "BasL2".to_string(),
109 start_bit: 3,
110 size: 2,
111 byte_order: ByteOrder::BigEndian,
112 value_type: ValueType::Signed,
113 factor: 1.0,
114 offset: 0.0,
115 min: 0.0,
116 max: 0.0,
117 unit: "x".to_string(),
118 multiplexer_indicator: MultiplexIndicator::Plain,
119 receivers: vec!["DFA_FUS".to_string()],
120 };
121 let val = test_into::<Signal>(def, Rule::signal);
122 assert_eq!(val, exp);
123 }
124}