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 pub version: Version,
20 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
21 pub new_symbols: Vec<Symbol>,
22 pub bit_timing: Option<Vec<Baudrate>>,
24 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
26 pub nodes: Vec<Node>,
27 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
29 pub value_tables: Vec<ValueTable>,
30 #[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 #[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 #[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 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
68 pub value_descriptions: Vec<ValueDescription>,
69 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Vec::is_empty"))]
76 pub signal_type_refs: Vec<SignalTypeRef>,
77 #[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 #[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 #[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 #[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 #[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 #[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 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)] pub(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 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 }
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![], 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![], signal_groups,
412 signal_extended_value_type_list,
413 extended_multiplex,
414 })
415}