Skip to main content

dbc_codegen2/codegen/
rust.rs

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        //TODO: this should definitely happen on the IR level
131        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                    // plain.push(s);
142                }
143
144                MultiplexIndicator::MultiplexedSignal(v) => {
145                    muxed.entry(*v).or_default().push(s);
146                }
147
148                // intentionally skip
149                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        //TODO: no need to check if unsigned value is less than 0
732        quote! {
733            if value < #min || value > #max {
734                return Err(CanError::ValueOutOfRange);
735            }
736        }
737    }
738
739    //TODO: move the calculations to a transformer node
740    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            // bitvec cannot read f32/f64 from bits. Code finds the best fitting unsigned type
794            // and reads data into the type. The data is later casted to the correct float type.
795            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    //TODO: add a checker node that ensures that */+- operations
801    //      are safe. dbc-codegen uses saturating_*, checked_*
802    //TODO: do not perform multiplication when factor is 1
803    //      do not perform addition when offset is 0
804    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            // bitvec does not work with floats. See comment in decode_read!
816            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    //TODO: do not perform division when factor is 1
826    //      do not perform subtraction when offset is 0
827    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            // bitvec does not work with floats. See comment in decode_read!
840            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}