rrdbc/ast/
signal.rs

1use std::fmt;
2
3use nom::branch::alt;
4use nom::bytes::complete::tag;
5use nom::character::complete::line_ending;
6use nom::combinator::{map, opt};
7use nom::multi::{many0, separated_list0};
8use nom::sequence::{delimited, pair, separated_pair};
9use nom::{IResult, Parser};
10
11use super::char_string::{parser_char_string, CharString};
12use super::common_parsers::{
13    multispacey, number_value, parser_node_name, parser_signal_name, spacey, unsigned_integer,
14};
15use super::error::DbcParseError;
16
17/// example:
18///
19/// ```text
20/// SG_ S7 m1 : 40|24@1- (1,0) [0|0] "" Vector__XXX
21/// SG_ S8 m2 : 40|8@1- (1,0) [0|0] "" Vector__XXX
22/// SG_ S6 M : 32|8@1- (1,0) [0|0] "" Vector__XXX
23/// SG_ S3 m0 : 16|16@1- (1,0) [0|0] "" Vector__XXX
24/// SG_ S2 m0 : 8|8@1- (1,0) [0|0] "" Vector__XXX
25///
26/// BO_ 100 MuxMsg: 1 Vector__XXX
27///  SG_ Mux_4 m2 : 6|2@1+ (1,0) [0|0] "" Vector__XXX
28///  SG_ Mux_3 m3M : 4|2@1+ (1,0) [0|0] "" Vector__XXX
29///  SG_ Mux_2 m3M : 2|2@1+ (1,0) [0|0] "" Vector__XXX
30///  SG_ Mux_1 M : 0|2@1+ (1,0) [0|0] "" Vector__XXX
31///
32///
33/// SG_MUL_VAL_ 100 Mux_2 Mux_1 3-3, 5-10;
34/// SG_MUL_VAL_ 100 Mux_3 Mux_2 3-3;
35/// SG_MUL_VAL_ 100 Mux_4 Mux_3 2-2;
36/// ```
37#[derive(PartialEq, Debug, Clone)]
38#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
39pub struct MultiplexerIndicator {
40    // A 'm' (lowercase) character followed by an unsigned integer defines the
41    // signal as being multiplexed by the multiplexer switch.
42    pub multiplexer_signal: Option<u32>,
43    // A 'M' (uppercase) character defines the signal as the multiplexer switch
44    pub multiplexer_switch: Option<()>,
45}
46
47impl fmt::Display for MultiplexerIndicator {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        if let Some(multiplexer_signal) = self.multiplexer_signal {
50            write!(f, "m{multiplexer_signal}")?;
51        }
52        if let Some(()) = self.multiplexer_switch {
53            write!(f, "M")?;
54        }
55        Ok(())
56    }
57}
58
59/// Endianness: 1 = little-endian, Intel; 0 = big-endian, Motorola
60#[derive(PartialEq, Debug, Clone)]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub enum ByteOrder {
63    LittleEndian,
64    BigEndian,
65}
66
67impl fmt::Display for ByteOrder {
68    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
69        match self {
70            ByteOrder::LittleEndian => write!(f, "1"),
71            ByteOrder::BigEndian => write!(f, "0"),
72        }
73    }
74}
75
76/// Signed: + = unsigned; - = signed
77#[derive(PartialEq, Debug, Clone)]
78#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
79pub enum ValueType {
80    Signed,
81    Unsigned,
82}
83
84impl fmt::Display for ValueType {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        match self {
87            ValueType::Signed => write!(f, "-"),
88            ValueType::Unsigned => write!(f, "+"),
89        }
90    }
91}
92
93/// The message's signal section lists all signals placed on the message, their position
94/// in the message's data field and their properties.
95///
96/// ```text
97/// signal = 'SG_' signal_name multiplexer_indicator ':' start_bit '|'
98/// signal_size '@' byte_order value_type '(' factor ',' offset ')'
99/// '[' minimum '|' maximum ']' unit receiver {',' receiver} ;
100/// signal_name = DBC_identifier ;
101/// multiplexer_indicator = ' ' | [m multiplexer_switch_value] [M] ;
102/// start_bit = unsigned_integer ;
103/// signal_size = unsigned_integer ;
104/// byte_order = '0' | '1' ; (* 0=big endian, 1=little endian *)
105/// value_type = '+' | '-' ; (* +=unsigned, -=signed *)
106/// factor = double ;
107/// offset = double ;
108/// minimum = double ;
109/// maximum = double ;
110/// unit = char_string ;
111/// receiver = node_name | 'Vector__XXX' ;
112/// ```
113///
114/// Signal definition.
115/// Format: `SG_ <SignalName> [M|m<MultiplexerIdentifier>] : <StartBit>|<Length>@<Endianness><Signed> (<Factor>,<Offset>) [<Min>|<Max>] "[Unit]" [ReceivingNodes]`
116/// Length in bits.
117/// Signed: + = unsigned; - = signed
118/// Endianness: 1 = little-endian, Intel; 0 = big-endian, Motorola
119/// M: If M than this signals contains a multiplexer identifier.
120/// `MultiplexerIdentifier`: Signal definition is only used if the value of the multiplexer signal equals this value.
121#[derive(PartialEq, Debug, Clone)]
122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
123pub struct Signal {
124    pub name: String,
125    pub multiplexer: Option<MultiplexerIndicator>,
126    pub start_bit: u32,
127    pub size: u32,
128    pub byte_order: ByteOrder,
129    pub value_type: ValueType,
130    pub factor: f64,
131    pub offset: f64,
132    pub min: Option<f64>,
133    pub max: Option<f64>,
134    pub unit: Option<CharString>,
135    pub receivers: Option<Vec<String>>,
136}
137
138impl fmt::Display for Signal {
139    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140        let multiplexer = match &self.multiplexer {
141            Some(m) => format!("{m} "),
142            None => String::new(),
143        };
144        let value_type = match &self.value_type {
145            ValueType::Signed => "-",
146            ValueType::Unsigned => "+",
147        };
148        let byte_order = &self.byte_order.to_string();
149        let min_max = match (&self.min, &self.max) {
150            (Some(min), Some(max)) => format!("[{min}|{max}]"),
151            _ => String::new(),
152        };
153        let unit = match &self.unit {
154            Some(u) => format!(r#""{u}""#),
155            None => String::new(),
156        };
157        let mut receivers_str = String::new();
158        if let Some(nodes) = &self.receivers {
159            receivers_str = nodes.join(",");
160        }
161
162        write!(
163            f,
164            "SG_ {} {}: {}|{}@{}{} ({},{}) {} {} {}",
165            self.name,
166            multiplexer,
167            self.start_bit,
168            self.size,
169            byte_order,
170            value_type,
171            self.factor,
172            self.offset,
173            min_max,
174            unit,
175            receivers_str
176        )
177    }
178}
179
180fn parser_signal_multiplexer(input: &str) -> IResult<&str, MultiplexerIndicator, DbcParseError> {
181    map(
182        (opt(pair(tag("m"), unsigned_integer)), opt(tag("M"))),
183        |(multiplexer_signal, multiplexer_switch)| MultiplexerIndicator {
184            multiplexer_signal: multiplexer_signal.map(|(_, num)| num),
185            multiplexer_switch: multiplexer_switch.map(|_| ()),
186        },
187    )
188    .parse(input)
189}
190
191fn parser_signal_multiplexer_option(
192    input: &str,
193) -> IResult<&str, Option<MultiplexerIndicator>, DbcParseError> {
194    let res = parser_signal_multiplexer(input)?;
195    if res.1.multiplexer_signal.is_none() && res.1.multiplexer_switch.is_none() {
196        return Ok((res.0, None));
197    }
198    Ok((res.0, Some(res.1)))
199}
200
201fn parser_signal_start_bit(input: &str) -> IResult<&str, u32, DbcParseError> {
202    unsigned_integer(input)
203}
204
205fn parser_signal_size(input: &str) -> IResult<&str, u32, DbcParseError> {
206    unsigned_integer(input)
207}
208
209fn parser_signal_byte_order(input: &str) -> IResult<&str, ByteOrder, DbcParseError> {
210    alt((
211        map(tag("1"), |_| ByteOrder::LittleEndian),
212        map(tag("0"), |_| ByteOrder::BigEndian),
213    ))
214    .parse(input)
215}
216
217fn parser_signal_value_type(input: &str) -> IResult<&str, ValueType, DbcParseError> {
218    alt((
219        map(tag("+"), |_| ValueType::Unsigned),
220        map(tag("-"), |_| ValueType::Signed),
221    ))
222    .parse(input)
223}
224
225fn parser_signal_factor_offset(input: &str) -> IResult<&str, (f64, f64), DbcParseError> {
226    let (remain, (factor, offset)) = delimited(
227        spacey(tag("(")),
228        separated_pair(number_value, spacey(tag(",")), number_value),
229        spacey(tag(")")),
230    )
231    .parse(input)?;
232
233    Ok((remain, (factor, offset)))
234}
235
236fn parser_signal_min_max(input: &str) -> IResult<&str, (f64, f64), DbcParseError> {
237    let (remain, (min_value, max_value)) = delimited(
238        spacey(tag("[")),
239        separated_pair(number_value, spacey(tag("|")), number_value),
240        spacey(tag("]")),
241    )
242    .parse(input)?;
243
244    Ok((remain, (min_value, max_value)))
245}
246
247fn parser_signal_unit(input: &str) -> IResult<&str, CharString, DbcParseError> {
248    parser_char_string(input)
249}
250
251fn parser_signal_receivers(input: &str) -> IResult<&str, Vec<String>, DbcParseError> {
252    let (remain, nodes) =
253        spacey(separated_list0(tag(","), spacey(parser_node_name))).parse(input)?;
254    Ok((remain, nodes.into_iter().map(String::from).collect()))
255}
256
257pub fn parser_signal(input: &str) -> IResult<&str, Signal, DbcParseError> {
258    let res = map(
259        (
260            multispacey(tag("SG_")),
261            spacey(parser_signal_name),
262            spacey(parser_signal_multiplexer_option),
263            spacey(tag(":")),
264            spacey(parser_signal_start_bit),
265            spacey(tag("|")),
266            spacey(parser_signal_size),
267            spacey(tag("@")),
268            spacey(parser_signal_byte_order),
269            spacey(parser_signal_value_type),
270            spacey(parser_signal_factor_offset),
271            spacey(opt(parser_signal_min_max)),
272            spacey(opt(parser_signal_unit)),
273            spacey(opt(parser_signal_receivers)),
274            many0(line_ending),
275        ),
276        |(
277            _,
278            name,
279            multiplexer,
280            _,
281            start_bit,
282            _,
283            size,
284            _,
285            byte_order,
286            value_type,
287            factor_offset,
288            min_max,
289            unit,
290            receiving_nodes,
291            _,
292        )| Signal {
293            name: String::from(name),
294            multiplexer,
295            start_bit,
296            size,
297            byte_order,
298            value_type,
299            factor: factor_offset.0,
300            offset: factor_offset.1,
301            min: min_max.map(|(min, _)| min),
302            max: min_max.map(|(_, max)| max),
303            unit,
304            receivers: receiving_nodes,
305        },
306    )
307    .parse(input);
308
309    match res {
310        Ok((remain, signal)) => {
311            log::info!("parse signal: {signal:?}");
312            Ok((remain, signal))
313        }
314        Err(e) => {
315            log::trace!("parse signal failed, e = {e:?}");
316            Err(nom::Err::Error(DbcParseError::BadSignal))
317        }
318    }
319}
320
321#[cfg(test)]
322mod tests {
323    use super::*;
324
325    #[test]
326    fn test_dbc_signal_multiplexer_01() {
327        assert_eq!(
328            parser_signal_multiplexer("M"),
329            Ok((
330                "",
331                MultiplexerIndicator {
332                    multiplexer_signal: None,
333                    multiplexer_switch: Some(())
334                }
335            )),
336        );
337    }
338
339    #[test]
340    fn test_dbc_signal_multiplexer_02() {
341        assert_eq!(
342            parser_signal_multiplexer("m0"),
343            Ok((
344                "",
345                MultiplexerIndicator {
346                    multiplexer_signal: Some(0),
347                    multiplexer_switch: None
348                }
349            )),
350        );
351    }
352
353    #[test]
354    fn test_dbc_signal_multiplexer_03() {
355        assert_eq!(
356            parser_signal_multiplexer("m123"),
357            Ok((
358                "",
359                MultiplexerIndicator {
360                    multiplexer_signal: Some(123),
361                    multiplexer_switch: None
362                }
363            )),
364        );
365    }
366
367    #[test]
368    fn test_dbc_signal_multiplexer_04() {
369        assert_eq!(
370            parser_signal_multiplexer("m3M"),
371            Ok((
372                "",
373                MultiplexerIndicator {
374                    multiplexer_signal: Some(3),
375                    multiplexer_switch: Some(())
376                }
377            )),
378        );
379    }
380
381    #[test]
382    fn test_dbc_signal_01() {
383        let ret = parser_signal(
384            r#" SG_ AY1 : 32|16@1+ (0.000127465,-4.1768) [-4.1768|4.1765] "g"  ABS
385
386"#,
387        );
388        match ret {
389            Ok((_remain, signal)) => {
390                assert_eq!(
391                    signal,
392                    Signal {
393                        name: "AY1".into(),
394                        multiplexer: None,
395                        start_bit: 32,
396                        size: 16,
397                        byte_order: ByteOrder::LittleEndian,
398                        value_type: ValueType::Unsigned,
399                        factor: 0.000_127_465,
400                        offset: -4.1768,
401                        min: Some(-4.1768),
402                        max: Some(4.1765),
403                        unit: Some(CharString("g".into())),
404                        receivers: Some(vec!["ABS".into()]),
405                    }
406                );
407            }
408            Err(err) => panic!("err = {err:?}"),
409        }
410    }
411
412    #[test]
413    fn test_dbc_signal_02() {
414        let ret = parser_signal(
415            r#" SG_ S2 m0 : 8|8@1- (1.0,0.0) [0.0|0.0] "" Vector__XXX
416
417"#,
418        );
419
420        match ret {
421            Ok((_remain, signal)) => {
422                assert_eq!(
423                    signal,
424                    Signal {
425                        name: "S2".into(),
426                        multiplexer: Some(MultiplexerIndicator {
427                            multiplexer_signal: Some(0),
428                            multiplexer_switch: None
429                        }),
430                        start_bit: 8,
431                        size: 8,
432                        byte_order: ByteOrder::LittleEndian,
433                        value_type: ValueType::Signed,
434                        factor: 1.0,
435                        offset: 0.0,
436                        min: Some(0.0),
437                        max: Some(0.0),
438                        unit: Some(CharString(String::new())),
439                        receivers: Some(vec!["Vector__XXX".into()]),
440                    }
441                );
442            }
443            Err(err) => panic!("err = {err:?}"),
444        }
445    }
446
447    #[test]
448    fn test_dbc_signal_03() {
449        let ret = parser_signal(
450            r#" SG_ S2 m0 : 8|8@1- (1,0) [0|0] "" Vector__XXX
451
452"#,
453        );
454
455        match ret {
456            Ok((_remain, signal)) => {
457                assert_eq!(
458                    signal,
459                    Signal {
460                        name: "S2".into(),
461                        multiplexer: Some(MultiplexerIndicator {
462                            multiplexer_signal: Some(0),
463                            multiplexer_switch: None
464                        }),
465                        start_bit: 8,
466                        size: 8,
467                        byte_order: ByteOrder::LittleEndian,
468                        value_type: ValueType::Signed,
469                        factor: 1.0,
470                        offset: 0.0,
471                        min: Some(0.0),
472                        max: Some(0.0),
473                        unit: Some(CharString(String::new())),
474                        receivers: Some(vec!["Vector__XXX".into()]),
475                    }
476                );
477            }
478            Err(err) => panic!("err = {err:?}"),
479        }
480    }
481
482    #[test]
483    fn test_dbc_signal_04() {
484        let ret = parser_signal(
485            r#"  SG_ Signal1 : 32|32@1+ (100,0) [0|100] "%"  Node1,Node2
486
487"#,
488        );
489
490        match ret {
491            Ok((_remain, signal)) => {
492                assert_eq!(
493                    signal,
494                    Signal {
495                        name: "Signal1".into(),
496                        multiplexer: None,
497                        start_bit: 32,
498                        size: 32,
499                        byte_order: ByteOrder::LittleEndian,
500                        value_type: ValueType::Unsigned,
501                        factor: 100.0,
502                        offset: 0.0,
503                        min: Some(0.0),
504                        max: Some(100.0),
505                        unit: Some(CharString("%".into())),
506                        receivers: Some(vec!["Node1".into(), "Node2".into()]),
507                    }
508                );
509            }
510            Err(err) => panic!("err = {err:?}"),
511        }
512    }
513}