1#![deny(missing_docs)]
8#![deny(clippy::arithmetic_side_effects)]
9
10use anyhow::{anyhow, ensure, Context, Result};
11use can_dbc::{Message, MultiplexIndicator, Signal, ValDescription, ValueDescription, DBC};
12use heck::{ToPascalCase, ToSnakeCase};
13use pad::PadAdapter;
14use std::{
15 collections::{BTreeMap, BTreeSet},
16 io::{BufWriter, Write},
17};
18
19mod includes;
20mod keywords;
21mod pad;
22
23pub fn codegen(dbc_name: &str, dbc_content: &[u8], out: impl Write, debug: bool) -> Result<()> {
25 let dbc = can_dbc::DBC::from_slice(dbc_content).map_err(|e| {
26 let msg = "Could not parse dbc file";
27 if debug {
28 anyhow!("{}: {:#?}", msg, e)
29 } else {
30 anyhow!("{}", msg)
31 }
32 })?;
33 if debug {
34 eprintln!("{:#?}", dbc);
35 }
36 let mut w = BufWriter::new(out);
37
38 writeln!(&mut w, "// Generated code!")?;
39 writeln!(
40 &mut w,
41 "#![allow(unused_comparisons, unreachable_patterns)]"
42 )?;
43 writeln!(&mut w, "#![allow(clippy::let_and_return, clippy::eq_op)]")?;
44 writeln!(
45 &mut w,
46 "#![allow(clippy::excessive_precision, clippy::manual_range_contains, clippy::absurd_extreme_comparisons)]"
47 )?;
48 writeln!(&mut w, "#![deny(clippy::arithmetic_side_effects)]")?;
49 writeln!(&mut w)?;
50 writeln!(&mut w, "//! Message definitions from file `{:?}`", dbc_name)?;
51 writeln!(&mut w, "//!")?;
52 writeln!(&mut w, "//! - Version: `{:?}`", dbc.version())?;
53 writeln!(&mut w)?;
54 writeln!(&mut w, "use core::ops::BitOr;")?;
55 writeln!(&mut w, "use bitvec::prelude::*;")?;
56 writeln!(w, r##"#[cfg(feature = "arb")]"##)?;
57 writeln!(&mut w, "use arbitrary::{{Arbitrary, Unstructured}};")?;
58 writeln!(&mut w)?;
59
60 render_dbc(&mut w, &dbc).context("could not generate Rust code")?;
61
62 writeln!(&mut w)?;
63 writeln!(&mut w, "/// This is just to make testing easier")?;
64 writeln!(&mut w, "#[allow(dead_code)]")?;
65 writeln!(&mut w, "fn main() {{}}")?;
66 writeln!(&mut w)?;
67 w.write_all(include_bytes!("./includes/errors.rs"))?;
68 w.write_all(include_bytes!("./includes/arbitrary_helpers.rs"))?;
69 writeln!(&mut w)?;
70
71 Ok(())
72}
73
74fn render_dbc(mut w: impl Write, dbc: &DBC) -> Result<()> {
75 render_root_enum(&mut w, dbc)?;
76
77 for msg in get_relevant_messages(dbc) {
78 render_message(&mut w, msg, dbc)
79 .with_context(|| format!("write message `{}`", msg.message_name()))?;
80 writeln!(w)?;
81 }
82
83 Ok(())
84}
85
86fn render_root_enum(mut w: impl Write, dbc: &DBC) -> Result<()> {
87 writeln!(w, "/// All messages")?;
88 writeln!(w, "#[derive(Clone)]")?;
89 writeln!(w, r##"#[cfg_attr(feature = "debug", derive(Debug))]"##)?;
90 writeln!(w, "pub enum Messages {{")?;
91 {
92 let mut w = PadAdapter::wrap(&mut w);
93 for msg in get_relevant_messages(dbc) {
94 writeln!(w, "/// {}", msg.message_name())?;
95 writeln!(w, "{0}({0}),", type_name(msg.message_name()))?;
96 }
97 }
98 writeln!(&mut w, "}}")?;
99 writeln!(&mut w)?;
100
101 writeln!(w, "impl Messages {{")?;
102 {
103 let mut w = PadAdapter::wrap(&mut w);
104 writeln!(&mut w, "/// Read message from CAN frame")?;
105 writeln!(w, "#[inline(never)]")?;
106 writeln!(
107 &mut w,
108 "pub fn from_can_message(id: u32, payload: &[u8]) -> Result<Self, CanError> {{",
109 )?;
110 {
111 let mut w = PadAdapter::wrap(&mut w);
112 writeln!(&mut w)?;
113 writeln!(&mut w, "let res = match id {{")?;
114 {
115 let mut w = PadAdapter::wrap(&mut w);
116 for msg in get_relevant_messages(dbc) {
117 writeln!(
118 w,
119 "{} => Messages::{1}({1}::try_from(payload)?),",
120 msg.message_id().0,
121 type_name(msg.message_name())
122 )?;
123 }
124 writeln!(w, r#"n => return Err(CanError::UnknownMessageId(n)),"#)?;
125 }
126 writeln!(&mut w, "}};")?;
127 writeln!(&mut w, "Ok(res)")?;
128 }
129
130 writeln!(&mut w, "}}")?;
131 }
132 writeln!(&mut w, "}}")?;
133 writeln!(&mut w)?;
134
135 Ok(())
136}
137
138fn render_message(mut w: impl Write, msg: &Message, dbc: &DBC) -> Result<()> {
139 writeln!(w, "/// {}", msg.message_name())?;
140 writeln!(w, "///")?;
141 writeln!(w, "/// - ID: {0} (0x{0:x})", msg.message_id().0)?;
142 writeln!(w, "/// - Size: {} bytes", msg.message_size())?;
143 if let can_dbc::Transmitter::NodeName(transmitter) = msg.transmitter() {
144 writeln!(w, "/// - Transmitter: {}", transmitter)?;
145 }
146 if let Some(comment) = dbc.message_comment(*msg.message_id()) {
147 writeln!(w, "///")?;
148 for line in comment.trim().lines() {
149 writeln!(w, "/// {}", line)?;
150 }
151 }
152 writeln!(w, "#[derive(Clone, Copy)]")?;
153 writeln!(w, "pub struct {} {{", type_name(msg.message_name()))?;
154 {
155 let mut w = PadAdapter::wrap(&mut w);
156 writeln!(w, "raw: [u8; {}],", msg.message_size())?;
157 }
158 writeln!(w, "}}")?;
159 writeln!(w)?;
160
161 writeln!(w, "impl {} {{", type_name(msg.message_name()))?;
162 {
163 let mut w = PadAdapter::wrap(&mut w);
164
165 writeln!(
166 &mut w,
167 "pub const MESSAGE_ID: u32 = {};",
168 msg.message_id().0
169 )?;
170 writeln!(w)?;
171
172 for signal in msg
173 .signals()
174 .iter()
175 .filter(|sig| signal_to_rust_type(sig) != "bool")
176 {
177 let typ = signal_to_rust_type(signal);
178 writeln!(
179 &mut w,
180 "pub const {sig}_MIN: {typ} = {min}_{typ};",
181 sig = field_name(signal.name()).to_uppercase(),
182 typ = typ,
183 min = signal.min,
184 )?;
185
186 writeln!(
187 &mut w,
188 "pub const {sig}_MAX: {typ} = {max}_{typ};",
189 sig = field_name(signal.name()).to_uppercase(),
190 typ = typ,
191 max = signal.max,
192 )?;
193 }
194 writeln!(w)?;
195
196 writeln!(
197 &mut w,
198 "/// Construct new {} from values",
199 msg.message_name()
200 )?;
201 let args: Vec<String> = msg
202 .signals()
203 .iter()
204 .filter_map(|signal| {
205 if *signal.multiplexer_indicator() == MultiplexIndicator::Plain
206 || *signal.multiplexer_indicator() == MultiplexIndicator::Multiplexor
207 {
208 Some(format!(
209 "{}: {}",
210 field_name(signal.name()),
211 signal_to_rust_type(signal)
212 ))
213 } else {
214 None
215 }
216 })
217 .collect();
218 writeln!(
219 &mut w,
220 "pub fn new({}) -> Result<Self, CanError> {{",
221 args.join(", ")
222 )?;
223 {
224 let mut w = PadAdapter::wrap(&mut w);
225 writeln!(
226 &mut w,
227 "let mut res = Self {{ raw: [0u8; {}] }};",
228 msg.message_size()
229 )?;
230 for signal in msg.signals().iter() {
231 if *signal.multiplexer_indicator() == MultiplexIndicator::Plain {
232 writeln!(&mut w, "res.set_{0}({0})?;", field_name(signal.name()))?;
233 }
234
235 if *signal.multiplexer_indicator() == MultiplexIndicator::Multiplexor {
236 writeln!(&mut w, "res.set_{0}({0})?;", field_name(signal.name()))?;
237 }
238 }
239 writeln!(&mut w, "Ok(res)")?;
240 }
241 writeln!(&mut w, "}}")?;
242 writeln!(w)?;
243
244 writeln!(&mut w, "/// Access message payload raw value")?;
245 writeln!(
246 &mut w,
247 "pub fn raw(&self) -> &[u8; {}] {{",
248 msg.message_size()
249 )?;
250 {
251 let mut w = PadAdapter::wrap(&mut w);
252 writeln!(&mut w, "&self.raw")?;
253 }
254 writeln!(&mut w, "}}")?;
255 writeln!(w)?;
256
257 for signal in msg.signals().iter() {
258 match signal.multiplexer_indicator() {
259 MultiplexIndicator::Plain => render_signal(&mut w, signal, dbc, msg)
260 .with_context(|| format!("write signal impl `{}`", signal.name()))?,
261 MultiplexIndicator::Multiplexor => render_multiplexor_signal(&mut w, signal, msg)?,
262 MultiplexIndicator::MultiplexedSignal(_) => {}
263 MultiplexIndicator::MultiplexorAndMultiplexedSignal(_) => {}
264 }
265 }
266 }
267
268 writeln!(w, "}}")?;
269 writeln!(w)?;
270
271 writeln!(
272 w,
273 "impl core::convert::TryFrom<&[u8]> for {} {{",
274 type_name(msg.message_name())
275 )?;
276 {
277 let mut w = PadAdapter::wrap(&mut w);
278 writeln!(&mut w, "type Error = CanError;")?;
279 writeln!(w)?;
280 writeln!(w, "#[inline(always)]")?;
281 writeln!(
282 &mut w,
283 "fn try_from(payload: &[u8]) -> Result<Self, Self::Error> {{"
284 )?;
285 {
286 let mut w = PadAdapter::wrap(&mut w);
287 writeln!(
288 &mut w,
289 r#"if payload.len() != {} {{ return Err(CanError::InvalidPayloadSize); }}"#,
290 msg.message_size()
291 )?;
292 writeln!(&mut w, "let mut raw = [0u8; {}];", msg.message_size())?;
293 writeln!(
294 &mut w,
295 "raw.copy_from_slice(&payload[..{}]);",
296 msg.message_size()
297 )?;
298 writeln!(&mut w, "Ok(Self {{ raw }})")?;
299 }
300 writeln!(&mut w, "}}")?;
301 }
302 writeln!(w, "}}")?;
303 writeln!(w)?;
304
305 render_debug_impl(&mut w, msg)?;
306
307 render_arbitrary(&mut w, msg)?;
308
309 let enums_for_this_message = dbc.value_descriptions().iter().filter_map(|x| {
310 if let ValueDescription::Signal {
311 message_id,
312 signal_name,
313 value_descriptions,
314 } = x
315 {
316 if message_id != msg.message_id() {
317 return None;
318 }
319 let signal = dbc.signal_by_name(*message_id, signal_name).unwrap();
320 Some((signal, value_descriptions))
321 } else {
322 None
323 }
324 });
325 for (signal, variants) in enums_for_this_message {
326 write_enum(&mut w, signal, msg, variants.as_slice())?;
327 }
328
329 let multiplexor_signal = msg
330 .signals()
331 .iter()
332 .find(|s| *s.multiplexer_indicator() == MultiplexIndicator::Multiplexor);
333
334 if let Some(multiplexor_signal) = multiplexor_signal {
335 render_multiplexor_enums(w, dbc, msg, multiplexor_signal)?;
336 }
337
338 Ok(())
339}
340
341fn render_signal(mut w: impl Write, signal: &Signal, dbc: &DBC, msg: &Message) -> Result<()> {
342 writeln!(w, "/// {}", signal.name())?;
343 if let Some(comment) = dbc.signal_comment(*msg.message_id(), signal.name()) {
344 writeln!(w, "///")?;
345 for line in comment.trim().lines() {
346 writeln!(w, "/// {}", line)?;
347 }
348 }
349 writeln!(w, "///")?;
350 writeln!(w, "/// - Min: {}", signal.min)?;
351 writeln!(w, "/// - Max: {}", signal.max)?;
352 writeln!(w, "/// - Unit: {:?}", signal.unit())?;
353 writeln!(w, "/// - Receivers: {}", signal.receivers().join(", "))?;
354 writeln!(w, "#[inline(always)]")?;
355 if let Some(variants) = dbc.value_descriptions_for_signal(*msg.message_id(), signal.name()) {
356 let type_name = enum_name(msg, signal);
357
358 writeln!(
359 w,
360 "pub fn {}(&self) -> {} {{",
361 field_name(signal.name()),
362 type_name,
363 )?;
364 {
365 let match_on_raw_type = match signal_to_rust_type(signal).as_str() {
366 "bool" => |x: f64| format!("{}", x),
367 _ => |x: f64| format!("{}", x),
369 };
370 let mut w = PadAdapter::wrap(&mut w);
371 let read_fn = match signal.byte_order() {
372 can_dbc::ByteOrder::LittleEndian => {
373 let (start_bit, end_bit) = le_start_end_bit(signal, msg)?;
374
375 format!(
376 "self.raw.view_bits::<Lsb0>()[{start}..{end}].load_le::<{typ}>()",
377 typ = signal_to_rust_uint(signal),
378 start = start_bit,
379 end = end_bit,
380 )
381 }
382 can_dbc::ByteOrder::BigEndian => {
383 let (start_bit, end_bit) = be_start_end_bit(signal, msg)?;
384
385 format!(
386 "self.raw.view_bits::<Msb0>()[{start}..{end}].load_be::<{typ}>()",
387 typ = signal_to_rust_uint(signal),
388 start = start_bit,
389 end = end_bit
390 )
391 }
392 };
393
394 writeln!(&mut w, r#"let signal = {};"#, read_fn)?;
395 writeln!(&mut w)?;
396 writeln!(&mut w, "match signal {{")?;
397 {
398 let mut w = PadAdapter::wrap(&mut w);
399 for variant in variants {
400 let literal = match_on_raw_type(*variant.a());
401 writeln!(
402 &mut w,
403 "{} => {}::{},",
404 literal,
405 type_name,
406 enum_variant_name(variant.b())
407 )?;
408 }
409 writeln!(
410 &mut w,
411 "_ => {}::_Other(self.{}_raw()),",
412 type_name,
413 field_name(signal.name())
414 )?;
415 }
416 writeln!(&mut w, "}}")?;
417 }
418 writeln!(&mut w, "}}")?;
419 writeln!(w)?;
420 } else {
421 writeln!(
422 w,
423 "pub fn {}(&self) -> {} {{",
424 field_name(signal.name()),
425 signal_to_rust_type(signal)
426 )?;
427 {
428 let mut w = PadAdapter::wrap(&mut w);
429 writeln!(&mut w, "self.{}_raw()", field_name(signal.name()))?;
430 }
431 writeln!(&mut w, "}}")?;
432 writeln!(w)?;
433 }
434
435 writeln!(w, "/// Get raw value of {}", signal.name())?;
436 writeln!(w, "///")?;
437 writeln!(w, "/// - Start bit: {}", signal.start_bit)?;
438 writeln!(w, "/// - Signal size: {} bits", signal.signal_size)?;
439 writeln!(w, "/// - Factor: {}", signal.factor)?;
440 writeln!(w, "/// - Offset: {}", signal.offset)?;
441 writeln!(w, "/// - Byte order: {:?}", signal.byte_order())?;
442 writeln!(w, "/// - Value type: {:?}", signal.value_type())?;
443 writeln!(w, "#[inline(always)]")?;
444 writeln!(
445 w,
446 "pub fn {}_raw(&self) -> {} {{",
447 field_name(signal.name()),
448 signal_to_rust_type(signal)
449 )?;
450 {
451 let mut w = PadAdapter::wrap(&mut w);
452 signal_from_payload(&mut w, signal, msg).context("signal from payload")?;
453 }
454 writeln!(&mut w, "}}")?;
455 writeln!(w)?;
456
457 render_set_signal(&mut w, signal, msg)?;
458
459 Ok(())
460}
461
462fn render_set_signal(mut w: impl Write, signal: &Signal, msg: &Message) -> Result<()> {
463 writeln!(&mut w, "/// Set value of {}", signal.name())?;
464 writeln!(w, "#[inline(always)]")?;
465
466 let visibility = if *signal.multiplexer_indicator() == MultiplexIndicator::Multiplexor {
469 ""
470 } else {
471 "pub "
472 };
473
474 writeln!(
475 w,
476 "{}fn set_{}(&mut self, value: {}) -> Result<(), CanError> {{",
477 visibility,
478 field_name(signal.name()),
479 signal_to_rust_type(signal)
480 )?;
481
482 {
483 let mut w = PadAdapter::wrap(&mut w);
484
485 if signal.signal_size != 1 {
486 writeln!(w, r##"#[cfg(feature = "range_checked")]"##)?;
487 writeln!(
488 w,
489 r##"if value < {min}_{typ} || {max}_{typ} < value {{"##,
490 typ = signal_to_rust_type(signal),
491 min = signal.min(),
492 max = signal.max(),
493 )?;
494 {
495 let mut w = PadAdapter::wrap(&mut w);
496 writeln!(
497 w,
498 r##"return Err(CanError::ParameterOutOfRange {{ message_id: {message_id} }});"##,
499 message_id = msg.message_id().0,
500 )?;
501 }
502 writeln!(w, r"}}")?;
503 }
504 signal_to_payload(&mut w, signal, msg).context("signal to payload")?;
505 }
506
507 writeln!(&mut w, "}}")?;
508 writeln!(w)?;
509
510 Ok(())
511}
512
513fn render_set_signal_multiplexer(
514 mut w: impl Write,
515 multiplexor: &Signal,
516 msg: &Message,
517 switch_index: u64,
518) -> Result<()> {
519 writeln!(&mut w, "/// Set value of {}", multiplexor.name())?;
520 writeln!(w, "#[inline(always)]")?;
521 writeln!(
522 w,
523 "pub fn set_{enum_variant_wrapper}(&mut self, value: {enum_variant}) -> Result<(), CanError> {{",
524 enum_variant_wrapper = multiplexed_enum_variant_wrapper_name(switch_index).to_snake_case(),
525 enum_variant = multiplexed_enum_variant_name(msg, multiplexor, switch_index)?,
526 )?;
527
528 {
529 let mut w = PadAdapter::wrap(&mut w);
530
531 writeln!(&mut w, "let b0 = BitArray::<_, LocalBits>::new(self.raw);")?;
532 writeln!(&mut w, "let b1 = BitArray::<_, LocalBits>::new(value.raw);")?;
533 writeln!(&mut w, "self.raw = b0.bitor(b1).into_inner();")?;
534 writeln!(
535 &mut w,
536 "self.set_{}({})?;",
537 field_name(multiplexor.name()),
538 switch_index
539 )?;
540 writeln!(&mut w, "Ok(())",)?;
541 }
542
543 writeln!(&mut w, "}}")?;
544 writeln!(w)?;
545
546 Ok(())
547}
548
549fn render_multiplexor_signal(mut w: impl Write, signal: &Signal, msg: &Message) -> Result<()> {
550 writeln!(w, "/// Get raw value of {}", signal.name())?;
551 writeln!(w, "///")?;
552 writeln!(w, "/// - Start bit: {}", signal.start_bit)?;
553 writeln!(w, "/// - Signal size: {} bits", signal.signal_size)?;
554 writeln!(w, "/// - Factor: {}", signal.factor)?;
555 writeln!(w, "/// - Offset: {}", signal.offset)?;
556 writeln!(w, "/// - Byte order: {:?}", signal.byte_order())?;
557 writeln!(w, "/// - Value type: {:?}", signal.value_type())?;
558 writeln!(w, "#[inline(always)]")?;
559 writeln!(
560 w,
561 "pub fn {}_raw(&self) -> {} {{",
562 field_name(signal.name()),
563 signal_to_rust_type(signal)
564 )?;
565 {
566 let mut w = PadAdapter::wrap(&mut w);
567 signal_from_payload(&mut w, signal, msg).context("signal from payload")?;
568 }
569 writeln!(&mut w, "}}")?;
570 writeln!(w)?;
571
572 writeln!(
573 w,
574 "pub fn {}(&mut self) -> Result<{}, CanError> {{",
575 field_name(signal.name()),
576 multiplex_enum_name(msg, signal)?
577 )?;
578
579 let multiplexer_indexes: BTreeSet<u64> = msg
580 .signals()
581 .iter()
582 .filter_map(|s| {
583 if let MultiplexIndicator::MultiplexedSignal(index) = s.multiplexer_indicator() {
584 Some(index)
585 } else {
586 None
587 }
588 })
589 .cloned()
590 .collect();
591
592 {
593 let mut w = PadAdapter::wrap(&mut w);
594 writeln!(&mut w, "match self.{}_raw() {{", field_name(signal.name()))?;
595
596 {
597 let mut w = PadAdapter::wrap(&mut w);
598 for multiplexer_index in multiplexer_indexes.iter() {
599 writeln!(
600 &mut w,
601 "{idx} => Ok({enum_name}::{multiplexed_wrapper_name}({multiplexed_name}{{ raw: self.raw }})),",
602 idx = multiplexer_index,
603 enum_name = multiplex_enum_name(msg, signal)?,
604 multiplexed_wrapper_name = multiplexed_enum_variant_wrapper_name(*multiplexer_index),
605 multiplexed_name =
606 multiplexed_enum_variant_name(msg, signal, *multiplexer_index)?
607 )?;
608 }
609 writeln!(
610 &mut w,
611 "multiplexor => Err(CanError::InvalidMultiplexor {{ message_id: {}, multiplexor: multiplexor.into() }}),",
612 msg.message_id().0
613 )?;
614 }
615
616 writeln!(w, "}}")?;
617 }
618 writeln!(w, "}}")?;
619
620 render_set_signal(&mut w, signal, msg)?;
621
622 let mut multiplexed_signals = BTreeMap::new();
623 for signal in msg.signals() {
624 if let MultiplexIndicator::MultiplexedSignal(switch_index) = signal.multiplexer_indicator()
625 {
626 multiplexed_signals
627 .entry(switch_index)
628 .and_modify(|v: &mut Vec<&Signal>| v.push(signal))
629 .or_insert_with(|| vec![signal]);
630 }
631 }
632
633 for switch_index in multiplexer_indexes {
634 render_set_signal_multiplexer(&mut w, signal, msg, switch_index)?;
635 }
636
637 Ok(())
638}
639
640fn be_start_end_bit(signal: &Signal, msg: &Message) -> Result<(u64, u64)> {
641 let err = "calculating start bit";
642
643 let x = signal.start_bit.checked_div(8).context(err)?;
644 let x = x.checked_mul(8).context(err)?;
645
646 let y = signal.start_bit.checked_rem(8).context(err)?;
647 let y = 7u64.checked_sub(y).context(err)?;
648
649 let start_bit = x.checked_add(y).context(err)?;
650 let end_bit = start_bit
651 .checked_add(signal.signal_size)
652 .context("calculating last bit position")?;
653
654 let msg_bits = msg.message_size().checked_mul(8).unwrap();
655
656 ensure!(
657 start_bit <= msg_bits,
658 "signal starts at {}, but message is only {} bits",
659 start_bit,
660 msg_bits
661 );
662 ensure!(
663 end_bit <= msg_bits,
664 "signal ends at {}, but message is only {} bits",
665 end_bit,
666 msg_bits
667 );
668 Ok((start_bit, end_bit))
669}
670
671fn le_start_end_bit(signal: &Signal, msg: &Message) -> Result<(u64, u64)> {
672 let msg_bits = msg.message_size().checked_mul(8).unwrap();
673 let start_bit = signal.start_bit;
674 ensure!(
675 start_bit <= msg_bits,
676 "signal starts at {}, but message is only {} bits",
677 start_bit,
678 msg_bits
679 );
680
681 let end_bit = signal
682 .start_bit
683 .checked_add(signal.signal_size)
684 .context("overflow calculating last bit position")?;
685 ensure!(
686 end_bit <= msg_bits,
687 "signal ends at {}, but message is only {} bits",
688 end_bit,
689 msg_bits
690 );
691 Ok((start_bit, end_bit))
692}
693
694fn signal_from_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Result<()> {
695 let read_fn = match signal.byte_order() {
696 can_dbc::ByteOrder::LittleEndian => {
697 let (start_bit, end_bit) = le_start_end_bit(signal, msg)?;
698
699 format!(
700 "self.raw.view_bits::<Lsb0>()[{start}..{end}].load_le::<{typ}>()",
701 typ = signal_to_rust_uint(signal),
702 start = start_bit,
703 end = end_bit,
704 )
705 }
706 can_dbc::ByteOrder::BigEndian => {
707 let (start_bit, end_bit) = be_start_end_bit(signal, msg)?;
708
709 format!(
710 "self.raw.view_bits::<Msb0>()[{start}..{end}].load_be::<{typ}>()",
711 typ = signal_to_rust_uint(signal),
712 start = start_bit,
713 end = end_bit
714 )
715 }
716 };
717
718 writeln!(&mut w, r#"let signal = {};"#, read_fn)?;
719 writeln!(&mut w)?;
720
721 if *signal.value_type() == can_dbc::ValueType::Signed {
722 writeln!(
723 &mut w,
724 "let signal = {}::from_ne_bytes(signal.to_ne_bytes());",
725 signal_to_rust_int(signal)
726 )?;
727 };
728
729 if signal.signal_size == 1 {
730 writeln!(&mut w, "signal == 1")?;
731 } else if signal_is_float_in_rust(signal) {
732 writeln!(&mut w, "let factor = {}_f32;", signal.factor)?;
734 writeln!(&mut w, "let offset = {}_f32;", signal.offset)?;
735 writeln!(&mut w, "(signal as f32) * factor + offset")?;
736 } else {
737 writeln!(&mut w, "signal")?;
738 }
739 Ok(())
740}
741
742fn signal_to_payload(mut w: impl Write, signal: &Signal, msg: &Message) -> Result<()> {
743 if signal.signal_size == 1 {
744 writeln!(&mut w, "let value = value as u8;")?;
746 } else if signal_is_float_in_rust(signal) {
747 writeln!(&mut w, "let factor = {}_f32;", signal.factor)?;
749 writeln!(&mut w, "let offset = {}_f32;", signal.offset)?;
750 writeln!(
751 &mut w,
752 "let value = ((value - offset) / factor) as {};",
753 signal_to_rust_int(signal)
754 )?;
755 writeln!(&mut w)?;
756 }
757
758 if *signal.value_type() == can_dbc::ValueType::Signed {
759 writeln!(
760 &mut w,
761 "let value = {}::from_ne_bytes(value.to_ne_bytes());",
762 signal_to_rust_uint(signal)
763 )?;
764 };
765
766 match signal.byte_order() {
767 can_dbc::ByteOrder::LittleEndian => {
768 let (start_bit, end_bit) = le_start_end_bit(signal, msg)?;
769 writeln!(
770 &mut w,
771 r#"self.raw.view_bits_mut::<Lsb0>()[{start_bit}..{end_bit}].store_le(value);"#,
772 start_bit = start_bit,
773 end_bit = end_bit,
774 )?;
775 }
776 can_dbc::ByteOrder::BigEndian => {
777 let (start_bit, end_bit) = be_start_end_bit(signal, msg)?;
778 writeln!(
779 &mut w,
780 r#"self.raw.view_bits_mut::<Msb0>()[{start_bit}..{end_bit}].store_be(value);"#,
781 start_bit = start_bit,
782 end_bit = end_bit,
783 )?;
784 }
785 };
786
787 writeln!(&mut w, "Ok(())")?;
788 Ok(())
789}
790
791fn write_enum(
792 mut w: impl Write,
793 signal: &Signal,
794 msg: &Message,
795 variants: &[ValDescription],
796) -> Result<()> {
797 let type_name = enum_name(msg, signal);
798 let signal_rust_type = signal_to_rust_type(signal);
799
800 writeln!(w, "/// Defined values for {}", signal.name())?;
801 writeln!(w, "#[derive(Clone, Copy, PartialEq)]")?;
802 writeln!(w, r##"#[cfg_attr(feature = "debug", derive(Debug))]"##)?;
803 writeln!(w, "pub enum {} {{", type_name)?;
804 {
805 let mut w = PadAdapter::wrap(&mut w);
806 for variant in variants {
807 writeln!(w, "{},", enum_variant_name(variant.b()))?;
808 }
809 writeln!(w, "_Other({}),", signal_rust_type)?;
810 }
811 writeln!(w, "}}")?;
812 writeln!(w)?;
813
814 writeln!(w, "impl From<{type_name}> for {signal_rust_type} {{")?;
815 {
816 let match_on_raw_type = match signal_to_rust_type(signal).as_str() {
817 "bool" => |x: f64| format!("{}", (x as i64) == 1),
818 "f32" => |x: f64| format!("{}_f32", x),
819 _ => |x: f64| format!("{}", x as i64),
820 };
821
822 let mut w = PadAdapter::wrap(&mut w);
823 writeln!(w, "fn from(val: {type_name}) -> {signal_rust_type} {{")?;
824 {
825 let mut w = PadAdapter::wrap(&mut w);
826
827 writeln!(&mut w, "match val {{")?;
828 {
829 let mut w = PadAdapter::wrap(&mut w);
830 for variant in variants {
831 let literal = match_on_raw_type(*variant.a());
832 writeln!(
833 &mut w,
834 "{}::{} => {},",
835 type_name,
836 enum_variant_name(variant.b()),
837 literal,
838 )?;
839 }
840 writeln!(&mut w, "{}::_Other(x) => x,", type_name,)?;
841 }
842 writeln!(w, "}}")?;
843 }
844 writeln!(w, "}}")?;
845 }
846 writeln!(w, "}}")?;
847 writeln!(w)?;
848 Ok(())
849}
850
851fn signal_to_rust_int(signal: &Signal) -> String {
852 let sign = match signal.value_type() {
853 can_dbc::ValueType::Signed => "i",
854 can_dbc::ValueType::Unsigned => "u",
855 };
856
857 let size = match *signal.signal_size() {
858 n if n <= 8 => "8",
859 n if n <= 16 => "16",
860 n if n <= 32 => "32",
861 _ => "64",
862 };
863
864 format!("{}{}", sign, size)
865}
866
867fn signal_to_rust_uint(signal: &Signal) -> String {
868 let size = match *signal.signal_size() {
869 n if n <= 8 => "8",
870 n if n <= 16 => "16",
871 n if n <= 32 => "32",
872 _ => "64",
873 };
874
875 format!("u{}", size)
876}
877
878#[allow(clippy::float_cmp)]
879fn signal_is_float_in_rust(signal: &Signal) -> bool {
880 *signal.offset() != 0.0 || *signal.factor() != 1.0
881}
882
883fn signal_to_rust_type(signal: &Signal) -> String {
884 if signal.signal_size == 1 {
885 String::from("bool")
886 } else if signal_is_float_in_rust(signal) {
887 String::from("f32")
889 } else {
890 signal_to_rust_int(signal)
891 }
892}
893
894fn type_name(x: &str) -> String {
895 if keywords::is_keyword(x) || !x.starts_with(|c: char| c.is_ascii_alphabetic()) {
896 format!("X{}", x.to_pascal_case())
897 } else {
898 x.to_pascal_case()
899 }
900}
901
902fn field_name(x: &str) -> String {
903 if keywords::is_keyword(x) || !x.starts_with(|c: char| c.is_ascii_alphabetic()) {
904 format!("x{}", x.to_snake_case())
905 } else {
906 x.to_snake_case()
907 }
908}
909
910fn enum_name(msg: &Message, signal: &Signal) -> String {
911 let signal_name = signal
913 .name()
914 .trim_start_matches(|c: char| c.is_ascii_punctuation());
915
916 format!(
917 "{}{}",
918 enum_variant_name(msg.message_name()),
919 signal_name.to_pascal_case()
920 )
921}
922
923fn enum_variant_name(x: &str) -> String {
924 if keywords::is_keyword(x) || !x.starts_with(|c: char| c.is_ascii_alphabetic()) {
925 format!("X{}", x.to_pascal_case())
926 } else {
927 x.to_pascal_case()
928 }
929}
930
931fn multiplexed_enum_variant_wrapper_name(switch_index: u64) -> String {
932 format!("M{}", switch_index)
933}
934
935fn multiplex_enum_name(msg: &Message, multiplexor: &Signal) -> Result<String> {
936 ensure!(
937 matches!(
938 multiplexor.multiplexer_indicator(),
939 MultiplexIndicator::Multiplexor
940 ),
941 "signal {:?} is not the multiplexor",
942 multiplexor
943 );
944 Ok(format!(
945 "{}{}",
946 msg.message_name().to_pascal_case(),
947 multiplexor.name().to_pascal_case()
948 ))
949}
950
951fn multiplexed_enum_variant_name(
952 msg: &Message,
953 multiplexor: &Signal,
954 switch_index: u64,
955) -> Result<String> {
956 ensure!(
957 matches!(
958 multiplexor.multiplexer_indicator(),
959 MultiplexIndicator::Multiplexor
960 ),
961 "signal {:?} is not the multiplexor",
962 multiplexor
963 );
964
965 Ok(format!(
966 "{}{}M{}",
967 msg.message_name().to_pascal_case(),
968 multiplexor.name().to_pascal_case(),
969 switch_index
970 ))
971}
972
973fn render_debug_impl(mut w: impl Write, msg: &Message) -> Result<()> {
974 let typ = type_name(msg.message_name());
975 writeln!(w, r##"#[cfg(feature = "debug")]"##)?;
976 writeln!(w, r##"impl core::fmt::Debug for {} {{"##, typ)?;
977 {
978 let mut w = PadAdapter::wrap(&mut w);
979 writeln!(
980 w,
981 "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {{"
982 )?;
983 {
984 let mut w = PadAdapter::wrap(&mut w);
985 writeln!(w, r#"if f.alternate() {{"#)?;
986 {
987 let mut w = PadAdapter::wrap(&mut w);
988 writeln!(w, r#"f.debug_struct("{}")"#, typ)?;
989 {
990 let mut w = PadAdapter::wrap(&mut w);
991 for signal in msg.signals() {
992 if *signal.multiplexer_indicator() == MultiplexIndicator::Plain {
993 writeln!(
994 w,
995 r#".field("{field_name}", &self.{field_name}())"#,
996 field_name = field_name(signal.name()),
997 )?;
998 }
999 }
1000 }
1001 writeln!(w, r#".finish()"#)?;
1002 }
1003 writeln!(w, r#"}} else {{"#)?;
1004 {
1005 let mut w = PadAdapter::wrap(&mut w);
1006 writeln!(w, r#"f.debug_tuple("{}").field(&self.raw).finish()"#, typ)?;
1007 }
1008 writeln!(w, "}}")?;
1009 }
1010 writeln!(w, "}}")?;
1011 }
1012 writeln!(w, "}}")?;
1013 writeln!(w)?;
1014 Ok(())
1015}
1016
1017fn render_multiplexor_enums(
1018 mut w: impl Write,
1019 dbc: &DBC,
1020 msg: &Message,
1021 multiplexor_signal: &Signal,
1022) -> Result<()> {
1023 ensure!(
1024 *multiplexor_signal.multiplexer_indicator() == MultiplexIndicator::Multiplexor,
1025 "signal {} is not the multiplexor",
1026 multiplexor_signal.name(),
1027 );
1028
1029 let mut multiplexed_signals = BTreeMap::new();
1030 for signal in msg.signals() {
1031 if let MultiplexIndicator::MultiplexedSignal(switch_index) = signal.multiplexer_indicator()
1032 {
1033 multiplexed_signals
1034 .entry(switch_index)
1035 .and_modify(|v: &mut Vec<&Signal>| v.push(signal))
1036 .or_insert_with(|| vec![signal]);
1037 }
1038 }
1039
1040 writeln!(
1041 w,
1042 "/// Defined values for multiplexed signal {}",
1043 msg.message_name()
1044 )?;
1045 writeln!(w, r##"#[cfg_attr(feature = "debug", derive(Debug))]"##)?;
1046
1047 writeln!(
1048 w,
1049 "pub enum {} {{",
1050 multiplex_enum_name(msg, multiplexor_signal)?
1051 )?;
1052
1053 {
1054 let mut w = PadAdapter::wrap(&mut w);
1055 for (switch_index, _multiplexed_signals) in multiplexed_signals.iter() {
1056 writeln!(
1057 w,
1058 "{multiplexed_wrapper_name}({multiplexed_name}),",
1059 multiplexed_wrapper_name = multiplexed_enum_variant_wrapper_name(**switch_index),
1060 multiplexed_name =
1061 multiplexed_enum_variant_name(msg, multiplexor_signal, **switch_index)?
1062 )?;
1063 }
1064 }
1065 writeln!(w, "}}")?;
1066 writeln!(w)?;
1067
1068 for (switch_index, multiplexed_signals) in multiplexed_signals.iter() {
1069 writeln!(w, r##"#[derive(Default)]"##)?;
1070 writeln!(w, r##"#[cfg_attr(feature = "debug", derive(Debug))]"##)?;
1071 let struct_name = multiplexed_enum_variant_name(msg, multiplexor_signal, **switch_index)?;
1072 writeln!(
1073 w,
1074 "pub struct {} {{ raw: [u8; {}] }}",
1075 struct_name,
1076 msg.message_size()
1077 )?;
1078 writeln!(w)?;
1079
1080 writeln!(w, "impl {} {{", struct_name)?;
1081
1082 writeln!(
1083 w,
1084 "pub fn new() -> Self {{ Self {{ raw: [0u8; {}] }} }}",
1085 msg.message_size()
1086 )?;
1087
1088 for signal in multiplexed_signals {
1089 render_signal(&mut w, signal, dbc, msg)?;
1090 }
1091
1092 writeln!(w, "}}")?;
1093 writeln!(w)?;
1094 }
1095
1096 Ok(())
1097}
1098
1099fn render_arbitrary(mut w: impl Write, msg: &Message) -> Result<()> {
1100 writeln!(w, r##"#[cfg(feature = "arb")]"##)?;
1101 writeln!(
1102 w,
1103 "impl<'a> Arbitrary<'a> for {typ} {{",
1104 typ = type_name(msg.message_name())
1105 )?;
1106 {
1107 let mut w = PadAdapter::wrap(&mut w);
1108 writeln!(
1109 w,
1110 "fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self, arbitrary::Error> {{"
1111 )?;
1112 {
1113 let mut w = PadAdapter::wrap(&mut w);
1114 let filtered_signals: Vec<&Signal> = msg
1115 .signals()
1116 .iter()
1117 .filter(|signal| {
1118 *signal.multiplexer_indicator() == MultiplexIndicator::Plain
1119 || *signal.multiplexer_indicator() == MultiplexIndicator::Multiplexor
1120 })
1121 .collect();
1122
1123 for signal in filtered_signals.iter() {
1124 writeln!(
1125 w,
1126 "let {field_name} = {arbitrary_value};",
1127 field_name = field_name(signal.name()),
1128 arbitrary_value = signal_to_arbitrary(signal),
1129 )?;
1130 }
1131
1132 let args: Vec<String> = filtered_signals
1133 .iter()
1134 .map(|signal| field_name(signal.name()))
1135 .collect();
1136
1137 writeln!(
1138 w,
1139 "{typ}::new({args}).map_err(|_| arbitrary::Error::IncorrectFormat)",
1140 typ = type_name(msg.message_name()),
1141 args = args.join(",")
1142 )?;
1143 }
1144 writeln!(w, "}}")?;
1145 }
1146 writeln!(w, "}}")?;
1147
1148 Ok(())
1149}
1150
1151fn signal_to_arbitrary(signal: &Signal) -> String {
1152 if signal.signal_size == 1 {
1153 "u.int_in_range(0..=1)? == 1".to_string()
1154 } else if signal_is_float_in_rust(signal) {
1155 format!(
1156 "u.float_in_range({min}_f32..={max}_f32)?",
1157 min = signal.min(),
1158 max = signal.max()
1159 )
1160 } else {
1161 format!(
1162 "u.int_in_range({min}..={max})?",
1163 min = signal.min(),
1164 max = signal.max()
1165 )
1166 }
1167}
1168
1169fn get_relevant_messages(dbc: &DBC) -> impl Iterator<Item = &Message> {
1170 dbc.messages().iter().filter(|m| !message_ignored(m))
1171}
1172
1173fn message_ignored(message: &Message) -> bool {
1174 message.message_name() == "VECTOR__INDEPENDENT_SIG_MSG"
1176}