can-dbc 9.0.0

A parser for the DBC format. The DBC format is used to exchange CAN network data.
Documentation
use can_dbc_pest::{Pair, Rule};

use crate::ast::MessageId;
use crate::parser::{
    collect_strings, expect_empty, next_rule, next_string, parse_next_uint, validated_inner,
    DbcError,
};

/// Signal groups define a group of signals within a message
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SignalGroups {
    pub message_id: MessageId,
    pub name: String,
    pub repetitions: u64,
    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
    pub signal_names: Vec<String>,
}

impl TryFrom<Pair<'_, Rule>> for SignalGroups {
    type Error = DbcError;

    /// Parse signal group: `SIG_GROUP_ message_id group_name multiplexer_id : signal1 signal2 ... ;`
    fn try_from(value: Pair<'_, Rule>) -> Result<Self, Self::Error> {
        let mut pairs = validated_inner(value, Rule::signal_group)?;

        let value = Self {
            message_id: next_rule(&mut pairs, Rule::message_id)?.try_into()?,
            name: next_string(&mut pairs, Rule::group_name)?,
            repetitions: parse_next_uint(&mut pairs, Rule::multiplexer_id)?,
            signal_names: collect_strings(&mut pairs, Rule::signal_name)?,
        };
        expect_empty(&pairs)?;

        Ok(value)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_helpers::*;

    #[test]
    fn signal_groups_test() {
        let def = "
SIG_GROUP_ 23 X_3290 1 : A_b XY_Z;
";
        let exp = SignalGroups {
            message_id: MessageId::Standard(23),
            name: "X_3290".to_string(),
            repetitions: 1,
            signal_names: vec!["A_b".to_string(), "XY_Z".to_string()],
        };
        let val = test_into::<SignalGroups>(def.trim_start(), Rule::signal_group);
        assert_eq!(val, exp);
    }
}