can_dbc/ast/
dbc.rs

1use std::str;
2
3use can_dbc_pest::{DbcParser, Parser as _, Rule};
4
5use crate::ast::{
6    AttributeDefault, AttributeDefinition, AttributeValueForObject, Baudrate, Comment,
7    EnvironmentVariable, EnvironmentVariableData, ExtendedMultiplex, Message, MessageId,
8    MessageTransmitter, MultiplexIndicator, Node, Signal, SignalExtendedValueType,
9    SignalExtendedValueTypeList, SignalGroups, SignalType, SignalTypeRef, Symbol, ValDescription,
10    ValueDescription, ValueTable, Version,
11};
12use crate::parser::{collect_all, DbcError, DbcResult};
13use crate::{AttributeValue, AttributeValueForObjectType, AttributeValueForRelation};
14
15#[derive(Clone, Debug, PartialEq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub struct Dbc {
18    /// Version generated by DB editor
19    pub version: Version,
20    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
21    pub new_symbols: Vec<Symbol>,
22    /// Baud rate of network
23    pub bit_timing: Option<Vec<Baudrate>>,
24    /// CAN network nodes
25    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
26    pub nodes: Vec<Node>,
27    /// Global value table
28    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
29    pub value_tables: Vec<ValueTable>,
30    /// CAN message (frame) details including signal details
31    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
32    pub messages: Vec<Message>,
33    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
34    pub message_transmitters: Vec<MessageTransmitter>,
35    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
36    pub environment_variables: Vec<EnvironmentVariable>,
37    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
38    pub environment_variable_data: Vec<EnvironmentVariableData>,
39    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
40    pub signal_types: Vec<SignalType>,
41    /// Object comments
42    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
43    pub comments: Vec<Comment>,
44    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
45    pub attribute_definitions: Vec<AttributeDefinition>,
46    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
47    pub relation_attribute_definitions: Vec<AttributeDefinition>,
48    // undefined
49    // sigtype_attr_list: SigtypeAttrList,
50    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
51    pub attribute_defaults: Vec<AttributeDefault>,
52    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
53    pub relation_attribute_defaults: Vec<AttributeDefault>,
54    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
55    pub relation_attribute_values: Vec<AttributeValueForRelation>,
56    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
57    pub attribute_values_database: Vec<AttributeValueForDatabase>,
58    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
59    pub attribute_values_node: Vec<AttributeValueForNode>,
60    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
61    pub attribute_values_message: Vec<AttributeValueForMessage>,
62    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
63    pub attribute_values_signal: Vec<AttributeValueForSignal>,
64    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
65    pub attribute_values_env: Vec<AttributeValueForEnvVariable>,
66    /// Encoding for signal raw values
67    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
68    pub value_descriptions: Vec<ValueDescription>,
69    // obsolete + undefined
70    // category_definitions: Vec<CategoryDefinition>,
71    // obsolete + undefined
72    //categories: Vec<Category>,
73    // obsolete + undefined
74    //filter: Vec<Filter>,
75    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
76    pub signal_type_refs: Vec<SignalTypeRef>,
77    /// Signal groups define a group of signals within a message
78    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
79    pub signal_groups: Vec<SignalGroups>,
80    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
81    pub signal_extended_value_type_list: Vec<SignalExtendedValueTypeList>,
82    /// Extended multiplex attributes
83    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
84    pub extended_multiplex: Vec<ExtendedMultiplex>,
85}
86
87#[derive(Clone, Debug, PartialEq)]
88#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
89pub struct AttributeValueForDatabase {
90    pub name: String,
91    pub value: AttributeValue,
92}
93
94#[derive(Clone, Debug, PartialEq)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub struct AttributeValueForNode {
97    pub name: String,
98    pub node_name: String,
99    pub value: AttributeValue,
100}
101
102#[derive(Clone, Debug, PartialEq)]
103#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
104pub struct AttributeValueForMessage {
105    pub name: String,
106    pub message_id: MessageId,
107    pub value: AttributeValue,
108}
109
110#[derive(Clone, Debug, PartialEq)]
111#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
112pub struct AttributeValueForSignal {
113    pub name: String,
114    pub message_id: MessageId,
115    pub signal_name: String,
116    pub value: AttributeValue,
117}
118
119#[derive(Clone, Debug, PartialEq)]
120#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
121pub struct AttributeValueForEnvVariable {
122    pub name: String,
123    pub variable_name: String,
124    pub value: AttributeValue,
125}
126
127impl Dbc {
128    #[must_use]
129    pub fn signal_by_name(&self, message_id: MessageId, signal_name: &str) -> Option<&Signal> {
130        let message = self
131            .messages
132            .iter()
133            .find(|message| message.id == message_id);
134
135        if let Some(message) = message {
136            return message
137                .signals
138                .iter()
139                .find(|signal| signal.name == *signal_name);
140        }
141        None
142    }
143
144    /// Lookup a message comment
145    #[must_use]
146    pub fn message_comment(&self, message_id: MessageId) -> Option<&str> {
147        self.comments.iter().find_map(|x| match x {
148            Comment::Message {
149                id: ref x_message_id,
150                ref comment,
151            } => {
152                if *x_message_id == message_id {
153                    Some(comment.as_str())
154                } else {
155                    None
156                }
157            }
158            _ => None,
159        })
160    }
161
162    /// Lookup a signal comment
163    #[must_use]
164    pub fn signal_comment(&self, message_id: MessageId, signal_name: &str) -> Option<&str> {
165        self.comments.iter().find_map(|x| match x {
166            Comment::Signal {
167                message_id: ref x_message_id,
168                name: ref x_signal_name,
169                comment,
170            } => {
171                if *x_message_id == message_id && x_signal_name == signal_name {
172                    Some(comment.as_str())
173                } else {
174                    None
175                }
176            }
177            _ => None,
178        })
179    }
180
181    /// Lookup value descriptions for signal
182    #[must_use]
183    pub fn value_descriptions_for_signal(
184        &self,
185        message_id: MessageId,
186        signal_name: &str,
187    ) -> Option<&[ValDescription]> {
188        self.value_descriptions.iter().find_map(|x| match x {
189            ValueDescription::Signal {
190                message_id: ref x_message_id,
191                name: ref x_signal_name,
192                ref value_descriptions,
193            } => {
194                if *x_message_id == message_id && x_signal_name == signal_name {
195                    Some(value_descriptions.as_slice())
196                } else {
197                    None
198                }
199            }
200            ValueDescription::EnvironmentVariable { .. } => None,
201        })
202    }
203
204    /// Lookup the extended value for a given signal
205    #[must_use]
206    pub fn extended_value_type_for_signal(
207        &self,
208        message_id: MessageId,
209        signal_name: &str,
210    ) -> Option<&SignalExtendedValueType> {
211        self.signal_extended_value_type_list.iter().find_map(|x| {
212            let SignalExtendedValueTypeList {
213                message_id: ref x_message_id,
214                signal_name: ref x_signal_name,
215                ref signal_extended_value_type,
216            } = x;
217            if *x_message_id == message_id && x_signal_name == signal_name {
218                Some(signal_extended_value_type)
219            } else {
220                None
221            }
222        })
223    }
224
225    /// Lookup the message multiplexer switch signal for a given message
226    /// This does not work for extended multiplexed messages, if multiple multiplexors are defined for a message an Error is returned.
227    pub fn message_multiplexor_switch(&self, message_id: MessageId) -> DbcResult<Option<&Signal>> {
228        let message = self
229            .messages
230            .iter()
231            .find(|message| message.id == message_id);
232
233        if let Some(message) = message {
234            if self
235                .extended_multiplex
236                .iter()
237                .any(|ext_mp| ext_mp.message_id == message_id)
238            {
239                Err(DbcError::MultipleMultiplexors)
240            } else {
241                Ok(message
242                    .signals
243                    .iter()
244                    .find(|signal| signal.multiplexer_indicator == MultiplexIndicator::Multiplexor))
245            }
246        } else {
247            Ok(None)
248        }
249    }
250}
251
252impl<'a> TryFrom<&'a str> for Dbc {
253    type Error = DbcError;
254
255    fn try_from(dbc_in: &'a str) -> Result<Self, Self::Error> {
256        dbc(dbc_in)
257    }
258}
259
260#[allow(clippy::too_many_lines)] // FIXME: refactor
261pub(crate) fn dbc(buffer: &str) -> DbcResult<Dbc> {
262    let mut version = Version::default();
263    let mut new_symbols = vec![];
264    let mut bit_timing = None;
265    let mut nodes = vec![];
266    let mut value_tables = vec![];
267    let mut messages: Vec<Message> = vec![];
268    let mut message_transmitters = vec![];
269    let mut environment_variables = vec![];
270    let mut environment_variable_data = vec![];
271    let mut comments = vec![];
272    let mut attribute_definitions = vec![];
273    let mut relation_attribute_definitions = vec![];
274    let mut attribute_defaults = vec![];
275    let mut relation_attribute_defaults = vec![];
276    let mut attribute_values_database = vec![];
277    let mut attribute_values_node = vec![];
278    let mut attribute_values_message = vec![];
279    let mut attribute_values_signal = vec![];
280    let mut attribute_values_env = vec![];
281    let mut relation_attribute_values = vec![];
282    let mut value_descriptions = vec![];
283    let mut signal_groups = vec![];
284    let mut signal_extended_value_type_list = vec![];
285    let mut extended_multiplex = vec![];
286
287    for pair in DbcParser::parse(Rule::file, buffer)? {
288        if !matches!(pair.as_rule(), Rule::file) {
289            return Err(DbcError::ExpectedRule(Rule::file, pair.as_rule()));
290        }
291        for pairs in pair.into_inner() {
292            match pairs.as_rule() {
293                Rule::version => version = pairs.try_into()?,
294                Rule::new_symbols => {
295                    let symbols: Vec<Symbol> = collect_all::<Symbol>(&mut pairs.into_inner())?;
296                    new_symbols.extend(symbols);
297                }
298                Rule::bit_timing => {
299                    let inner_pairs = pairs.into_inner();
300                    if inner_pairs.len() == 0 {
301                        bit_timing = Some(vec![]);
302                    } else {
303                        // For now, just return empty vec since bit-timing parsing is not implemented
304                        bit_timing = Some(vec![]);
305                    }
306                }
307                Rule::nodes => nodes = collect_all::<Node>(&mut pairs.into_inner())?,
308                Rule::message => messages.push(pairs.try_into()?),
309                Rule::comment => comments.push(pairs.try_into()?),
310                Rule::attr_def => attribute_definitions.push(pairs.try_into()?),
311                Rule::ba_def_rel => relation_attribute_definitions.push(pairs.try_into()?),
312                Rule::ba_rel => relation_attribute_values.push(pairs.try_into()?),
313                Rule::attr_value => {
314                    let attr_value: AttributeValueForObject = pairs.try_into()?;
315                    match attr_value.value {
316                        AttributeValueForObjectType::Raw(attribute_value) => {
317                            attribute_values_database.push(AttributeValueForDatabase {
318                                name: attr_value.name,
319                                value: attribute_value,
320                            });
321                        }
322                        AttributeValueForObjectType::NetworkNode(node_name, attribute_value) => {
323                            attribute_values_node.push(AttributeValueForNode {
324                                name: attr_value.name,
325                                node_name,
326                                value: attribute_value,
327                            });
328                        }
329                        AttributeValueForObjectType::MessageDefinition(
330                            message_id,
331                            attribute_value,
332                        ) => {
333                            if let Some(value) = attribute_value {
334                                attribute_values_message.push(AttributeValueForMessage {
335                                    name: attr_value.name,
336                                    message_id,
337                                    value,
338                                });
339                            }
340                        }
341                        AttributeValueForObjectType::Signal(
342                            message_id,
343                            signal_name,
344                            attribute_value,
345                        ) => {
346                            attribute_values_signal.push(AttributeValueForSignal {
347                                name: attr_value.name,
348                                message_id,
349                                signal_name,
350                                value: attribute_value,
351                            });
352                        }
353                        AttributeValueForObjectType::EnvVariable(
354                            variable_name,
355                            attribute_value,
356                        ) => {
357                            attribute_values_env.push(AttributeValueForEnvVariable {
358                                name: attr_value.name,
359                                variable_name,
360                                value: attribute_value,
361                            });
362                        }
363                    }
364                }
365                Rule::value_table => value_tables.push(pairs.try_into()?),
366                Rule::value_table_def => value_descriptions.push(pairs.try_into()?),
367                Rule::signal_group => signal_groups.push(pairs.try_into()?),
368                Rule::signal_value_type => {
369                    signal_extended_value_type_list.push(pairs.try_into()?);
370                }
371                Rule::message_transmitter => message_transmitters.push(pairs.try_into()?),
372                Rule::ba_def_def => attribute_defaults.push(pairs.try_into()?),
373                Rule::ba_def_def_rel => relation_attribute_defaults.push(pairs.try_into()?),
374                Rule::sg_mul_val => extended_multiplex.push(pairs.try_into()?),
375                Rule::environment_variable => {
376                    environment_variables.push(pairs.try_into()?);
377                }
378                Rule::env_var_data => environment_variable_data.push(pairs.try_into()?),
379                Rule::EOI => {
380                    // ignore
381                }
382                other => panic!("Unexpected rule in DBC file: {other:?}"),
383            }
384        }
385    }
386
387    Ok(Dbc {
388        version,
389        new_symbols,
390        bit_timing,
391        nodes,
392        value_tables,
393        messages,
394        message_transmitters,
395        environment_variables,
396        environment_variable_data,
397        signal_types: vec![], // TODO
398        comments,
399        attribute_definitions,
400        relation_attribute_definitions,
401        attribute_defaults,
402        relation_attribute_defaults,
403        relation_attribute_values,
404        attribute_values_database,
405        attribute_values_node,
406        attribute_values_message,
407        attribute_values_signal,
408        attribute_values_env,
409        value_descriptions,
410        signal_type_refs: vec![], // TODO
411        signal_groups,
412        signal_extended_value_type_list,
413        extended_multiplex,
414    })
415}