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 #[must_use]
253 pub fn message_attribute(&self, message_id: MessageId, name: &str) -> Option<&AttributeValue> {
254 self.attribute_values_message
255 .iter()
256 .find(|a| a.message_id == message_id && a.name == name)
257 .map(|a| &a.value)
258 }
259
260 #[must_use]
262 pub fn signal_attribute(
263 &self,
264 message_id: MessageId,
265 signal_name: &str,
266 name: &str,
267 ) -> Option<&AttributeValue> {
268 self.attribute_values_signal
269 .iter()
270 .find(|a| a.message_id == message_id && a.signal_name == signal_name && a.name == name)
271 .map(|a| &a.value)
272 }
273
274 #[must_use]
276 pub fn attribute_default(&self, name: &str) -> Option<&AttributeValue> {
277 self.attribute_defaults
278 .iter()
279 .find(|d| d.name == name)
280 .map(|d| &d.value)
281 }
282
283 #[must_use]
286 pub fn resolved_message_attribute(
287 &self,
288 message_id: MessageId,
289 name: &str,
290 ) -> Option<&AttributeValue> {
291 self.message_attribute(message_id, name)
292 .or_else(|| self.attribute_default(name))
293 }
294
295 #[must_use]
298 pub fn resolved_signal_attribute(
299 &self,
300 message_id: MessageId,
301 signal_name: &str,
302 name: &str,
303 ) -> Option<&AttributeValue> {
304 self.signal_attribute(message_id, signal_name, name)
305 .or_else(|| self.attribute_default(name))
306 }
307}
308
309impl<'a> TryFrom<&'a str> for Dbc {
310 type Error = DbcError;
311
312 fn try_from(dbc_in: &'a str) -> Result<Self, Self::Error> {
313 dbc(dbc_in)
314 }
315}
316
317#[expect(clippy::too_many_lines)] pub(crate) fn dbc(buffer: &str) -> DbcResult<Dbc> {
319 let mut version = Version::default();
320 let mut new_symbols = vec![];
321 let mut bit_timing = None;
322 let mut nodes = vec![];
323 let mut value_tables = vec![];
324 let mut messages: Vec<Message> = vec![];
325 let mut message_transmitters = vec![];
326 let mut environment_variables = vec![];
327 let mut environment_variable_data = vec![];
328 let mut comments = vec![];
329 let mut attribute_definitions = vec![];
330 let mut relation_attribute_definitions = vec![];
331 let mut attribute_defaults = vec![];
332 let mut relation_attribute_defaults = vec![];
333 let mut attribute_values_database = vec![];
334 let mut attribute_values_node = vec![];
335 let mut attribute_values_message = vec![];
336 let mut attribute_values_signal = vec![];
337 let mut attribute_values_env = vec![];
338 let mut relation_attribute_values = vec![];
339 let mut value_descriptions = vec![];
340 let mut signal_groups = vec![];
341 let mut signal_extended_value_type_list = vec![];
342 let mut extended_multiplex = vec![];
343
344 for pair in DbcParser::parse(Rule::file, buffer)? {
345 if !matches!(pair.as_rule(), Rule::file) {
346 return Err(DbcError::ExpectedRule(Rule::file, pair.as_rule()));
347 }
348 for pairs in pair.into_inner() {
349 match pairs.as_rule() {
350 Rule::version => version = pairs.try_into()?,
351 Rule::new_symbols => {
352 let symbols: Vec<Symbol> = collect_all::<Symbol>(&mut pairs.into_inner())?;
353 new_symbols.extend(symbols);
354 }
355 Rule::bit_timing => {
356 let _inner_pairs = pairs.into_inner();
357 bit_timing = Some(vec![]);
359 }
360 Rule::nodes => nodes = collect_all::<Node>(&mut pairs.into_inner())?,
361 Rule::message => messages.push(pairs.try_into()?),
362 Rule::comment => comments.push(pairs.try_into()?),
363 Rule::attr_def => attribute_definitions.push(pairs.try_into()?),
364 Rule::ba_def_rel => relation_attribute_definitions.push(pairs.try_into()?),
365 Rule::ba_rel => relation_attribute_values.push(pairs.try_into()?),
366 Rule::attr_value => {
367 let attr_value: AttributeValueForObject = pairs.try_into()?;
368 match attr_value.value {
369 AttributeValueForObjectType::Raw(attribute_value) => {
370 attribute_values_database.push(AttributeValueForDatabase {
371 name: attr_value.name,
372 value: attribute_value,
373 });
374 }
375 AttributeValueForObjectType::NetworkNode(node_name, attribute_value) => {
376 attribute_values_node.push(AttributeValueForNode {
377 name: attr_value.name,
378 node_name,
379 value: attribute_value,
380 });
381 }
382 AttributeValueForObjectType::MessageDefinition(
383 message_id,
384 attribute_value,
385 ) => {
386 if let Some(value) = attribute_value {
387 attribute_values_message.push(AttributeValueForMessage {
388 name: attr_value.name,
389 message_id,
390 value,
391 });
392 }
393 }
394 AttributeValueForObjectType::Signal(
395 message_id,
396 signal_name,
397 attribute_value,
398 ) => {
399 attribute_values_signal.push(AttributeValueForSignal {
400 name: attr_value.name,
401 message_id,
402 signal_name,
403 value: attribute_value,
404 });
405 }
406 AttributeValueForObjectType::EnvVariable(
407 variable_name,
408 attribute_value,
409 ) => {
410 attribute_values_env.push(AttributeValueForEnvVariable {
411 name: attr_value.name,
412 variable_name,
413 value: attribute_value,
414 });
415 }
416 }
417 }
418 Rule::value_table => value_tables.push(pairs.try_into()?),
419 Rule::value_table_def => value_descriptions.push(pairs.try_into()?),
420 Rule::signal_group => signal_groups.push(pairs.try_into()?),
421 Rule::signal_value_type => {
422 signal_extended_value_type_list.push(pairs.try_into()?);
423 }
424 Rule::message_transmitter => message_transmitters.push(pairs.try_into()?),
425 Rule::ba_def_def => attribute_defaults.push(pairs.try_into()?),
426 Rule::ba_def_def_rel => relation_attribute_defaults.push(pairs.try_into()?),
427 Rule::sg_mul_val => extended_multiplex.push(pairs.try_into()?),
428 Rule::environment_variable => {
429 environment_variables.push(pairs.try_into()?);
430 }
431 Rule::env_var_data => environment_variable_data.push(pairs.try_into()?),
432 Rule::EOI => {
433 }
435 other => Err(DbcError::UnknownRule(other))?,
436 }
437 }
438 }
439
440 Ok(Dbc {
441 version,
442 new_symbols,
443 bit_timing,
444 nodes,
445 value_tables,
446 messages,
447 message_transmitters,
448 environment_variables,
449 environment_variable_data,
450 signal_types: vec![], comments,
452 attribute_definitions,
453 relation_attribute_definitions,
454 attribute_defaults,
455 relation_attribute_defaults,
456 relation_attribute_values,
457 attribute_values_database,
458 attribute_values_node,
459 attribute_values_message,
460 attribute_values_signal,
461 attribute_values_env,
462 value_descriptions,
463 signal_type_refs: vec![], signal_groups,
465 signal_extended_value_type_list,
466 extended_multiplex,
467 })
468}