@@ -378,10 +378,12 @@ pub fn fields(
378378 // Reader and writer use one common `Enum_A` unless a fields have two `enumeratedValues`,
379379 // then we have one for read-only `Enum_A` and another for write-only `Enum_AW`
380380 let name_constant_case_a = Ident :: new ( & ( name_constant_case. clone ( ) + "_A" ) , span) ;
381- let mut name_constant_case_aw = & name_constant_case_a;
381+ let mut value_write_ty = & name_constant_case_a;
382382
383383 let mut evs_r = None ;
384384
385+ // Reads dim information from svd field. If it has dim index, the field is treated as an
386+ // array; or it should be treated as a single register field.
385387 let field_dim = match f {
386388 Field :: Array ( _, de) => {
387389 let first = if let Some ( dim_index) = & de. dim_index {
@@ -412,27 +414,8 @@ pub fn fields(
412414 }
413415 } ;
414416
417+ // If this field can be read, generate read proxy structure and value structure.
415418 if can_read {
416- let mut readerdoc = if let Some ( ( _, _, _, _, suffixes_str) ) = & field_dim {
417- format ! (
418- "Fields `{}` reader - {}" ,
419- util:: replace_suffix( & f. name, suffixes_str) ,
420- description,
421- )
422- } else {
423- format ! ( "Field `{}` reader - {}" , f. name, description)
424- } ;
425- if let Some ( action) = f. read_action {
426- readerdoc += match action {
427- ReadAction :: Clear => "\n \n The field is **cleared** (set to zero) following a read operation." ,
428- ReadAction :: Set => "\n \n The field is **set** (set to ones) following a read operation." ,
429- ReadAction :: Modify => "\n \n The field is **modified** in some way after a read operation." ,
430- ReadAction :: ModifyExternal => "\n \n One or more dependent resources other than the current field are immediately affected by a read operation." ,
431- } ;
432- }
433-
434- let reader_ty = Ident :: new ( & ( name_constant_case. clone ( ) + "_R" ) , span) ;
435-
436419 let cast = if width == 1 {
437420 quote ! { != 0 }
438421 } else {
@@ -453,6 +436,29 @@ pub fn fields(
453436 }
454437 } ;
455438
439+ // get a brief description for this field
440+ // the suffix string from field name is removed in brief description.
441+ let mut field_reader_brief = if let Some ( ( _, _, _, _, suffixes_str) ) = & field_dim {
442+ format ! (
443+ "Fields `{}` reader - {}" ,
444+ util:: replace_suffix( & f. name, suffixes_str) ,
445+ description,
446+ )
447+ } else {
448+ format ! ( "Field `{}` reader - {}" , f. name, description)
449+ } ;
450+ if let Some ( action) = f. read_action {
451+ field_reader_brief += match action {
452+ ReadAction :: Clear => "\n \n The field is **cleared** (set to zero) following a read operation." ,
453+ ReadAction :: Set => "\n \n The field is **set** (set to ones) following a read operation." ,
454+ ReadAction :: Modify => "\n \n The field is **modified** in some way after a read operation." ,
455+ ReadAction :: ModifyExternal => "\n \n One or more dependent resources other than the current field are immediately affected by a read operation." ,
456+ } ;
457+ }
458+
459+ // name of read proxy type
460+ let reader_ty = Ident :: new ( & ( name_constant_case. clone ( ) + "_R" ) , span) ;
461+
456462 if let Some ( ( first, dim, increment, suffixes, suffixes_str) ) = & field_dim {
457463 let offset_calc = calculate_offset ( * first, * increment, offset, true ) ;
458464 let value = quote ! { ( ( self . bits >> #offset_calc) & #hexmask) #cast } ;
@@ -507,9 +513,13 @@ pub fn fields(
507513 } ) ;
508514 }
509515
516+ // collect information on items in enumeration to generate it later.
510517 let mut enum_items = TokenStream :: new ( ) ;
511- let mut derived = false ;
518+ let mut should_derive_reader = true ;
512519 let mut ftype = fty. clone ( ) ;
520+
521+ // if this is an enumeratedValues not derived from base, generate the enum structure
522+ // and implement functions for each value in enumeration.
513523 if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Read ) {
514524 evs_r = Some ( evs. clone ( ) ) ;
515525
@@ -528,13 +538,26 @@ pub fn fields(
528538
529539 let pc = pc_orig. to_sanitized_constant_case ( ) ;
530540 let base_pc_r = Ident :: new ( & ( pc + "_R" ) , span) ;
531- derive_from_base ( mod_items, & base, & reader_ty, & base_pc_r, & readerdoc) ;
532- derived = true ;
541+ derive_from_base (
542+ mod_items,
543+ & base,
544+ & reader_ty,
545+ & base_pc_r,
546+ & field_reader_brief,
547+ ) ;
548+ should_derive_reader = false ;
533549 } else {
550+ // do we have finite definition of this enumeration in svd? If not, the later code would
551+ // return an Option when the value read from field does not match any defined values.
534552 let has_reserved_variant = evs. values . len ( ) != ( 1 << width) ;
553+ // parse enum variants from enumeratedValues svd record
535554 let variants = Variant :: from_enumerated_values ( evs, config. pascal_enum_values ) ?;
536555
556+ // if there's no variant defined in enumeratedValues, generate enumeratedValues with new-type
557+ // wrapper struct, and generate From conversation only.
558+ // else, generate enumeratedValues into a Rust enum with functions for each variant.
537559 if variants. is_empty ( ) {
560+ // generate struct VALUE_READ_TY_A(fty) and From<fty> for VALUE_READ_TY_A.
538561 add_with_no_variants (
539562 mod_items,
540563 & name_constant_case_a,
@@ -543,6 +566,7 @@ pub fn fields(
543566 rv,
544567 ) ;
545568 } else {
569+ // generate enum VALUE_READ_TY_A { ... each variants ... } and and From<fty> for VALUE_READ_TY_A.
546570 add_from_variants (
547571 mod_items,
548572 & variants,
@@ -552,6 +576,8 @@ pub fn fields(
552576 rv,
553577 ) ;
554578
579+ // prepare code for each match arm. If we have reserved variant, the match operation would
580+ // return an Option, thus we wrap the return value with Some.
555581 let mut arms = TokenStream :: new ( ) ;
556582 for v in variants. iter ( ) . map ( |v| {
557583 let i = util:: unsuffixed_or_bool ( v. value , width) ;
@@ -566,6 +592,11 @@ pub fn fields(
566592 arms. extend ( v) ;
567593 }
568594
595+ // if we have reserved variant, for all values other than defined we return None.
596+ // if svd suggests it only would return defined variants but FieldReader has
597+ // other values, it's regarded as unreachable and we enter unreachable! macro.
598+ // This situation is rare and only exists if unsafe code casts any illegal value
599+ // into a FieldReader structure.
569600 if has_reserved_variant {
570601 arms. extend ( quote ! {
571602 _ => None ,
@@ -576,6 +607,8 @@ pub fn fields(
576607 } ) ;
577608 }
578609
610+ // prepare the `variant` function. This function would return field value in
611+ // Rust structure; if we have reserved variant we return by Option.
579612 if has_reserved_variant {
580613 enum_items. extend ( quote ! {
581614 #[ doc = "Get enumerated values variant" ]
@@ -597,6 +630,7 @@ pub fn fields(
597630 } } ) ;
598631 }
599632
633+ // for each variant defined, we generate an `is_variant` function.
600634 for v in & variants {
601635 let pc = & v. pc ;
602636 let sc = & v. nksc ;
@@ -624,17 +658,20 @@ pub fn fields(
624658 ftype = name_constant_case_a. clone ( ) ;
625659 }
626660 }
627- if !derived {
661+
662+ // derive the read proxy structure if necessary.
663+ if should_derive_reader {
628664 let reader = if width == 1 {
629665 quote ! { crate :: BitReader <#ftype> }
630666 } else {
631667 quote ! { crate :: FieldReader <#fty, #ftype> }
632668 } ;
633669 mod_items. extend ( quote ! {
634- #[ doc = #readerdoc ]
670+ #[ doc = #field_reader_brief ]
635671 pub type #reader_ty = #reader;
636672 } ) ;
637673 }
674+ // generate the enumeration functions prepared before.
638675 if !enum_items. is_empty ( ) {
639676 mod_items. extend ( quote ! {
640677 impl #reader_ty {
@@ -644,12 +681,15 @@ pub fn fields(
644681 }
645682 }
646683
684+ // If this field can be written, generate write proxy. Generate write value if it differs from
685+ // the read value, or else we reuse read value.
647686 if can_write {
648687 let mwv = f
649688 . modified_write_values
650689 . or ( register. modified_write_values )
651690 . unwrap_or_default ( ) ;
652- let writerdoc = if let Some ( ( _, _, _, _, suffixes_str) ) = & field_dim {
691+ // gets a brief of write proxy
692+ let field_writer_brief = if let Some ( ( _, _, _, _, suffixes_str) ) = & field_dim {
653693 format ! (
654694 "Fields `{}` writer - {}" ,
655695 util:: replace_suffix( & f. name, suffixes_str) ,
@@ -660,45 +700,37 @@ pub fn fields(
660700 } ;
661701
662702 let new_pc_aw = Ident :: new ( & ( name_constant_case. clone ( ) + "_AW" ) , span) ;
703+ // name of write proxy type
663704 let writer_ty = Ident :: new ( & ( name_constant_case. clone ( ) + "_W" ) , span) ;
664705
665706 let mut proxy_items = TokenStream :: new ( ) ;
666707 let mut unsafety = unsafety ( f. write_constraint . as_ref ( ) , width) ;
667708
668- let mut derived = false ;
709+ let mut should_derive_writer = true ;
710+ // if we writes to enumeratedValues, generate its structure if it differs from read structure.
669711 if let Some ( ( evs, base) ) = lookup_filter ( & lookup_results, Usage :: Write ) {
712+ // parse variants from enumeratedValues svd record
670713 let variants = Variant :: from_enumerated_values ( evs, config. pascal_enum_values ) ?;
671714
715+ // if the write structure is finite, it can be safely written.
672716 if variants. len ( ) == 1 << width {
673717 unsafety = false ;
674718 }
675719
676720 if Some ( evs) != evs_r. as_ref ( ) {
677- name_constant_case_aw = & new_pc_aw;
721+ value_write_ty = & new_pc_aw;
678722 if let Some ( base) = base. as_ref ( ) {
679723 let pc = util:: replace_suffix ( base. field , "" ) ;
680724 let pc = pc. to_sanitized_constant_case ( ) ;
681725 let base_pc_w = Ident :: new ( & ( pc + "_AW" ) , span) ;
682- derive_from_base (
683- mod_items,
684- base,
685- name_constant_case_aw,
686- & base_pc_w,
687- & description,
688- ) ;
726+ derive_from_base ( mod_items, base, value_write_ty, & base_pc_w, & description) ;
689727 } else if variants. is_empty ( ) {
690- add_with_no_variants (
691- mod_items,
692- name_constant_case_aw,
693- & fty,
694- & description,
695- rv,
696- ) ;
728+ add_with_no_variants ( mod_items, value_write_ty, & fty, & description, rv) ;
697729 } else {
698730 add_from_variants (
699731 mod_items,
700732 & variants,
701- name_constant_case_aw ,
733+ value_write_ty ,
702734 & fty,
703735 & description,
704736 rv,
@@ -711,32 +743,39 @@ pub fn fields(
711743 let pc = util:: replace_suffix ( base. field , "" ) ;
712744 let pc = pc. to_sanitized_constant_case ( ) ;
713745 let base_pc_w = Ident :: new ( & ( pc + "_W" ) , span) ;
714- derive_from_base ( mod_items, & base, & writer_ty, & base_pc_w, & writerdoc) ;
715- derived = true ;
746+ derive_from_base (
747+ mod_items,
748+ & base,
749+ & writer_ty,
750+ & base_pc_w,
751+ & field_writer_brief,
752+ ) ;
753+ should_derive_writer = false ;
716754 }
717755 _ => {
718756 if !variants. is_empty ( ) {
757+ // for each variant defined, generate a write function to this field.
719758 for v in & variants {
720759 let pc = & v. pc ;
721760 let sc = & v. sc ;
722-
723761 let doc = util:: escape_brackets ( util:: respace ( & v. doc ) . as_ref ( ) ) ;
724762 proxy_items. extend ( quote ! {
725763 #[ doc = #doc]
726764 #inline
727765 pub fn #sc( self ) -> & ' a mut W {
728- self . variant( #name_constant_case_aw :: #pc)
766+ self . variant( #value_write_ty :: #pc)
729767 }
730768 } ) ;
731769 }
732770 }
733771 }
734772 }
735773 } else {
736- name_constant_case_aw = & fty;
774+ value_write_ty = & fty;
737775 }
738776
739- if !derived {
777+ // derive writer structure by type alias to generic write proxy structure.
778+ if should_derive_writer {
740779 let proxy = if width == 1 {
741780 let wproxy = Ident :: new (
742781 match mwv {
@@ -754,7 +793,7 @@ pub fn fields(
754793 } ,
755794 span,
756795 ) ;
757- quote ! { crate :: #wproxy<' a, #rty, #name_constant_case_spec, #name_constant_case_aw , O > }
796+ quote ! { crate :: #wproxy<' a, #rty, #name_constant_case_spec, #value_write_ty , O > }
758797 } else {
759798 let wproxy = Ident :: new (
760799 if unsafety {
@@ -765,13 +804,15 @@ pub fn fields(
765804 span,
766805 ) ;
767806 let width = & util:: unsuffixed ( width as _ ) ;
768- quote ! { crate :: #wproxy<' a, #rty, #name_constant_case_spec, #fty, #name_constant_case_aw , #width, O > }
807+ quote ! { crate :: #wproxy<' a, #rty, #name_constant_case_spec, #fty, #value_write_ty , #width, O > }
769808 } ;
770809 mod_items. extend ( quote ! {
771- #[ doc = #writerdoc ]
810+ #[ doc = #field_writer_brief ]
772811 pub type #writer_ty<' a, const O : u8 > = #proxy;
773812 } ) ;
774813 }
814+
815+ // generate proxy items from collected information
775816 if !proxy_items. is_empty ( ) {
776817 mod_items. extend ( quote ! {
777818 impl <' a, const O : u8 > #writer_ty<' a, O > {
@@ -1121,7 +1162,7 @@ fn lookup_filter<'a>(
11211162) -> Option < ( & ' a EnumeratedValues , Option < Base < ' a > > ) > {
11221163 for ( evs, base) in evs. iter ( ) {
11231164 if evs. usage == Some ( usage) {
1124- return Some ( ( * evs, base. clone ( ) ) ) ;
1165+ return Some ( ( * evs, * base) ) ;
11251166 }
11261167 }
11271168
0 commit comments