1#![deny(missing_docs)]
2#![deny(clippy::arithmetic_side_effects)]
3#![allow(clippy::needless_doctest_main)]
4#![cfg_attr(feature = "std", doc = include_str!("../README.md"))]
5#![cfg_attr(
6 not(feature = "std"),
7 doc = "Documentation is only available with the `std` feature."
8)]
9
10mod feature_config;
11mod keywords;
12mod pad;
13mod signal_type;
14mod utils;
15
16use std::collections::{BTreeMap, BTreeSet, HashMap};
17use std::fs::OpenOptions;
18use std::io::{BufWriter, Write};
19use std::path::Path;
20
21use anyhow::{Context, Error, Result, anyhow, ensure};
22use can_dbc::ByteOrder::{BigEndian, LittleEndian};
23use can_dbc::MultiplexIndicator::{
24 MultiplexedSignal, Multiplexor, MultiplexorAndMultiplexedSignal, Plain,
25};
26use can_dbc::ValueType::Signed;
27use can_dbc::{
28 AttributeValue, AttributeValueForRelationType, Dbc, Message, MessageId, Signal, ValDescription,
29 ValueDescription,
30};
31use heck::ToSnakeCase;
32use quote::ToTokens;
33use typed_builder::TypedBuilder;
34
35pub use crate::feature_config::FeatureConfig;
36use crate::pad::PadAdapter;
37use crate::signal_type::{IntSize, ValType};
38use crate::utils::{
39 MessageExt as _, SignalExt as _, enum_name, enum_variant_name, is_screaming_snake_case,
40 is_valid_ident, is_valid_type_path, multiplex_enum_name, multiplexed_enum_variant_name,
41 multiplexed_enum_variant_wrapper_name, node_field_name,
42};
43
44static ALLOW_DEADCODE: &str = "#[allow(dead_code)]";
45static ALLOW_LINTS: &str = r"#[allow(
46 clippy::absurd_extreme_comparisons,
47 clippy::excessive_precision,
48 clippy::manual_range_contains,
49 clippy::unnecessary_cast,
50 clippy::useless_conversion,
51 unused_comparisons,
52 unused_variables,
53)]";
54
55#[derive(TypedBuilder)]
57#[non_exhaustive]
58pub struct Config<'a> {
59 pub dbc_name: &'a str,
61
62 pub dbc_content: &'a str,
64
65 #[builder(default)]
67 pub debug_prints: bool,
68
69 #[builder(default)]
71 pub impl_debug: FeatureConfig<'a>,
72
73 #[builder(default)]
75 pub impl_defmt: FeatureConfig<'a>,
76
77 #[builder(default)]
79 pub impl_arbitrary: FeatureConfig<'a>,
80
81 #[builder(default)]
83 pub impl_serde: FeatureConfig<'a>,
84
85 #[builder(default)]
87 pub impl_error: FeatureConfig<'a>,
88
89 #[builder(default = FeatureConfig::Always)]
91 pub impl_embedded_can_frame: FeatureConfig<'a>,
92
93 #[builder(default = FeatureConfig::Always)]
95 pub check_ranges: FeatureConfig<'a>,
96
97 #[builder(default)]
99 pub allow_dead_code: bool,
100
101 #[builder(default)]
103 pub padding_bit_value: bool,
104
105 #[builder(default)]
109 pub attribute_structs: &'a [AttributeStruct<'a>],
110}
111
112#[derive(Debug, Clone)]
115pub struct AttributeStruct<'a> {
116 pub type_path: &'a str,
118
119 pub const_name: &'a str,
121
122 pub scope: AttributeScope,
124
125 pub require: &'a str,
129
130 pub fields: &'a [AttributeField<'a>],
132
133 pub for_node: Option<&'a str>,
138}
139
140#[derive(Debug, Clone, Copy)]
142#[non_exhaustive]
143pub enum AttributeScope {
144 Message,
146 Signal,
148 NodeMessage,
150 NodeSignal,
152}
153
154#[derive(Debug, Clone)]
156pub struct AttributeField<'a> {
157 pub name: &'a str,
159 pub source: FieldSource<'a>,
161}
162
163#[derive(Debug, Clone)]
165#[non_exhaustive]
166pub enum FieldSource<'a> {
167 Attr(&'a str),
171 MessageAttr(&'a str),
173 StartBit,
175 StartByte,
177 BitWidth,
179 MessageSize,
181 Int(i64),
183 Str(&'a str),
185 NodeName,
188}
189
190struct AttrTarget<'a> {
192 msg: &'a Message,
193 dbc: &'a Dbc,
194 signal: Option<&'a Signal>,
195 node: Option<&'a str>,
196}
197
198impl Config<'_> {
199 fn codegen(&self, out: impl Write) -> Result<()> {
201 self.validate_attribute_structs()?;
202 let dbc = Dbc::try_from(self.dbc_content).map_err(|e| {
203 let msg = "Could not parse dbc file";
204 if self.debug_prints {
205 anyhow!("{msg}: {e:#?}")
206 } else {
207 anyhow!("{msg}")
208 }
209 })?;
210 if self.debug_prints {
211 eprintln!("{dbc:#?}");
212 }
213 let mut w = BufWriter::new(out);
214
215 writeln!(
216 w,
217 "/// The name of the DBC file this code was generated from"
218 )?;
219 writeln!(w, "#[allow(dead_code)]")?;
220 let dbc_name = self.dbc_name.to_token_stream();
221 writeln!(w, "pub const DBC_FILE_NAME: &str = {dbc_name};")?;
222 writeln!(
223 w,
224 "/// The version of the DBC file this code was generated from"
225 )?;
226 writeln!(w, "#[allow(dead_code)]")?;
227 let dbc_version = dbc.version.0.to_token_stream();
228 writeln!(w, "pub const DBC_FILE_VERSION: &str = {dbc_version};")?;
229
230 writeln!(w, "#[allow(unused_imports)]")?;
231 writeln!(w, "use core::ops::BitOr;")?;
232 writeln!(w, "#[allow(unused_imports)]")?;
233 writeln!(w, "use bitvec::prelude::*;")?;
234 writeln!(w, "#[allow(unused_imports)]")?;
235 writeln!(w, "use embedded_can::{{Id, StandardId, ExtendedId}};")?;
236
237 self.impl_arbitrary.fmt_cfg(&mut w, |w| {
238 writeln!(w, "use arbitrary::{{Arbitrary, Unstructured}};")
239 })?;
240
241 self.impl_serde.fmt_cfg(&mut w, |w| {
242 writeln!(w, "use serde::{{Serialize, Deserialize}};")
243 })?;
244
245 writeln!(w)?;
246 self.render_dbc(&mut w, &dbc)?;
247 writeln!(w)?;
248 self.render_error(&mut w)?;
249 self.render_arbitrary_helpers(&mut w)?;
250 writeln!(w)?;
251
252 Ok(())
253 }
254
255 fn render_dbc(&self, w: &mut impl Write, dbc: &Dbc) -> Result<()> {
256 self.render_root_enum(w, dbc)?;
257
258 for msg in get_relevant_messages(dbc) {
259 self.render_message(w, msg, dbc)
260 .with_context(|| format!("write message `{}`", msg.name))?;
261 writeln!(w)?;
262 }
263
264 Ok(())
265 }
266
267 fn render_root_enum(&self, w: &mut impl Write, dbc: &Dbc) -> Result<()> {
268 writeln!(w, "/// All messages")?;
269 writeln!(w, "{ALLOW_LINTS}")?;
270 self.write_allow_dead_code(w)?;
271 writeln!(w, "#[derive(Clone)]")?;
272 self.impl_debug.fmt_attr(w, "derive(Debug)")?;
273 self.impl_defmt.fmt_attr(w, "derive(defmt::Format)")?;
274 self.impl_serde.fmt_attr(w, "derive(Serialize)")?;
275 self.impl_serde.fmt_attr(w, "derive(Deserialize)")?;
276 writeln!(w, "pub enum Messages {{")?;
277 {
278 let mut w = PadAdapter::wrap(w);
279 for msg in get_relevant_messages(dbc) {
280 writeln!(w, "/// {}", msg.name)?;
281 writeln!(w, "{0}({0}),", msg.type_name())?;
282 }
283 }
284 writeln!(w, "}}")?;
285 writeln!(w)?;
286
287 writeln!(w, "{ALLOW_LINTS}")?;
288 self.write_allow_dead_code(w)?;
289 writeln!(w, "impl Messages {{")?;
290 {
291 let mut w = PadAdapter::wrap(w);
292 writeln!(w, "/// Read message from CAN frame")?;
293 writeln!(w, "#[inline(never)]")?;
294 writeln!(
295 w,
296 "pub fn from_can_message(id: Id, payload: &[u8]) -> Result<Self, CanError> {{",
297 )?;
298
299 {
300 let mut w = PadAdapter::wrap(&mut w);
301 let messages: Vec<_> = get_relevant_messages(dbc).collect();
302 if messages.is_empty() {
303 writeln!(w, "Err(CanError::UnknownMessageId(id))")?;
304 } else {
305 writeln!(w)?;
306 writeln!(w, "let res = match id {{")?;
307 {
308 let mut w = PadAdapter::wrap(&mut w);
309 for msg in messages {
310 writeln!(
311 w,
312 "{0}::MESSAGE_ID => Messages::{0}({0}::try_from(payload)?),",
313 msg.type_name(),
314 )?;
315 }
316 writeln!(w, r"id => return Err(CanError::UnknownMessageId(id)),")?;
317 }
318 writeln!(w, "}};")?;
319 writeln!(w, "Ok(res)")?;
320 }
321 }
322
323 writeln!(w, "}}")?;
324 }
325 writeln!(w, "}}")?;
326 writeln!(w)?;
327
328 Ok(())
329 }
330
331 fn render_message(&self, w: &mut impl Write, msg: &Message, dbc: &Dbc) -> Result<()> {
332 writeln!(w, "/// {}", msg.name)?;
333 writeln!(w, "///")?;
334 match msg.id {
335 MessageId::Standard(id) => writeln!(w, "/// - Standard ID: {id} (0x{id:x})"),
336 MessageId::Extended(id) => writeln!(w, "/// - Extended ID: {id} (0x{id:x})"),
337 }?;
338 writeln!(w, "/// - Size: {} bytes", msg.size)?;
339 if let Some(transmitter) = &msg.transmitter {
340 writeln!(w, "/// - Transmitter: {transmitter}")?;
341 }
342 if let Some(comment) = dbc.message_comment(msg.id) {
343 writeln!(w, "///")?;
344 for line in comment.trim().lines() {
345 writeln!(w, "/// {line}")?;
346 }
347 }
348 writeln!(w, "#[derive(Clone, Copy)]")?;
349 self.impl_serde.fmt_attr(w, "derive(Serialize)")?;
350 self.impl_serde.fmt_attr(w, "derive(Deserialize)")?;
351 writeln!(w, "pub struct {} {{", msg.type_name())?;
352 {
353 let mut w = PadAdapter::wrap(w);
354 self.impl_serde
355 .fmt_attr(&mut w, "serde(with = \"serde_bytes\")")?;
356 writeln!(w, "raw: [u8; {}],", msg.size)?;
357 }
358 writeln!(w, "}}")?;
359 writeln!(w)?;
360
361 writeln!(w, "{ALLOW_LINTS}")?;
362 self.write_allow_dead_code(w)?;
363 writeln!(w, "impl {} {{", msg.type_name())?;
364 {
365 let mut w = PadAdapter::wrap(w);
366
367 writeln!(
368 w,
369 "pub const MESSAGE_ID: embedded_can::Id = {};",
370 match msg.id {
371 MessageId::Standard(id) =>
372 format!("Id::Standard(StandardId::new({id:#x}).unwrap())"),
373 MessageId::Extended(id) =>
374 format!("Id::Extended(ExtendedId::new({id:#x}).unwrap())"),
375 }
376 )?;
377 writeln!(w)?;
378
379 writeln!(w, "pub const MESSAGE_SIZE: usize = {};", msg.size)?;
380 writeln!(w)?;
381
382 Self::render_cycle_time(&mut w, msg, dbc)?;
383
384 for signal in &msg.signals {
385 let typ = ValType::from_signal(signal);
386 if typ != ValType::Bool {
387 let sig = signal.field_name().to_uppercase();
388 let min = signal.min;
389 let max = signal.max;
390 writeln!(w, "pub const {sig}_MIN: {typ} = {min}_{typ};")?;
391 writeln!(w, "pub const {sig}_MAX: {typ} = {max}_{typ};")?;
392 }
393 }
394 writeln!(w)?;
395
396 self.render_attribute_structs(&mut w, msg, dbc)?;
397
398 writeln!(
399 w,
400 "/// Constructs a new `{}` message from values.",
401 msg.name
402 )?;
403 let args = msg
404 .signals
405 .iter()
406 .filter_map(|signal| {
407 if matches!(signal.multiplexer_indicator, Plain | Multiplexor) {
408 let field = signal.field_name();
409 let typ = signal_pub_type(dbc, msg, signal);
410 Some(format!("{field}: {typ}"))
411 } else {
412 None
413 }
414 })
415 .collect::<Vec<_>>()
416 .join(", ");
417 writeln!(w, "pub fn new({args}) -> Result<Self, CanError> {{")?;
418 {
419 let mut w = PadAdapter::wrap(&mut w);
420 let mutable = if msg.signals.is_empty() { "" } else { "mut " };
421 let padding_value = if self.padding_bit_value {
422 "0xFF"
423 } else {
424 "0x00"
425 };
426 let size = msg.size;
427 writeln!(
428 w,
429 "let {mutable}res = Self {{ raw: [{padding_value}; {size}] }};"
430 )?;
431 for signal in &msg.signals {
432 if matches!(signal.multiplexer_indicator, Plain | Multiplexor) {
433 writeln!(w, "res.set_{0}({0})?;", signal.field_name())?;
434 }
435 }
436 writeln!(w, "Ok(res)")?;
437 }
438 writeln!(w, "}}")?;
439 writeln!(w)?;
440
441 writeln!(w, "/// Returns the raw `{}` message payload.", msg.name)?;
442 writeln!(w, "pub fn raw(&self) -> &[u8; {}] {{", msg.size)?;
443 {
444 let mut w = PadAdapter::wrap(&mut w);
445 writeln!(w, "&self.raw")?;
446 }
447 writeln!(w, "}}")?;
448 writeln!(w)?;
449
450 for signal in &msg.signals {
451 match signal.multiplexer_indicator {
452 Plain => self
453 .render_signal(&mut w, signal, dbc, msg)
454 .with_context(|| format!("write signal impl `{}`", signal.name))?,
455 Multiplexor => {
456 self.render_multiplexor_signal(&mut w, signal, dbc, msg)?;
457 }
458 MultiplexedSignal(_) | MultiplexorAndMultiplexedSignal(_) => {}
459 }
460 }
461 }
462
463 writeln!(w, "}}")?;
464 writeln!(w)?;
465
466 let typ = msg.type_name();
467 writeln!(w, "impl core::convert::TryFrom<&[u8]> for {typ} {{")?;
468 {
469 let mut w = PadAdapter::wrap(w);
470 writeln!(w, "type Error = CanError;")?;
471 writeln!(w)?;
472 writeln!(w, "#[inline(always)]")?;
473 writeln!(
474 w,
475 "fn try_from(payload: &[u8]) -> Result<Self, Self::Error> {{",
476 )?;
477 {
478 let mut w = PadAdapter::wrap(&mut w);
479 writeln!(
480 w,
481 r"if payload.len() != {} {{ return Err(CanError::InvalidPayloadSize); }}",
482 msg.size,
483 )?;
484 writeln!(w, "let mut raw = [0u8; {}];", msg.size)?;
485 writeln!(w, "raw.copy_from_slice(&payload[..{}]);", msg.size)?;
486 writeln!(w, "Ok(Self {{ raw }})")?;
487 }
488 writeln!(w, "}}")?;
489 }
490 writeln!(w, "}}")?;
491 writeln!(w)?;
492
493 self.render_embedded_can_frame(w, msg)?;
494
495 self.impl_debug
496 .fmt_cfg(&mut *w, |w| render_debug_impl(w, msg))?;
497 self.impl_defmt
498 .fmt_cfg(&mut *w, |w| render_defmt_impl(w, msg))?;
499 self.impl_arbitrary
500 .fmt_cfg(&mut *w, |w| self.render_arbitrary(w, dbc, msg))?;
501
502 let enums_for_this_message = dbc.value_descriptions.iter().filter_map(|x| {
503 if let ValueDescription::Signal {
504 message_id,
505 name,
506 value_descriptions,
507 } = x
508 {
509 if *message_id != msg.id {
510 return None;
511 }
512 dbc.signal_by_name(*message_id, name)
513 .map(|v| (v, value_descriptions))
514 } else {
515 None
516 }
517 });
518 for (signal, variants) in enums_for_this_message {
519 self.write_enum(w, signal, msg, variants.as_slice())?;
520 }
521
522 let multiplexor_signal = msg
523 .signals
524 .iter()
525 .find(|s| s.multiplexer_indicator == Multiplexor);
526
527 if let Some(multiplexor_signal) = multiplexor_signal {
528 self.render_multiplexor_enums(w, dbc, msg, multiplexor_signal)?;
529 }
530
531 Ok(())
532 }
533
534 fn validate_attribute_structs(&self) -> Result<()> {
536 for spec in self.attribute_structs {
537 ensure!(
540 is_screaming_snake_case(spec.const_name),
541 "attribute_structs: 'const_name' {:?} must be SCREAMING_SNAKE_CASE",
542 spec.const_name
543 );
544 ensure!(
545 is_valid_type_path(spec.type_path),
546 "attribute_structs: 'type_path' {:?} for {:?} is not a valid Rust type path",
547 spec.type_path,
548 spec.const_name
549 );
550 ensure!(
551 !spec.require.is_empty(),
552 "attribute_structs: 'require' must not be empty for {:?}",
553 spec.const_name
554 );
555 ensure!(
556 !spec.fields.is_empty(),
557 "attribute_structs: {:?} declares no fields",
558 spec.const_name
559 );
560
561 let has_signal = matches!(
562 spec.scope,
563 AttributeScope::Signal | AttributeScope::NodeSignal
564 );
565 let has_node = matches!(
566 spec.scope,
567 AttributeScope::NodeSignal | AttributeScope::NodeMessage
568 );
569 if let Some(for_node) = spec.for_node {
570 ensure!(
571 !for_node.is_empty(),
572 "attribute_structs: 'for_node' must not be empty for {:?}",
573 spec.const_name
574 );
575 ensure!(
576 has_node,
577 "attribute_structs: {:?} sets 'for_node' but its scope has no associated \
578 node (scope must be NodeSignal or NodeMessage)",
579 spec.const_name
580 );
581 }
582 let mut seen = BTreeSet::new();
583 for field in spec.fields {
584 ensure!(
585 is_valid_ident(field.name),
586 "attribute_structs: field name {:?} in {:?} is not a valid Rust identifier",
587 field.name,
588 spec.const_name
589 );
590 ensure!(
591 seen.insert(field.name),
592 "attribute_structs: duplicate field {:?} in {:?}",
593 field.name,
594 spec.const_name
595 );
596 if !has_signal {
597 ensure!(
598 !matches!(
599 field.source,
600 FieldSource::StartBit | FieldSource::StartByte | FieldSource::BitWidth
601 ),
602 "attribute_structs: field {:?} of {:?} uses a signal-only source \
603 (StartBit/StartByte/BitWidth) but the struct has no associated signal",
604 field.name,
605 spec.const_name
606 );
607 }
608 if !has_node {
609 ensure!(
610 !matches!(field.source, FieldSource::NodeName),
611 "attribute_structs: field {:?} of {:?} uses NodeName but the struct has \
612 no associated node (scope must be NodeSignal or NodeMessage)",
613 field.name,
614 spec.const_name
615 );
616 }
617 }
618 }
619 Ok(())
620 }
621
622 fn render_attribute_structs(&self, w: &mut impl Write, msg: &Message, dbc: &Dbc) -> Result<()> {
624 if self.attribute_structs.is_empty() {
625 return Ok(());
626 }
627
628 let mut used: BTreeSet<String> = BTreeSet::new();
632 used.insert("MESSAGE_ID".to_string());
633 for signal in &msg.signals {
634 if ValType::from_signal(signal) != ValType::Bool {
635 let sig = signal.field_name().to_uppercase();
636 used.insert(format!("{sig}_MIN"));
637 used.insert(format!("{sig}_MAX"));
638 }
639 }
640
641 for spec in self.attribute_structs {
642 match spec.scope {
643 AttributeScope::Message => {
644 if dbc.message_attribute(msg.id, spec.require).is_none() {
645 continue;
646 }
647 Self::render_attribute_struct(
648 w,
649 spec,
650 spec.const_name,
651 &AttrTarget {
652 msg,
653 dbc,
654 signal: None,
655 node: None,
656 },
657 &mut used,
658 )?;
659 }
660 AttributeScope::Signal => {
661 for signal in &msg.signals {
662 if dbc
663 .signal_attribute(msg.id, &signal.name, spec.require)
664 .is_none()
665 {
666 continue;
667 }
668 let name =
669 format!("{}_{}", signal.field_name().to_uppercase(), spec.const_name);
670 Self::render_attribute_struct(
671 w,
672 spec,
673 &name,
674 &AttrTarget {
675 msg,
676 dbc,
677 signal: Some(signal),
678 node: None,
679 },
680 &mut used,
681 )?;
682 }
683 }
684 AttributeScope::NodeSignal => {
685 for signal in &msg.signals {
686 for node in &signal.receivers {
687 if spec.for_node.is_some_and(|target| node != target) {
688 continue;
689 }
690 if node_relation_attribute(
691 dbc,
692 node,
693 msg.id,
694 Some(&signal.name),
695 spec.require,
696 )
697 .is_none()
698 {
699 continue;
700 }
701 let name = if spec.for_node.is_some() {
702 format!(
703 "{}_{}",
704 signal.field_name().to_uppercase(),
705 spec.const_name
706 )
707 } else {
708 let node_ident = node_field_name(node).to_uppercase();
709 format!(
710 "{}_{node_ident}_{}",
711 signal.field_name().to_uppercase(),
712 spec.const_name
713 )
714 };
715 Self::render_attribute_struct(
716 w,
717 spec,
718 &name,
719 &AttrTarget {
720 msg,
721 dbc,
722 signal: Some(signal),
723 node: Some(node),
724 },
725 &mut used,
726 )?;
727 }
728 }
729 }
730 AttributeScope::NodeMessage => {
731 for node in &dbc.nodes {
732 if spec.for_node.is_some_and(|target| node.0 != target) {
733 continue;
734 }
735 if node_relation_attribute(dbc, &node.0, msg.id, None, spec.require)
736 .is_none()
737 {
738 continue;
739 }
740 let name = if spec.for_node.is_some() {
741 spec.const_name.to_string()
742 } else {
743 format!(
744 "{}_{}",
745 node_field_name(&node.0).to_uppercase(),
746 spec.const_name
747 )
748 };
749 Self::render_attribute_struct(
750 w,
751 spec,
752 &name,
753 &AttrTarget {
754 msg,
755 dbc,
756 signal: None,
757 node: Some(&node.0),
758 },
759 &mut used,
760 )?;
761 }
762 }
763 }
764 }
765 Ok(())
766 }
767
768 fn render_attribute_struct(
770 w: &mut impl Write,
771 spec: &AttributeStruct<'_>,
772 const_name: &str,
773 target: &AttrTarget<'_>,
774 used: &mut BTreeSet<String>,
775 ) -> Result<()> {
776 ensure!(
777 used.insert(const_name.to_string()),
778 "attribute_structs: generated const '{const_name}' on message {:?} collides with \
779 another const. Use a distinct 'const_name'.",
780 target.msg.name
781 );
782
783 let mut fields = Vec::with_capacity(spec.fields.len());
784 for field in spec.fields {
785 let lit = resolve_field_source(&field.source, target).ok_or_else(|| {
786 anyhow!(
787 "attribute_structs: const '{const_name}' field {:?} has no value in the DBC \
788 and no default (source: {:?})",
789 field.name,
790 field.source
791 )
792 })?;
793 fields.push((field.name, lit));
794 }
795
796 let ty = spec.type_path;
797 writeln!(w, "/// Generated from DBC attributes `{}`", spec.require)?;
798 writeln!(w, "pub const {const_name}: {ty} = {ty} {{")?;
799 {
800 let mut w = PadAdapter::wrap(w);
801 for (name, lit) in fields {
802 writeln!(w, "{name}: {lit},")?;
803 }
804 }
805 writeln!(w, "}};")?;
806 writeln!(w)?;
807 Ok(())
808 }
809
810 fn render_cycle_time(w: &mut impl Write, msg: &Message, dbc: &Dbc) -> Result<()> {
813 let Some(ms) = message_cycle_time_ms(dbc, msg.id) else {
814 return Ok(());
815 };
816 writeln!(w, "pub const MESSAGE_CYCLE_TIME_MS: u32 = {ms};")?;
817 Ok(())
818 }
819
820 fn render_signal(
821 &self,
822 w: &mut impl Write,
823 signal: &Signal,
824 dbc: &Dbc,
825 msg: &Message,
826 ) -> Result<()> {
827 writeln!(w, "/// Returns the value of `{}`.", signal.name)?;
828 if let Some(comment) = dbc.signal_comment(msg.id, &signal.name) {
829 writeln!(w, "///")?;
830 for line in comment.trim().lines() {
831 writeln!(w, "/// {line}")?;
832 }
833 }
834 writeln!(w, "///")?;
835 writeln!(w, "/// - Min: {}", signal.min)?;
836 writeln!(w, "/// - Max: {}", signal.max)?;
837 if signal.unit.is_empty() {
838 writeln!(w, "/// - Unit: Not specified")?;
839 } else {
840 writeln!(w, "/// - Unit: {:?}", signal.unit)?;
841 }
842 if signal.receivers.is_empty() {
843 writeln!(w, "/// - Receivers: Vector__XXX")?;
844 } else {
845 writeln!(w, "/// - Receivers: {}", signal.receivers.join(", "))?;
846 }
847
848 let fn_name = signal.field_name();
849 let variants = dbc.value_descriptions_for_signal(msg.id, &signal.name);
850 if variants.is_none() {
851 writeln!(w, "/// - Factor: {}", signal.factor)?;
852 writeln!(w, "/// - Offset: {}", signal.offset)?;
853 }
854 writeln!(w, "#[inline(always)]")?;
855 if let Some(variants) = variants {
856 let type_name = enum_name(msg, signal);
857 let signal_ty = ValType::from_signal(signal);
858 let variant_infos = generate_variant_info(variants, signal_ty);
859
860 writeln!(w, "pub fn {fn_name}(&self) -> {type_name} {{")?;
861 {
862 let mut w = PadAdapter::wrap(w);
863
864 let has_negative_values = variants.iter().any(|v| v.id < 0);
866 let load_type = if signal.value_type == Signed && has_negative_values {
867 signal_ty
868 } else {
869 ValType::from_signal_uint(signal)
870 };
871
872 let read = read_fn_with_type(signal, msg, load_type)?;
873 writeln!(w, r"let signal = {read};")?;
874 writeln!(w)?;
875 writeln!(w, "match signal {{")?;
876 {
877 let mut w = PadAdapter::wrap(&mut w);
878 for info in &variant_infos {
879 let literal = info.value;
880 let variant = &info.base_name;
881 match info.dup_type {
882 DuplicateType::Unique => {
883 writeln!(w, "{literal} => {type_name}::{variant},")?;
884 }
885 DuplicateType::FirstDuplicate | DuplicateType::Duplicate => {
886 writeln!(w, "{literal} => {type_name}::{variant}({literal}),")?;
887 }
888 }
889 }
890 writeln!(w, "_ => {type_name}::_Other(self.{fn_name}_phys_val()),")?;
891 }
892 writeln!(w, "}}")?;
893 }
894 writeln!(w, "}}")?;
895 writeln!(w)?;
896
897 writeln!(w, "#[inline(always)]")?;
899 let typ = ValType::from_signal(signal);
900 writeln!(w, "fn {fn_name}_phys_val(&self) -> {typ} {{")?;
901 {
902 let mut w = PadAdapter::wrap(w);
903 signal_from_payload(&mut w, signal, msg).context("signal from payload")?;
904 }
905 writeln!(w, "}}")?;
906 writeln!(w)?;
907 } else {
908 let typ = ValType::from_signal(signal);
909 writeln!(w, "pub fn {fn_name}(&self) -> {typ} {{")?;
910 {
911 let mut w = PadAdapter::wrap(w);
912 signal_from_payload(&mut w, signal, msg).context("signal from payload")?;
913 }
914 writeln!(w, "}}")?;
915 writeln!(w)?;
916 }
917
918 render_raw_accessors(w, signal, msg)?;
919
920 self.render_set_signal(w, signal, dbc, msg)?;
921
922 Ok(())
923 }
924
925 fn render_set_signal(
926 &self,
927 w: &mut impl Write,
928 signal: &Signal,
929 dbc: &Dbc,
930 msg: &Message,
931 ) -> Result<()> {
932 let visibility = if signal.multiplexer_indicator == Multiplexor {
935 ""
936 } else {
937 "pub "
938 };
939
940 let field = signal.field_name();
941 let typ = ValType::from_signal(signal);
942 let param_type = signal_pub_type(dbc, msg, signal);
943 let is_enum_backed = param_type != typ.to_string();
944
945 writeln!(w, "/// Sets the value of `{}`.", signal.name)?;
946 writeln!(w, "#[inline(always)]")?;
947 writeln!(
948 w,
949 "{visibility}fn set_{field}(&mut self, value: {param_type}) -> Result<(), CanError> {{",
950 )?;
951 {
952 let mut w = PadAdapter::wrap(w);
953 if is_enum_backed {
956 writeln!(w, "let value = {typ}::from(value);")?;
957 }
958 self.render_set_signal_body(&mut w, signal, msg)?;
959 }
960 writeln!(w, "}}")?;
961 writeln!(w)?;
962
963 Ok(())
964 }
965
966 fn render_set_signal_body(
967 &self,
968 w: &mut impl Write,
969 signal: &Signal,
970 msg: &Message,
971 ) -> Result<()> {
972 if signal.size != 1 {
973 if let FeatureConfig::Gated(gate) = self.check_ranges {
974 writeln!(w, r"#[cfg(feature = {gate:?})]")?;
975 }
976
977 if let FeatureConfig::Gated(..) | FeatureConfig::Always = self.check_ranges {
978 let typ = ValType::from_signal(signal);
979 let min = signal.min;
980 let max = signal.max;
981 writeln!(w, r"if value < {min}_{typ} || {max}_{typ} < value {{")?;
982
983 {
984 let mut w = PadAdapter::wrap(&mut *w);
985 let typ = msg.type_name();
986 writeln!(
987 w,
988 r"return Err(CanError::ParameterOutOfRange {{ message_id: {typ}::MESSAGE_ID }});",
989 )?;
990 }
991
992 writeln!(w, r"}}")?;
993 }
994 }
995 signal_to_payload(&mut *w, signal, msg).context("signal to payload")?;
996
997 Ok(())
998 }
999
1000 fn render_multiplexor_signal(
1001 &self,
1002 w: &mut impl Write,
1003 signal: &Signal,
1004 dbc: &Dbc,
1005 msg: &Message,
1006 ) -> Result<()> {
1007 let signal_typ = ValType::from_signal(signal);
1008
1009 render_raw_accessors(w, signal, msg)?;
1010
1011 let field = signal.field_name();
1012 let typ = multiplex_enum_name(msg, signal)?;
1013 writeln!(
1014 w,
1015 "/// Selects the active multiplexed sub-message for `{}`.",
1016 signal.name
1017 )?;
1018 writeln!(
1019 w,
1020 "pub fn {field}_multiplexed(&mut self) -> Result<{typ}, CanError> {{"
1021 )?;
1022
1023 let multiplexer_indexes: BTreeSet<u64> = msg
1024 .signals
1025 .iter()
1026 .filter_map(|s| {
1027 if let MultiplexedSignal(index) = &s.multiplexer_indicator {
1028 Some(index)
1029 } else {
1030 None
1031 }
1032 })
1033 .copied()
1034 .collect();
1035
1036 {
1037 let mut w = PadAdapter::wrap(w);
1038 writeln!(w, "match self.{}_raw_val() {{", signal.field_name())?;
1039
1040 {
1041 let mut w = PadAdapter::wrap(&mut w);
1042 for idx in &multiplexer_indexes {
1043 writeln!(
1044 w,
1045 "{idx} => Ok({enum_name}::{multiplexed_wrapper_name}({multiplexed_name}{{ raw: self.raw }})),",
1046 enum_name = multiplex_enum_name(msg, signal)?,
1047 multiplexed_wrapper_name = multiplexed_enum_variant_wrapper_name(*idx),
1048 multiplexed_name = multiplexed_enum_variant_name(msg, signal, *idx)?,
1049 )?;
1050 }
1051 let to_u16 = match signal_typ {
1052 ValType::UnsignedInt(IntSize::Size8) => "multiplexor.into()",
1053 ValType::UnsignedInt(IntSize::Size16) => "multiplexor",
1054 _ => "u16::try_from(multiplexor).unwrap_or(u16::MAX)",
1055 };
1056 writeln!(
1057 w,
1058 "multiplexor => Err(CanError::InvalidMultiplexor {{ message_id: {}::MESSAGE_ID, multiplexor: {to_u16} }}),",
1059 msg.type_name(),
1060 )?;
1061 }
1062
1063 writeln!(w, "}}")?;
1064 }
1065 writeln!(w, "}}")?;
1066
1067 self.render_set_signal(w, signal, dbc, msg)?;
1068
1069 for switch_index in multiplexer_indexes {
1070 render_set_signal_multiplexer(w, signal, msg, switch_index)?;
1071 }
1072
1073 Ok(())
1074 }
1075
1076 fn write_enum(
1077 &self,
1078 w: &mut impl Write,
1079 signal: &Signal,
1080 msg: &Message,
1081 variants: &[ValDescription],
1082 ) -> Result<()> {
1083 let type_name = enum_name(msg, signal);
1084 let signal_ty = ValType::from_signal(signal);
1085
1086 let variant_infos = generate_variant_info(variants, signal_ty);
1088
1089 writeln!(w, "/// Defined values for {}", signal.name)?;
1090 writeln!(w, "{ALLOW_LINTS}")?;
1091 self.write_allow_dead_code(w)?;
1092 writeln!(w, "#[derive(Clone, Copy, PartialEq)]")?;
1093 self.impl_debug.fmt_attr(w, "derive(Debug)")?;
1094 self.impl_defmt.fmt_attr(w, "derive(defmt::Format)")?;
1095 self.impl_serde.fmt_attr(w, "derive(Serialize)")?;
1096 self.impl_serde.fmt_attr(w, "derive(Deserialize)")?;
1097 writeln!(w, "pub enum {type_name} {{")?;
1098 {
1099 let mut w = PadAdapter::wrap(w);
1100 for info in &variant_infos {
1101 let variant = &info.base_name;
1102 match info.dup_type {
1103 DuplicateType::Unique => writeln!(w, "{variant},")?,
1104 DuplicateType::FirstDuplicate => {
1105 writeln!(w, "{variant}({}),", info.value_type)?;
1106 }
1107 DuplicateType::Duplicate => {}
1108 }
1109 }
1110 writeln!(w, "_Other({signal_ty}),")?;
1111 }
1112 writeln!(w, "}}")?;
1113 writeln!(w)?;
1114
1115 writeln!(w, "impl From<{type_name}> for {signal_ty} {{")?;
1116 {
1117 let match_on_raw_type = match ValType::from_signal(signal) {
1118 ValType::Bool => |x: i64| format!("{}", x == 1),
1119 ValType::F32 => |x: i64| format!("{x}_f32"),
1120 _ => |x: i64| format!("{x}"),
1121 };
1122
1123 let mut w = PadAdapter::wrap(w);
1124 writeln!(w, "fn from(val: {type_name}) -> {signal_ty} {{")?;
1125 {
1126 let mut w = PadAdapter::wrap(&mut w);
1127 writeln!(w, "match val {{")?;
1128 {
1129 let mut w = PadAdapter::wrap(&mut w);
1130 for info in &variant_infos {
1131 match info.dup_type {
1132 DuplicateType::Unique => {
1133 let literal = match_on_raw_type(info.value);
1134 writeln!(w, "{type_name}::{} => {literal},", info.base_name)?;
1135 }
1136 DuplicateType::FirstDuplicate => {
1137 writeln!(w, "{type_name}::{}(v) => v,", info.base_name)?;
1138 }
1139 DuplicateType::Duplicate => {}
1140 }
1141 }
1142 writeln!(w, "{type_name}::_Other(x) => x,")?;
1143 }
1144 writeln!(w, "}}")?;
1145 }
1146 writeln!(w, "}}")?;
1147 }
1148 writeln!(w, "}}")?;
1149 writeln!(w)?;
1150 Ok(())
1151 }
1152}
1153
1154fn render_set_signal_multiplexer(
1155 w: &mut impl Write,
1156 multiplexor: &Signal,
1157 msg: &Message,
1158 switch_index: u64,
1159) -> Result<()> {
1160 writeln!(w, "/// Sets the value of `{}`.", multiplexor.name)?;
1161 writeln!(w, "#[inline(always)]")?;
1162 writeln!(
1163 w,
1164 "pub fn set_{enum_variant_wrapper}(&mut self, value: {enum_variant}) -> Result<(), CanError> {{",
1165 enum_variant_wrapper = multiplexed_enum_variant_wrapper_name(switch_index).to_snake_case(),
1166 enum_variant = multiplexed_enum_variant_name(msg, multiplexor, switch_index)?,
1167 )?;
1168
1169 {
1170 let mut w = PadAdapter::wrap(w);
1171
1172 writeln!(w, "let b0 = BitArray::<_, LocalBits>::new(self.raw);")?;
1173 writeln!(w, "let b1 = BitArray::<_, LocalBits>::new(value.raw);")?;
1174 writeln!(w, "self.raw = b0.bitor(b1).into_inner();")?;
1175 writeln!(w, "self.set_{}({switch_index})?;", multiplexor.field_name())?;
1176 writeln!(w, "Ok(())")?;
1177 }
1178
1179 writeln!(w, "}}")?;
1180 writeln!(w)?;
1181
1182 Ok(())
1183}
1184
1185fn be_start_end_bit(signal: &Signal, msg: &Message) -> Result<(u64, u64)> {
1186 let err = "calculating start bit";
1187
1188 let x = signal.start_bit.checked_div(8).context(err)?;
1189 let x = x.checked_mul(8).context(err)?;
1190
1191 let y = signal.start_bit.checked_rem(8).context(err)?;
1192 let y = 7u64.checked_sub(y).context(err)?;
1193
1194 let start_bit = x.checked_add(y).context(err)?;
1195 let end_bit = start_bit
1196 .checked_add(signal.size)
1197 .context("calculating last bit position")?;
1198
1199 let msg_bits = msg.size.checked_mul(8).context("message size overflow")?;
1200
1201 ensure!(
1202 start_bit <= msg_bits,
1203 "signal starts at {start_bit}, but message is only {msg_bits} bits",
1204 );
1205 ensure!(
1206 end_bit <= msg_bits,
1207 "signal ends at {end_bit}, but message is only {msg_bits} bits",
1208 );
1209 Ok((start_bit, end_bit))
1210}
1211
1212fn le_start_end_bit(signal: &Signal, msg: &Message) -> Result<(u64, u64)> {
1213 let msg_bits = msg.size.checked_mul(8).context("message size overflow")?;
1214 let start_bit = signal.start_bit;
1215 ensure!(
1216 start_bit <= msg_bits,
1217 "signal starts at {start_bit}, but message is only {msg_bits} bits",
1218 );
1219
1220 let end_bit = signal
1221 .start_bit
1222 .checked_add(signal.size)
1223 .context("overflow calculating last bit position")?;
1224 ensure!(
1225 end_bit <= msg_bits,
1226 "signal ends at {end_bit}, but message is only {msg_bits} bits",
1227 );
1228 Ok((start_bit, end_bit))
1229}
1230
1231fn signal_pub_type(dbc: &Dbc, msg: &Message, signal: &Signal) -> String {
1235 if signal.multiplexer_indicator != Multiplexor
1236 && dbc
1237 .value_descriptions_for_signal(msg.id, &signal.name)
1238 .is_some()
1239 {
1240 enum_name(msg, signal)
1241 } else {
1242 ValType::from_signal(signal).to_string()
1243 }
1244}
1245
1246#[allow(clippy::float_cmp)]
1249fn is_unscaled(signal: &Signal) -> bool {
1250 signal.factor == 1.0 && signal.offset == 0.0
1251}
1252
1253fn signal_from_payload(w: &mut impl Write, signal: &Signal, msg: &Message) -> Result<()> {
1254 if is_unscaled(signal) {
1255 let field = signal.field_name();
1256 if signal.size == 1 {
1257 writeln!(w, "self.{field}_raw_val() == 1")?;
1258 } else {
1259 writeln!(w, "self.{field}_raw_val()")?;
1260 }
1261 return Ok(());
1262 }
1263
1264 writeln!(w, r"let signal = {};", read_fn(signal, msg)?)?;
1265 writeln!(w)?;
1266
1267 let typ = ValType::from_signal(signal);
1268 match typ {
1269 ValType::Bool => {
1270 writeln!(w, "signal == 1")?;
1271 }
1272 ValType::F32 => {
1273 writeln!(w, "let factor = {}_f32;", signal.factor)?;
1275 writeln!(w, "let offset = {}_f32;", signal.offset)?;
1276 writeln!(w, "(signal as f32) * factor + offset")?;
1277 }
1278 _ => {
1279 writeln!(w, "let factor = {};", signal.factor)?;
1280 if Some(typ) == ValType::from_signal_uint(signal).unsigned_to_signed() {
1281 writeln!(w, "let signal = signal as {typ};")?;
1284 }
1285
1286 if signal.offset >= 0.0 {
1287 writeln!(
1288 w,
1289 "{typ}::from(signal).saturating_mul(factor).saturating_add({})",
1290 signal.offset,
1291 )?;
1292 } else {
1293 writeln!(
1294 w,
1295 "{typ}::from(signal).saturating_mul(factor).saturating_sub({})",
1296 signal.offset.abs(),
1297 )?;
1298 }
1299 }
1300 }
1301 Ok(())
1302}
1303
1304fn read_fn(signal: &Signal, msg: &Message) -> Result<String> {
1305 read_fn_with_type(signal, msg, ValType::from_signal_int(signal))
1306}
1307
1308fn read_fn_with_type(signal: &Signal, msg: &Message, typ: ValType) -> Result<String> {
1309 Ok(match signal.byte_order {
1310 LittleEndian => {
1311 let (start, end) = le_start_end_bit(signal, msg)?;
1312 format!("self.raw.view_bits::<Lsb0>()[{start}..{end}].load_le::<{typ}>()")
1313 }
1314 BigEndian => {
1315 let (start, end) = be_start_end_bit(signal, msg)?;
1316 format!("self.raw.view_bits::<Msb0>()[{start}..{end}].load_be::<{typ}>()")
1317 }
1318 })
1319}
1320
1321fn signal_to_payload(w: &mut impl Write, signal: &Signal, msg: &Message) -> Result<()> {
1322 let typ = ValType::from_signal(signal);
1323 match typ {
1324 ValType::Bool => {
1325 writeln!(w, "let value = value as u8;")?;
1327 }
1328 ValType::F32 => {
1329 writeln!(w, "let factor = {}_f32;", signal.factor)?;
1331 writeln!(w, "let offset = {}_f32;", signal.offset)?;
1332 let typ = ValType::from_signal_int(signal);
1333 writeln!(w, "let value = ((value - offset) / factor) as {typ};")?;
1334 writeln!(w)?;
1335 }
1336 _ if is_unscaled(signal) => {
1337 }
1339 _ => {
1340 writeln!(w, "let factor = {};", signal.factor)?;
1341 if signal.offset >= 0.0 {
1342 writeln!(w, "let value = value.checked_sub({})", signal.offset)?;
1343 } else {
1344 writeln!(w, "let value = value.checked_add({})", signal.offset.abs())?;
1345 }
1346 writeln!(
1347 w,
1348 " .ok_or(CanError::ParameterOutOfRange {{ message_id: {}::MESSAGE_ID }})?;",
1349 msg.type_name(),
1350 )?;
1351 let typ = ValType::from_signal_int(signal);
1352 writeln!(w, "let value = (value / factor) as {typ};")?;
1353 writeln!(w)?;
1354 }
1355 }
1356
1357 pack_bits(w, signal, msg)?;
1358
1359 writeln!(w, "Ok(())")?;
1360 Ok(())
1361}
1362
1363fn pack_bits(w: &mut impl Write, signal: &Signal, msg: &Message) -> Result<()> {
1365 if signal.value_type == Signed {
1366 let typ = ValType::from_signal_uint(signal);
1367 writeln!(w, "let value = {typ}::from_ne_bytes(value.to_ne_bytes());")?;
1368 }
1369
1370 match signal.byte_order {
1371 LittleEndian => {
1372 let (start, end) = le_start_end_bit(signal, msg)?;
1373 writeln!(
1374 w,
1375 r"self.raw.view_bits_mut::<Lsb0>()[{start}..{end}].store_le(value);",
1376 )?;
1377 }
1378 BigEndian => {
1379 let (start, end) = be_start_end_bit(signal, msg)?;
1380 writeln!(
1381 w,
1382 r"self.raw.view_bits_mut::<Msb0>()[{start}..{end}].store_be(value);",
1383 )?;
1384 }
1385 }
1386
1387 Ok(())
1388}
1389
1390fn render_raw_accessors(w: &mut impl Write, signal: &Signal, msg: &Message) -> Result<()> {
1392 let field = signal.field_name();
1393 let typ = ValType::from_signal_int(signal);
1394
1395 writeln!(w, "/// Returns the raw value of `{}`.", signal.name)?;
1396 writeln!(w, "///")?;
1397 writeln!(w, "/// - Start bit: {}", signal.start_bit)?;
1398 writeln!(w, "/// - Signal size: {} bits", signal.size)?;
1399 writeln!(w, "/// - Byte order: {:?}", signal.byte_order)?;
1400 writeln!(w, "/// - Value type: {:?}", signal.value_type)?;
1401 writeln!(w, "#[inline(always)]")?;
1402 writeln!(w, "pub fn {field}_raw_val(&self) -> {typ} {{")?;
1403 {
1404 let mut w = PadAdapter::wrap(&mut *w);
1405 writeln!(w, "{}", read_fn(signal, msg)?)?;
1406 }
1407 writeln!(w, "}}")?;
1408 writeln!(w)?;
1409
1410 let visibility = if signal.multiplexer_indicator == Multiplexor {
1413 ""
1414 } else {
1415 "pub "
1416 };
1417
1418 writeln!(w, "/// Sets the raw value of `{}`.", signal.name)?;
1419 if visibility.is_empty() {
1420 writeln!(w, "#[allow(dead_code)]")?;
1422 }
1423 writeln!(w, "#[inline(always)]")?;
1424 writeln!(
1425 w,
1426 "{visibility}fn set_{field}_raw_val(&mut self, value: {typ}) {{",
1427 )?;
1428 {
1429 let mut w = PadAdapter::wrap(&mut *w);
1430 pack_bits(&mut w, signal, msg)?;
1431 }
1432 writeln!(w, "}}")?;
1433 writeln!(w)?;
1434
1435 Ok(())
1436}
1437
1438enum DuplicateType {
1439 Unique,
1440 FirstDuplicate,
1441 Duplicate,
1442}
1443
1444struct VariantInfo {
1446 base_name: String,
1447 value: i64,
1448 dup_type: DuplicateType,
1449 value_type: String,
1450}
1451
1452fn generate_variant_info(variants: &[ValDescription], signal_ty: ValType) -> Vec<VariantInfo> {
1455 let mut name_counts: HashMap<String, usize> = HashMap::new();
1457 for variant in variants {
1458 let base_name = enum_variant_name(&variant.description);
1459 name_counts
1460 .entry(base_name)
1461 .and_modify(|c| *c = c.saturating_add(1))
1462 .or_insert(1);
1463 }
1464
1465 let mut variant_infos = Vec::new();
1467 let mut seen_names: HashMap<String, usize> = HashMap::new();
1468 for variant in variants {
1469 let base_name = enum_variant_name(&variant.description);
1470 let count = name_counts.get(&base_name).copied().unwrap_or(0);
1471 let seen_count = seen_names.entry(base_name.clone()).or_insert(0);
1472 *seen_count = (*seen_count).saturating_add(1);
1473
1474 let dup_type = if count == 1 {
1475 DuplicateType::Unique
1476 } else if *seen_count == 1 {
1477 DuplicateType::FirstDuplicate
1478 } else {
1479 DuplicateType::Duplicate
1480 };
1481
1482 variant_infos.push(VariantInfo {
1483 base_name,
1484 value: variant.id,
1485 dup_type,
1486 value_type: signal_ty.to_string(),
1487 });
1488 }
1489 variant_infos
1490}
1491
1492impl Config<'_> {
1493 fn render_embedded_can_frame(&self, w: &mut impl Write, msg: &Message) -> Result<()> {
1494 self.impl_embedded_can_frame.fmt_cfg(w, |w| {
1495 writeln!(
1496 w,
1497 "\
1498impl embedded_can::Frame for {0} {{
1499 fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self> {{
1500 if id.into() != Self::MESSAGE_ID {{
1501 None
1502 }} else {{
1503 data.try_into().ok()
1504 }}
1505 }}
1506
1507 fn new_remote(_id: impl Into<Id>, _dlc: usize) -> Option<Self> {{
1508 unimplemented!()
1509 }}
1510
1511 fn is_extended(&self) -> bool {{
1512 match self.id() {{
1513 Id::Standard(_) => false,
1514 Id::Extended(_) => true,
1515 }}
1516 }}
1517
1518 fn is_remote_frame(&self) -> bool {{
1519 false
1520 }}
1521
1522 fn id(&self) -> Id {{
1523 Self::MESSAGE_ID
1524 }}
1525
1526 fn dlc(&self) -> usize {{
1527 self.raw.len()
1528 }}
1529
1530 fn data(&self) -> &[u8] {{
1531 &self.raw
1532 }}
1533}}",
1534 msg.type_name(),
1535 )
1536 })
1537 }
1538}
1539
1540fn render_debug_impl(w: &mut impl Write, msg: &Message) -> Result<()> {
1541 let typ = msg.type_name();
1542 writeln!(w, r"impl core::fmt::Debug for {typ} {{")?;
1543 {
1544 let mut w = PadAdapter::wrap(w);
1545 writeln!(
1546 w,
1547 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {{",
1548 )?;
1549 {
1550 let mut w = PadAdapter::wrap(&mut w);
1551 writeln!(w, r"if f.alternate() {{")?;
1552 {
1553 let mut w = PadAdapter::wrap(&mut w);
1554 writeln!(w, r#"f.debug_struct("{typ}")"#)?;
1555 {
1556 let mut w = PadAdapter::wrap(&mut w);
1557 for signal in &msg.signals {
1558 if signal.multiplexer_indicator == Plain {
1559 writeln!(w, r#".field("{0}", &self.{0}())"#, signal.field_name())?;
1560 }
1561 }
1562 }
1563 writeln!(w, r".finish()")?;
1564 }
1565 writeln!(w, r"}} else {{")?;
1566 {
1567 let mut w = PadAdapter::wrap(&mut w);
1568 writeln!(w, r#"f.debug_tuple("{typ}").field(&self.raw).finish()"#)?;
1569 }
1570 writeln!(w, "}}")?;
1571 }
1572 writeln!(w, "}}")?;
1573 }
1574 writeln!(w, "}}")?;
1575 writeln!(w)?;
1576 Ok(())
1577}
1578
1579fn render_defmt_impl(w: &mut impl Write, msg: &Message) -> Result<()> {
1580 let typ = msg.type_name();
1581 writeln!(w, r"impl defmt::Format for {typ} {{")?;
1582 {
1583 let mut w = PadAdapter::wrap(w);
1584 writeln!(w, "fn format(&self, f: defmt::Formatter) {{")?;
1585 {
1586 let mut w = PadAdapter::wrap(&mut w);
1587 writeln!(w, r"defmt::write!(f,")?;
1588 {
1589 let mut w = PadAdapter::wrap(&mut w);
1590 write!(w, r#""{typ} {{{{"#)?;
1591 {
1592 for signal in &msg.signals {
1593 if signal.multiplexer_indicator == Plain {
1594 write!(w, r" {}={{:?}}", signal.name)?;
1595 }
1596 }
1597 }
1598 writeln!(w, r#" }}}}","#)?;
1599
1600 for signal in &msg.signals {
1601 if signal.multiplexer_indicator == Plain {
1602 writeln!(w, "self.{}(),", signal.field_name())?;
1603 }
1604 }
1605 writeln!(w, r");")?;
1606 }
1607 writeln!(w, "}}")?;
1608 }
1609 }
1610 writeln!(w, "}}")?;
1611 writeln!(w)?;
1612 Ok(())
1613}
1614
1615impl Config<'_> {
1616 fn render_multiplexor_enums(
1617 &self,
1618 w: &mut impl Write,
1619 dbc: &Dbc,
1620 msg: &Message,
1621 multiplexor_signal: &Signal,
1622 ) -> Result<()> {
1623 ensure!(
1624 multiplexor_signal.multiplexer_indicator == Multiplexor,
1625 "signal {} is not the multiplexor",
1626 multiplexor_signal.name,
1627 );
1628
1629 let mut multiplexed_signals = BTreeMap::new();
1630 for signal in &msg.signals {
1631 if let MultiplexedSignal(switch_index) = signal.multiplexer_indicator {
1632 multiplexed_signals
1633 .entry(switch_index)
1634 .and_modify(|v: &mut Vec<&Signal>| v.push(signal))
1635 .or_insert_with(|| vec![&signal]);
1636 }
1637 }
1638
1639 writeln!(w, "/// Defined values for multiplexed signal {}", msg.name)?;
1640 writeln!(w, "{ALLOW_LINTS}")?;
1641 self.write_allow_dead_code(w)?;
1642
1643 self.impl_debug.fmt_attr(w, "derive(Debug)")?;
1644 self.impl_defmt.fmt_attr(w, "derive(defmt::Format)")?;
1645 self.impl_serde.fmt_attr(w, "derive(Serialize)")?;
1646 self.impl_serde.fmt_attr(w, "derive(Deserialize)")?;
1647
1648 let enum_name = multiplex_enum_name(msg, multiplexor_signal)?;
1649 writeln!(w, "pub enum {enum_name} {{")?;
1650
1651 {
1652 let mut w = PadAdapter::wrap(w);
1653 for switch_index in multiplexed_signals.keys() {
1654 writeln!(
1655 w,
1656 "{multiplexed_wrapper_name}({multiplexed_name}),",
1657 multiplexed_wrapper_name = multiplexed_enum_variant_wrapper_name(*switch_index),
1658 multiplexed_name =
1659 multiplexed_enum_variant_name(msg, multiplexor_signal, *switch_index)?,
1660 )?;
1661 }
1662 }
1663 writeln!(w, "}}")?;
1664 writeln!(w)?;
1665
1666 for (switch_index, multiplexed_signals) in &multiplexed_signals {
1667 let struct_name =
1668 multiplexed_enum_variant_name(msg, multiplexor_signal, *switch_index)?;
1669
1670 writeln!(w, "{ALLOW_LINTS}")?;
1671 self.write_allow_dead_code(w)?;
1672 self.impl_debug.fmt_attr(w, "derive(Debug)")?;
1673 self.impl_defmt.fmt_attr(w, "derive(defmt::Format)")?;
1674 self.impl_serde.fmt_attr(w, "derive(Serialize)")?;
1675 self.impl_serde.fmt_attr(w, "derive(Deserialize)")?;
1676 writeln!(w, r"#[derive(Default)]")?;
1677 writeln!(w, "pub struct {struct_name} {{ raw: [u8; {}] }}", msg.size)?;
1678 writeln!(w)?;
1679
1680 writeln!(w, "{ALLOW_LINTS}")?;
1681 self.write_allow_dead_code(w)?;
1682 writeln!(w, "impl {struct_name} {{")?;
1683
1684 writeln!(
1685 w,
1686 "pub fn new() -> Self {{ Self {{ raw: [0u8; {}] }} }}",
1687 msg.size
1688 )?;
1689
1690 for signal in multiplexed_signals {
1691 self.render_signal(w, signal, dbc, msg)?;
1692 }
1693
1694 writeln!(w, "}}")?;
1695 writeln!(w)?;
1696 }
1697
1698 Ok(())
1699 }
1700
1701 fn render_arbitrary(&self, w: &mut impl Write, dbc: &Dbc, msg: &Message) -> Result<()> {
1702 writeln!(w, "{ALLOW_LINTS}")?;
1703 self.write_allow_dead_code(w)?;
1704 let typ = msg.type_name();
1705 writeln!(w, "impl<'a> Arbitrary<'a> for {typ} {{")?;
1706 {
1707 let filtered_signals: Vec<&Signal> = msg
1708 .signals
1709 .iter()
1710 .filter(|v| matches!(v.multiplexer_indicator, Plain | Multiplexor))
1711 .collect();
1712 let mut w = PadAdapter::wrap(w);
1713 writeln!(
1714 w,
1715 "fn arbitrary({}u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {{",
1716 if filtered_signals.is_empty() { "_" } else { "" },
1717 )?;
1718 {
1719 let mut w = PadAdapter::wrap(&mut w);
1720
1721 for signal in &filtered_signals {
1722 writeln!(
1723 w,
1724 "let {field_name} = {arbitrary_value};",
1725 field_name = signal.field_name(),
1726 arbitrary_value = signal_to_arbitrary(signal),
1727 )?;
1728 }
1729
1730 let args: Vec<String> = filtered_signals
1731 .iter()
1732 .map(|signal| {
1733 let field = signal.field_name();
1734 let is_enum_backed = signal_pub_type(dbc, msg, signal)
1735 != ValType::from_signal(signal).to_string();
1736 if is_enum_backed {
1737 format!("{}::_Other({field})", enum_name(msg, signal))
1738 } else {
1739 field
1740 }
1741 })
1742 .collect();
1743
1744 writeln!(
1745 w,
1746 "{typ}::new({args}).map_err(|_| arbitrary::Error::IncorrectFormat)",
1747 typ = msg.type_name(),
1748 args = args.join(","),
1749 )?;
1750 }
1751 writeln!(w, "}}")?;
1752 }
1753 writeln!(w, "}}")?;
1754
1755 Ok(())
1756 }
1757
1758 fn render_error(&self, w: &mut impl Write) -> Result<()> {
1759 w.write_all(
1760 r#"
1761 #[allow(dead_code)]
1762#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1763pub enum CanError {
1764 UnknownMessageId(embedded_can::Id),
1765 /// Signal parameter is not within the range
1766 /// defined in the dbc
1767 ParameterOutOfRange {
1768 /// dbc message id
1769 message_id: embedded_can::Id,
1770 },
1771 InvalidPayloadSize,
1772 /// Multiplexor value not defined in the dbc
1773 InvalidMultiplexor {
1774 /// dbc message id
1775 message_id: embedded_can::Id,
1776 /// Multiplexor value not defined in the dbc
1777 multiplexor: u16,
1778 },
1779}
1780
1781impl core::fmt::Display for CanError {
1782 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1783 write!(f, "{self:?}")
1784 }
1785}
1786 "#
1787 .as_bytes(),
1788 )?;
1789
1790 self.impl_error.fmt_cfg(w, |w| {
1791 writeln!(w, "impl core::error::Error for CanError {{}}")
1792 })
1793 }
1794
1795 fn render_arbitrary_helpers(&self, w: &mut impl Write) -> Result<()> {
1796 self.impl_arbitrary.fmt_cfg(&mut *w, |w| {
1797 self.write_allow_dead_code(w)?;
1798 writeln!(w, "trait UnstructuredFloatExt {{")?;
1799 writeln!(w, " fn float_in_range(&mut self, range: core::ops::RangeInclusive<f32>) -> arbitrary::Result<f32>;")?;
1800 writeln!(w, "}}")?;
1801 writeln!(w)?;
1802 Ok::<_, Error>(())
1803 })?;
1804
1805 self.impl_arbitrary.fmt_cfg(w, |w| {
1806 writeln!(w, "impl UnstructuredFloatExt for arbitrary::Unstructured<'_> {{")?;
1807 writeln!(w, " fn float_in_range(&mut self, range: core::ops::RangeInclusive<f32>) -> arbitrary::Result<f32> {{")?;
1808 writeln!(w, " let min = range.start();")?;
1809 writeln!(w, " let max = range.end();")?;
1810 writeln!(w, " let steps = u32::MAX;")?;
1811 writeln!(w, " let factor = (max - min) / (steps as f32);")?;
1812 writeln!(w, " let random_int: u32 = self.int_in_range(0..=steps)?;")?;
1813 writeln!(w, " let random = min + factor * (random_int as f32);")?;
1814 writeln!(w, " Ok(random)")?;
1815 writeln!(w, " }}")?;
1816 writeln!(w, "}}")?;
1817 writeln!(w)?;
1818 Ok::<_, Error>(())
1819 })
1820 }
1821}
1822
1823fn signal_to_arbitrary(signal: &Signal) -> String {
1824 let typ = ValType::from_signal(signal);
1825 match typ {
1826 ValType::Bool => "u.int_in_range(0..=1)? == 1".to_string(),
1827 ValType::F32 => {
1828 let min = signal.min;
1829 let max = signal.max;
1830 format!("u.float_in_range({min}_f32..={max}_f32)?")
1831 }
1832 _ => {
1833 let min = signal.min;
1834 let max = signal.max;
1835 format!("u.int_in_range({min}..={max})?")
1836 }
1837 }
1838}
1839
1840fn get_relevant_messages(dbc: &Dbc) -> impl Iterator<Item = &Message> {
1841 dbc.messages.iter().filter(|v| !message_ignored(v))
1842}
1843
1844fn message_ignored(message: &Message) -> bool {
1845 message.name == "VECTOR__INDEPENDENT_SIG_MSG"
1847}
1848
1849fn resolve_field_source(source: &FieldSource<'_>, target: &AttrTarget<'_>) -> Option<String> {
1851 let AttrTarget {
1852 msg,
1853 dbc,
1854 signal,
1855 node,
1856 } = *target;
1857 match source {
1858 FieldSource::Attr(name) => match (signal, node) {
1859 (Some(s), None) => dbc.resolved_signal_attribute(msg.id, &s.name, name),
1860 (None, None) => dbc.resolved_message_attribute(msg.id, name),
1861 (Some(s), Some(n)) => {
1862 resolved_node_relation_attribute(dbc, n, msg.id, Some(&s.name), name)
1863 }
1864 (None, Some(n)) => resolved_node_relation_attribute(dbc, n, msg.id, None, name),
1865 }
1866 .map(attr_value_literal),
1867 FieldSource::MessageAttr(name) => dbc
1868 .resolved_message_attribute(msg.id, name)
1869 .map(attr_value_literal),
1870 FieldSource::StartBit => signal.map(|s| s.start_bit.to_string()),
1871 FieldSource::StartByte => signal.map(|s| signal_start_byte(s).to_string()),
1872 FieldSource::BitWidth => signal.map(|s| s.size.to_string()),
1873 FieldSource::MessageSize => Some(msg.size.to_string()),
1874 FieldSource::Int(v) => Some(v.to_string()),
1875 FieldSource::Str(v) => Some(format!("{v:?}")),
1876 FieldSource::NodeName => node.map(|n| format!("{n:?}")),
1877 }
1878}
1879
1880fn node_relation_attribute<'a>(
1884 dbc: &'a Dbc,
1885 node_name: &str,
1886 message_id: MessageId,
1887 signal_name: Option<&str>,
1888 name: &str,
1889) -> Option<&'a AttributeValue> {
1890 dbc.relation_attribute_values.iter().find_map(|rel| {
1891 if rel.name != name {
1892 return None;
1893 }
1894 match (&rel.details, signal_name) {
1895 (
1896 AttributeValueForRelationType::NodeToSignal {
1897 node_name: n,
1898 message_id: mid,
1899 signal_name: sig,
1900 value,
1901 },
1902 Some(want_sig),
1903 ) if n == node_name && *mid == message_id && sig == want_sig => Some(value),
1904 (
1905 AttributeValueForRelationType::NodeToMessage {
1906 node_name: n,
1907 message_id: mid,
1908 value,
1909 },
1910 None,
1911 ) if n == node_name && *mid == message_id => Some(value),
1912 _ => None,
1913 }
1914 })
1915}
1916
1917fn resolved_node_relation_attribute<'a>(
1920 dbc: &'a Dbc,
1921 node_name: &str,
1922 message_id: MessageId,
1923 signal_name: Option<&str>,
1924 name: &str,
1925) -> Option<&'a AttributeValue> {
1926 node_relation_attribute(dbc, node_name, message_id, signal_name, name).or_else(|| {
1927 dbc.relation_attribute_defaults
1928 .iter()
1929 .find(|d| d.name == name)
1930 .map(|d| &d.value)
1931 })
1932}
1933
1934fn signal_start_byte(signal: &Signal) -> u64 {
1936 signal.start_bit.checked_div(8).unwrap_or(0)
1937}
1938
1939fn attr_value_literal(value: &AttributeValue) -> String {
1941 match value {
1942 AttributeValue::Uint(v) => v.to_string(),
1943 AttributeValue::Int(v) => v.to_string(),
1944 AttributeValue::Double(v) => format!("{v:?}"),
1945 AttributeValue::String(v) => format!("{v:?}"),
1946 }
1947}
1948
1949fn message_cycle_time_ms(dbc: &Dbc, id: MessageId) -> Option<u32> {
1952 match dbc.message_attribute(id, "GenMsgCycleTime")? {
1953 AttributeValue::Uint(v) => u32::try_from(*v).ok(),
1954 AttributeValue::Int(v) => u32::try_from(*v).ok(),
1955 AttributeValue::Double(_) | AttributeValue::String(_) => None,
1956 }
1957}
1958
1959impl Config<'_> {
1960 pub fn generate(self) -> Result<String> {
1962 let mut out = Vec::new();
1963 self.codegen(&mut out)
1964 .context("could not generate Rust code")?;
1965 let out = std::str::from_utf8(&out).context("Failed to convert output to str")?;
1969 let file = syn::parse_file(out).context("Failed to parse generated Rust code")?;
1970 Ok(prettyplease::unparse(&file))
1971 }
1972
1973 pub fn write(self, mut out: impl Write) -> Result<()> {
1975 out.write_all(self.generate()?.as_bytes())?;
1976 Ok(())
1977 }
1978
1979 pub fn write_to_file<P: AsRef<Path>>(self, path: P) -> Result<()> {
1981 let file = OpenOptions::new()
1982 .write(true)
1983 .truncate(true)
1984 .create(true)
1985 .open(path.as_ref())?;
1986
1987 self.write(file)
1988 }
1989
1990 fn write_allow_dead_code(&self, w: &mut impl Write) -> Result<()> {
1991 if self.allow_dead_code {
1992 writeln!(w, "{ALLOW_DEADCODE}")?;
1993 }
1994 Ok(())
1995 }
1996}