1use proc_macro2::TokenStream;
2use quote::{ToTokens, format_ident, quote};
3use syn::File;
4
5use crate::DbcFile;
6use crate::ir::message::{Message, MessageId};
7use crate::ir::signal::{MultiplexIndicator, Signal};
8use crate::ir::signal_layout::{SignalLayout, ByteOrder};
9use crate::ir::signal_value_type::{RustIntegerLiteral, RustType, RustFloatLiteral, IntReprType};
10use std::collections::BTreeMap;
11
12pub struct RustGen;
13
14impl RustGen {
15 pub fn generate(file: &DbcFile) -> String {
16 let imports = quote! {
17 use embedded_can::{Frame, Id, StandardId, ExtendedId};
18 use bitvec::prelude::*;
19 };
20
21 let messages = &file.messages;
22 let error_enum = ErrorEnum;
23 let msg_trait = MsgTrait;
24 let msg_enum = MsgEnum { messages };
25 let message_defs: Vec<_> = messages.iter().map(|m| MessageDef { msg: m, file }).collect();
26
27 let tokens = quote! {
28 #imports
29
30 #error_enum
31
32 #msg_trait
33
34 #msg_enum
35
36 #( #message_defs )*
37 };
38
39 let file: File = syn::parse2(tokens).unwrap();
40 prettyplease::unparse(&file)
41 }
42}
43
44struct ErrorEnum;
45
46impl ToTokens for ErrorEnum {
47 fn to_tokens(&self, tokens: &mut TokenStream) {
48 quote! {
49 #[derive(Debug, Clone)]
50 pub enum CanError {
51 UnknownFrameId,
52 UnknownMuxValue,
53 InvalidPayloadSize,
54 ValueOutOfRange,
55 }
56 }
57 .to_tokens(tokens);
58 }
59}
60
61struct MsgTrait;
62
63impl ToTokens for MsgTrait {
64 fn to_tokens(&self, tokens: &mut TokenStream) {
65 quote! {
66 pub trait CanMessage<const LEN: usize>: Sized {
67 fn try_from_frame(frame: &impl Frame) -> Result<Self, CanError>;
68 fn encode(&self) -> [u8; LEN];
69 }
70 }
71 .to_tokens(tokens);
72 }
73}
74
75struct MsgEnum<'a> {
76 messages: &'a [Message],
77}
78
79impl ToTokens for MsgEnum<'_> {
80 fn to_tokens(&self, tokens: &mut TokenStream) {
81 let variants = self.messages.iter().map(|msg| {
82 let name = format_ident!("{}", msg.name.upper_camel());
83 quote! { #name(#name) }
84 });
85
86 quote! {
87 #[derive(Debug, Clone)]
88 pub enum Msg {
89 #( #variants, )*
90 }
91 }
92 .to_tokens(tokens);
93
94 let arms = self.messages.iter().map(|msg| {
95 let name = format_ident!("{}", msg.name.upper_camel());
96 quote! { #name::ID => Msg::#name(#name::try_from_frame(frame)?) }
97 });
98
99 quote! {
100 impl Msg {
101 fn try_from(frame: &impl Frame) -> Result<Self, CanError> {
102 let result = match frame.id() {
103 #( #arms, )*
104 _ => return Err(CanError::UnknownFrameId),
105 };
106
107 Ok(result)
108 }
109 }
110 }
111 .to_tokens(tokens);
112 }
113}
114
115struct MessageDef<'a> {
116 msg: &'a Message,
117 file: &'a DbcFile,
118}
119
120impl ToTokens for MessageDef<'_> {
121 fn to_tokens(&self, tokens: &mut TokenStream) {
122 let msg = self.msg;
123
124 let signals: Vec<SignalCtx> = msg
125 .signal_idxs
126 .iter()
127 .map(|idx| SignalCtx::new(&self.file.signals[idx.0], self.file))
128 .collect();
129
130 let mut plain = Vec::new();
132 let mut muxed: BTreeMap<u64, Vec<&SignalCtx>> = BTreeMap::new();
133 let mut mux_signal: Option<&SignalCtx> = None;
134
135 for s in &signals {
136 match &s.signal.multiplexer {
137 MultiplexIndicator::Plain => plain.push(s),
138
139 MultiplexIndicator::Multiplexor => {
140 mux_signal = Some(s);
141 }
143
144 MultiplexIndicator::MultiplexedSignal(v) => {
145 muxed.entry(*v).or_default().push(s);
146 }
147
148 MultiplexIndicator::MultiplexorAndMultiplexedSignal(_v) => (),
150 }
151 }
152
153 if muxed.is_empty() {
154 self.generate_plain(tokens, &signals);
155 } else {
156 self.generate_mux(tokens, &signals, plain, muxed, mux_signal.unwrap());
157 }
158 }
159}
160
161impl MessageDef<'_> {
162 fn generate_plain(&self, tokens: &mut TokenStream, signals: &Vec<SignalCtx>) {
163 let msg = self.msg;
164 let name = format_ident!("{}", msg.name.upper_camel());
165 let signals: Vec<&SignalCtx> = signals.iter().collect();
166
167 let value_enums = signals
168 .iter()
169 .map(|s| SignalValueEnum { signal: s.signal });
170 let fields = Self::gen_fields(&signals);
171
172 let id_expr = match msg.id {
173 MessageId::Standard(id) => {
174 quote! {
175 Id::Standard(unsafe { StandardId::new_unchecked(#id) })
176 }
177 }
178 MessageId::Extended(id) => {
179 quote! {
180 Id::Extended(unsafe { ExtendedId::new_unchecked(#id) })
181 }
182 }
183 };
184
185 let constructor_params = Self::gen_constructor_params(&signals);
186 let constructor_fields = Self::gen_constructor_fields(&signals);
187 let constructor_validations = Self::gen_constructor_validations(&signals);
188 let getters = Self::gen_getters(&signals);
189 let setters = Self::gen_setters(&signals);
190 let len = msg.size as usize;
191
192 let impl_block = quote! {
193 impl #name {
194 pub const ID: Id = #id_expr;
195 pub const LEN: usize = #len;
196
197 pub fn new(
198 #( #constructor_params ),*
199 ) -> Result<Self, CanError> {
200 let mut msg = Self {
201 #( #constructor_fields ),*
202 };
203
204 #( #constructor_validations )*
205
206 Ok(msg)
207 }
208
209 #( #getters )*
210
211 #( #setters )*
212 }
213 };
214
215 let try_from = {
216 let reads = Self::gen_reads(&signals);
217 let fields = Self::gen_decode_fields(&signals);
218
219 quote! {
220 fn try_from_frame(frame: &impl Frame) -> Result<Self, CanError> {
221 let data = frame.data();
222 if data.len() < Self::LEN {
223 return Err(CanError::InvalidPayloadSize);
224 }
225
226 #( #reads )*
227
228 Ok(Self {
229 #( #fields, )*
230 })
231 }
232 }
233 };
234
235 let encode = {
236 let writes = Self::gen_writes(&signals);
237
238 quote! {
239 fn encode(&self) -> [u8; #name::LEN] {
240 let mut data = [0u8; #name::LEN];
241
242 #( #writes )*
243
244 data
245 }
246 }
247 };
248
249 quote! {
250 #( #value_enums )*
251
252 #[derive(Debug, Clone)]
253 pub struct #name {
254 #( #fields, )*
255 }
256
257 #impl_block
258
259 impl CanMessage<{ #name::LEN }> for #name {
260 #try_from
261 #encode
262 }
263 }
264 .to_tokens(tokens);
265 }
266
267 fn generate_mux(
268 &self,
269 tokens: &mut TokenStream,
270 signals: &Vec<SignalCtx>,
271 plain: Vec<&SignalCtx>,
272 muxed: BTreeMap<u64, Vec<&SignalCtx>>,
273 mux_signal: &SignalCtx,
274 ) {
275 let msg = self.msg;
276 let name = format_ident!("{}", msg.name.upper_camel());
277 let mux_enum_name = format_ident!("{}Mux", name);
278
279 let value_enums = signals
280 .iter()
281 .map(|s| SignalValueEnum { signal: s.signal });
282
283 let id_expr = match msg.id {
284 MessageId::Standard(id) => {
285 quote! { Id::Standard(unsafe { StandardId::new_unchecked(#id) }) }
286 }
287 MessageId::Extended(id) => {
288 quote! { Id::Extended(unsafe { ExtendedId::new_unchecked(#id) }) }
289 }
290 };
291
292 let len = msg.size as usize;
293
294 let plain_fields = Self::gen_fields(&plain);
295 let plain_getters = Self::gen_getters(&plain);
296 let plain_setters = Self::gen_setters(&plain);
297 let plain_constructor_params = Self::gen_constructor_params(&plain);
298 let plain_constructor_fields = Self::gen_constructor_fields(&plain);
299 let plain_constructor_validations = Self::gen_constructor_validations(&plain);
300
301 let constructor = quote! {
302 pub fn new(
303 #( #plain_constructor_params, )*
304 mux: #mux_enum_name
305 ) -> Result<Self, CanError> {
306
307 let mut msg = Self {
308 #( #plain_constructor_fields, )*
309 mux,
310 };
311
312 #( #plain_constructor_validations )*
313
314 Ok(msg)
315 }
316 };
317
318 let plain_reads = Self::gen_reads(&plain);
319 let plain_init = Self::gen_decode_fields(&plain);
320 let plain_writes = Self::gen_writes(&plain);
321
322 let mux_structs = muxed.iter().map(|(v, sigs)| {
323 let struct_name = format_ident!("{}Mux{}", name, v);
324
325 let fields = Self::gen_fields(&sigs);
326 let constructor_params = Self::gen_constructor_params(&sigs);
327 let constructor_fields = Self::gen_constructor_fields(&sigs);
328 let constructor_validations = Self::gen_constructor_validations(&sigs);
329
330 let getters = Self::gen_getters(&sigs);
331 let setters = Self::gen_setters(&sigs);
332
333 let reads = Self::gen_reads(&sigs);
334 let inits = Self::gen_decode_fields(&sigs);
335 let writes = Self::gen_writes(&sigs);
336
337 quote! {
338 #[derive(Debug, Clone)]
339 pub struct #struct_name {
340 #( #fields, )*
341 }
342
343 impl #struct_name {
344
345 pub fn new(
346 #( #constructor_params ),*
347 ) -> Result<Self, CanError> {
348
349 let mut msg = Self {
350 #( #constructor_fields ),*
351 };
352
353 #( #constructor_validations )*
354
355 Ok(msg)
356 }
357
358 #( #getters )*
359
360 #( #setters )*
361
362 fn decode_from(data: &[u8]) -> Result<Self, CanError> {
363
364 #( #reads )*
365
366 Ok(Self {
367 #( #inits, )*
368 })
369 }
370
371 fn encode_into(&self, data: &mut [u8]) {
372 #( #writes )*
373 }
374 }
375 }
376 });
377
378 let mux_variants = muxed.keys().map(|v| {
379 let struct_name = format_ident!("{}Mux{}", name, v);
380 let variant = format_ident!("V{}", v);
381
382 quote! { #variant(#struct_name) }
383 });
384
385 let mux_raw_ty = mux_signal.raw_rust_type();
386 let (mux_start, mux_end) = mux_signal.start_end_bit();
387 let mux_order = mux_signal.bitvec_order();
388
389 let mux_encode_arms = muxed.keys().map(|v| {
390 let variant = format_ident!("V{}", v);
391 let mux_store = mux_signal.store_fn();
392
393 quote! {
394 #mux_enum_name::#variant(inner) => {
395
396 data.view_bits_mut::<#mux_order>()[#mux_start..#mux_end]
397 .#mux_store(#v as #mux_raw_ty);
398
399 inner.encode_into(&mut data);
400 }
401 }
402 });
403
404 let mux_read = mux_signal.decode_read();
405 let mux_raw = mux_signal.raw_ident();
406
407 let mux_decode_arms = muxed.keys().map(|v| {
408 let lit = mux_signal.signal.physical_type.literal(*v as i64);
409 let struct_name = format_ident!("{}Mux{}", name, v);
410 let variant = format_ident!("V{}", v);
411
412 quote! {
413 #lit => #mux_enum_name::#variant(#struct_name::decode_from(data)?)
414 }
415 });
416
417
418 let struct_def = quote! {
419 #[derive(Debug, Clone)]
420 pub struct #name {
421 #( #plain_fields, )*
422 pub mux: #mux_enum_name,
423 }
424 };
425
426 let trait_impl = quote! {
427 impl CanMessage<{ #name::LEN }> for #name {
428
429 fn try_from_frame(frame: &impl Frame) -> Result<Self, CanError> {
430
431 let data = frame.data();
432
433 if data.len() < Self::LEN {
434 return Err(CanError::InvalidPayloadSize);
435 }
436
437 #( #plain_reads )*
438
439 #mux_read
440
441 let mux = match #mux_raw {
442
443 #( #mux_decode_arms, )*
444
445 _ => return Err(CanError::UnknownMuxValue),
446 };
447
448 Ok(Self {
449 #( #plain_init, )*
450 mux,
451 })
452 }
453
454 fn encode(&self) -> [u8; #name::LEN] {
455
456 let mut data = [0u8; #name::LEN];
457
458 #( #plain_writes )*
459
460 match &self.mux {
461 #( #mux_encode_arms )*
462 }
463
464 data
465 }
466 }
467 };
468
469 let impl_block = quote! {
470 impl #name {
471
472 pub const ID: Id = #id_expr;
473 pub const LEN: usize = #len;
474
475 #constructor
476
477 #( #plain_getters )*
478
479 #( #plain_setters )*
480 }
481 };
482
483 quote! {
484
485 #( #value_enums )*
486
487 #( #mux_structs )*
488
489 #[derive(Debug, Clone)]
490 pub enum #mux_enum_name {
491 #( #mux_variants, )*
492 }
493
494 #struct_def
495
496 #impl_block
497
498 #trait_impl
499 }
500 .to_tokens(tokens);
501 }
502
503 fn gen_fields(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
504 signals.iter().map(|s| {
505 let field = s.field_ident();
506 let ty = s.rust_type();
507 quote! { pub #field: #ty }
508 })
509 }
510
511 fn gen_constructor_params(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
512 signals.iter().map(|s| {
513 let field = s.field_ident();
514 let ty = s.rust_type();
515 quote! { #field: #ty }
516 })
517 }
518
519 fn gen_constructor_fields(signals: &[&SignalCtx]) -> impl Iterator<Item = syn::Ident> {
520 signals.iter().map(|s| s.field_ident())
521 }
522
523 fn gen_constructor_validations(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
524 signals.iter().map(|s| {
525 let field = s.field_ident();
526 let setter = s.setter_ident();
527
528 quote! {
529 msg.#setter(msg.#field)?;
530 }
531 })
532 }
533
534 fn gen_getters(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
535 signals.iter().map(|s| {
536 let field = s.field_ident();
537 let ty = s.rust_type();
538
539 quote! {
540 pub fn #field(&self) -> #ty {
541 self.#field
542 }
543 }
544 })
545 }
546
547 fn gen_setters(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
548 signals.iter().map(|s| {
549 let field = s.field_ident();
550 let setter = s.setter_ident();
551 let ty = s.rust_type();
552 let check = s.range_check();
553
554 quote! {
555 pub fn #setter(&mut self, value: #ty) -> Result<(), CanError> {
556 #check
557 self.#field = value;
558 Ok(())
559 }
560 }
561 })
562 }
563
564 fn gen_reads(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
565 signals.iter().map(|s| s.decode_read())
566 }
567
568 fn gen_decode_fields(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
569 signals.iter().map(|s| s.decode_field())
570 }
571
572 fn gen_writes(signals: &[&SignalCtx]) -> impl Iterator<Item = TokenStream> {
573 signals.iter().map(|s| s.encode_write())
574 }
575}
576
577struct SignalValueEnum<'a> {
578 signal: &'a Signal,
579}
580
581impl ToTokens for SignalValueEnum<'_> {
582 fn to_tokens(&self, tokens: &mut TokenStream) {
583 let signal = self.signal;
584
585 let Some(enum_def) = &signal.signal_value_enum else {
586 return;
587 };
588
589 let enum_name = format_ident!("{}", signal.name.upper_camel());
590 let repr_type = &signal.physical_type;
591 let rust_type = format_ident!("{}", repr_type.as_rust_type());
592
593 let variants = enum_def.variants.iter().map(|vd| {
594 let name = format_ident!("{}", vd.description);
595 quote! { #name }
596 });
597
598 let from_arms = enum_def.variants.iter().map(|vd| {
599 let name = format_ident!("{}", vd.description);
600 let value = repr_type.literal(vd.value);
601 quote! { #value => #enum_name::#name }
602 });
603
604 let into_arms = enum_def.variants.iter().map(|vd| {
605 let name = format_ident!("{}", vd.description);
606 let value = repr_type.literal(vd.value);
607 quote! { #enum_name::#name => #value }
608 });
609
610 quote! {
611 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
612 pub enum #enum_name {
613 #( #variants, )*
614 _Other(#rust_type),
615 }
616
617 impl From<#rust_type> for #enum_name {
618 fn from(val: #rust_type) -> Self {
619 match val {
620 #( #from_arms, )*
621 _ => #enum_name::_Other(val),
622 }
623 }
624 }
625
626 impl From<#enum_name> for #rust_type {
627 fn from(val: #enum_name) -> Self {
628 match val {
629 #( #into_arms, )*
630 #enum_name::_Other(v) => v,
631 }
632 }
633 }
634 }
635 .to_tokens(tokens);
636 }
637}
638
639struct SignalCtx<'a> {
640 signal: &'a Signal,
641 layout: &'a SignalLayout,
642}
643
644impl<'a> SignalCtx<'a> {
645 fn new(signal: &'a Signal, file: &'a DbcFile) -> Self {
646 Self {
647 signal,
648 layout: &file.signal_layouts[signal.layout.0],
649 }
650 }
651
652 fn field_ident(&self) -> syn::Ident {
653 format_ident!("{}", self.signal.name.lower())
654 }
655
656 fn setter_ident(&self) -> syn::Ident {
657 format_ident!("set_{}", self.signal.name.lower())
658 }
659
660 fn raw_ident(&self) -> syn::Ident {
661 format_ident!("raw_{}", self.signal.name.lower())
662 }
663
664 fn enum_ident(&self) -> syn::Ident {
665 format_ident!("{}", self.signal.name.upper_camel())
666 }
667
668 fn rust_type(&self) -> syn::Ident {
669 if self.signal.signal_value_enum.is_some() {
670 self.enum_ident()
671 } else {
672 format_ident!("{}", self.signal.physical_type.as_rust_type())
673 }
674 }
675
676 fn raw_rust_type(&self) -> syn::Ident {
677 format_ident!("{}", self.signal.physical_type.as_rust_type())
678 }
679
680 fn is_enum(&self) -> bool {
681 self.signal.signal_value_enum.is_some()
682 }
683
684 fn is_float(&self) -> bool {
685 self.signal.physical_type.is_float()
686 }
687
688 fn factor_literal(&self) -> TokenStream {
689 let phys = &self.signal.physical_type;
690 if self.is_float() {
691 phys.fliteral(self.layout.factor).to_token_stream()
692 } else {
693 phys.literal(self.layout.factor as i64).to_token_stream()
694 }
695 }
696
697 fn offset_literal(&self) -> TokenStream {
698 let phys = &self.signal.physical_type;
699 if self.is_float() {
700 phys.fliteral(self.layout.offset).to_token_stream()
701 } else {
702 phys.literal(self.layout.offset as i64).to_token_stream()
703 }
704 }
705
706 fn int_repr_for_float(&self) -> syn::Ident {
707 let ty = IntReprType::from_size_sign(self.layout.size, false);
708 format_ident!("{}", ty.as_rust_type())
709 }
710
711 fn f64_to_correct_literal_with_type(&self, value: f64) -> TokenStream {
712 let phys = &self.signal.physical_type;
713 if self.is_float() {
714 phys.fliteral(value).to_token_stream()
715 } else {
716 phys.literal(value as i64).to_token_stream()
717 }
718 }
719
720 fn range_check(&self) -> TokenStream {
721 if self.is_enum() {
722 return quote! {};
723 }
724
725 let min = self.layout.min;
726 let max = self.layout.max;
727
728 let min = self.f64_to_correct_literal_with_type(min);
729 let max = self.f64_to_correct_literal_with_type(max);
730
731 quote! {
733 if value < #min || value > #max {
734 return Err(CanError::ValueOutOfRange);
735 }
736 }
737 }
738
739 fn start_end_bit(&self) -> (usize, usize) {
741 match self.layout.byte_order {
742 ByteOrder::LittleEndian => {
743 let start = self.layout.start_bit as usize;
744 let end = start + self.layout.size as usize;
745 (start, end)
746 }
747
748 ByteOrder::BigEndian => {
749 let start_bit = self.layout.start_bit;
750
751 let x = (start_bit / 8) * 8;
752 let y = 7 - (start_bit % 8);
753
754 let start = (x + y) as usize;
755 let end = start + self.layout.size as usize;
756
757 (start, end)
758 }
759 }
760 }
761
762 fn bitvec_order(&self) -> TokenStream {
763 match self.layout.byte_order {
764 ByteOrder::LittleEndian => quote! { Lsb0 },
765 ByteOrder::BigEndian => quote! { Msb0 },
766 }
767 }
768
769 fn load_fn(&self) -> syn::Ident {
770 match self.layout.byte_order {
771 ByteOrder::LittleEndian => format_ident!("load_le"),
772 ByteOrder::BigEndian => format_ident!("load_be"),
773 }
774 }
775
776 fn store_fn(&self) -> syn::Ident {
777 match self.layout.byte_order {
778 ByteOrder::LittleEndian => format_ident!("store_le"),
779 ByteOrder::BigEndian => format_ident!("store_be"),
780 }
781 }
782
783 fn decode_read(&self) -> TokenStream {
784 let raw = self.raw_ident();
785 let (start, end) = self.start_end_bit();
786 let order = self.bitvec_order();
787 let load = self.load_fn();
788
789 if self.is_enum() || !self.is_float() {
790 let raw_ty = self.raw_rust_type();
791 quote! { let #raw = data.view_bits::<#order>()[#start..#end].#load::<#raw_ty>(); }
792 } else {
793 let int_ty = self.int_repr_for_float();
796 quote! { let #raw = data.view_bits::<#order>()[#start..#end].#load::<#int_ty>(); }
797 }
798 }
799
800 fn decode_field(&self) -> TokenStream {
805 let field = self.field_ident();
806 let raw = self.raw_ident();
807
808 if self.is_enum() {
809 let enum_name = self.enum_ident();
810 let raw_ty = self.raw_rust_type();
811 quote! { #field: #enum_name::from(#raw as #raw_ty) }
812 } else if self.is_float() {
813 let factor = self.factor_literal();
814 let offset = self.offset_literal();
815 let ty = format_ident!("{}", self.signal.physical_type.as_rust_type());
817 quote! { #field: (#raw as #ty) * (#factor) + (#offset) }
818 } else {
819 let factor = self.factor_literal();
820 let offset = self.offset_literal();
821 quote! { #field: (#raw) * (#factor) + (#offset) }
822 }
823 }
824
825 fn encode_write(&self) -> TokenStream {
828 let field = self.field_ident();
829 let (start, end) = self.start_end_bit();
830 let order = self.bitvec_order();
831 let store = self.store_fn();
832
833 if self.is_enum() {
834 let ty = self.raw_rust_type();
835 quote! { data.view_bits_mut::<#order>()[#start..#end].#store(#ty::from(self.#field)); }
836 } else if self.is_float() {
837 let factor = self.factor_literal();
838 let offset = self.offset_literal();
839 let int_ty = self.int_repr_for_float();
841 quote! {
842 data.view_bits_mut::<#order>()[#start..#end].#store(((self.#field - (#offset)) / (#factor)) as #int_ty);
843 }
844 } else {
845 let factor = self.factor_literal();
846 let offset = self.offset_literal();
847 quote! {
848 data.view_bits_mut::<#order>()[#start..#end].#store((self.#field - (#offset)) / (#factor));
849 }
850 }
851 }
852
853}