@@ -296,7 +296,7 @@ pub fn fields(
296296 ( ( self . bits >> OFFSET ) & MASK as #rty) #cast
297297 } ;
298298
299- if let Some ( ( evs, base) ) = util :: lookup (
299+ if let Some ( ( evs, base) ) = lookup (
300300 f. evs ,
301301 fields,
302302 parent,
@@ -584,7 +584,7 @@ pub fn fields(
584584 let mask = & f. mask ;
585585 let width = f. width ;
586586
587- if let Some ( ( evs, base) ) = util :: lookup (
587+ if let Some ( ( evs, base) ) = lookup (
588588 & f. evs ,
589589 fields,
590590 parent,
@@ -803,3 +803,213 @@ pub fn fields(
803803
804804 Ok ( ( ) )
805805}
806+
807+ #[ derive( Clone , Debug ) ]
808+ pub struct Base < ' a > {
809+ pub peripheral : Option < & ' a str > ,
810+ pub register : Option < & ' a str > ,
811+ pub field : & ' a str ,
812+ }
813+
814+ fn lookup < ' a > (
815+ evs : & ' a [ EnumeratedValues ] ,
816+ fields : & ' a [ Field ] ,
817+ register : & ' a Register ,
818+ all_registers : & ' a [ Register ] ,
819+ peripheral : & ' a Peripheral ,
820+ all_peripherals : & ' a [ Peripheral ] ,
821+ usage : Usage ,
822+ ) -> Result < Option < ( & ' a EnumeratedValues , Option < Base < ' a > > ) > > {
823+ let evs = evs. iter ( )
824+ . map ( |evs| if let Some ( ref base) = evs. derived_from {
825+ let mut parts = base. split ( '.' ) ;
826+
827+ match ( parts. next ( ) , parts. next ( ) , parts. next ( ) , parts. next ( ) ) {
828+ ( Some ( base_peripheral) , Some ( base_register) , Some ( base_field) , Some ( base_evs) ) => {
829+ lookup_in_peripherals (
830+ base_peripheral,
831+ base_register,
832+ base_field,
833+ base_evs,
834+ all_peripherals,
835+ )
836+ }
837+ ( Some ( base_register) , Some ( base_field) , Some ( base_evs) , None ) => {
838+ lookup_in_peripheral (
839+ None ,
840+ base_register,
841+ base_field,
842+ base_evs,
843+ all_registers,
844+ peripheral,
845+ )
846+ }
847+ ( Some ( base_field) , Some ( base_evs) , None , None ) => {
848+ lookup_in_fields ( base_evs, base_field, fields, register)
849+ }
850+ ( Some ( base_evs) , None , None , None ) => lookup_in_register ( base_evs, register) ,
851+ _ => unreachable ! ( ) ,
852+ }
853+ } else {
854+ Ok ( ( evs, None ) )
855+ } )
856+ . collect :: < Result < Vec < _ > > > ( ) ?;
857+
858+ for & ( ref evs, ref base) in evs. iter ( ) {
859+ if evs. usage == Some ( usage) {
860+ return Ok ( Some ( ( * evs, base. clone ( ) ) ) ) ;
861+ }
862+ }
863+
864+ Ok ( evs. first ( ) . cloned ( ) )
865+ }
866+
867+ fn lookup_in_fields < ' f > (
868+ base_evs : & str ,
869+ base_field : & str ,
870+ fields : & ' f [ Field ] ,
871+ register : & Register ,
872+ ) -> Result < ( & ' f EnumeratedValues , Option < Base < ' f > > ) > {
873+ if let Some ( base_field) = fields. iter ( ) . find ( |f| f. name == base_field) {
874+ return lookup_in_field ( base_evs, None , None , base_field) ;
875+ } else {
876+ Err ( format ! (
877+ "Field {} not found in register {}" ,
878+ base_field,
879+ register. name
880+ ) ) ?
881+ }
882+ }
883+
884+ fn lookup_in_peripheral < ' p > (
885+ base_peripheral : Option < & ' p str > ,
886+ base_register : & ' p str ,
887+ base_field : & str ,
888+ base_evs : & str ,
889+ all_registers : & ' p [ Register ] ,
890+ peripheral : & ' p Peripheral ,
891+ ) -> Result < ( & ' p EnumeratedValues , Option < Base < ' p > > ) > {
892+ if let Some ( register) = all_registers. iter ( ) . find ( |r| r. name == base_register) {
893+ if let Some ( field) = register
894+ . fields
895+ . as_ref ( )
896+ . map ( |fs| & * * fs)
897+ . unwrap_or ( & [ ] )
898+ . iter ( )
899+ . find ( |f| f. name == base_field)
900+ {
901+ lookup_in_field ( base_evs, Some ( base_register) , base_peripheral, field)
902+ } else {
903+ Err ( format ! (
904+ "No field {} in register {}" ,
905+ base_field,
906+ register. name
907+ ) ) ?
908+ }
909+ } else {
910+ Err ( format ! (
911+ "No register {} in peripheral {}" ,
912+ base_register,
913+ peripheral. name
914+ ) ) ?
915+ }
916+ }
917+
918+ fn lookup_in_field < ' f > (
919+ base_evs : & str ,
920+ base_register : Option < & ' f str > ,
921+ base_peripheral : Option < & ' f str > ,
922+ field : & ' f Field ,
923+ ) -> Result < ( & ' f EnumeratedValues , Option < Base < ' f > > ) > {
924+ for evs in & field. enumerated_values {
925+ if evs. name . as_ref ( ) . map ( |s| & * * s) == Some ( base_evs) {
926+ return Ok (
927+ (
928+ evs,
929+ Some ( Base {
930+ field : & field. name ,
931+ register : base_register,
932+ peripheral : base_peripheral,
933+ } ) ,
934+ ) ,
935+ ) ;
936+ }
937+ }
938+
939+ Err ( format ! (
940+ "No EnumeratedValues {} in field {}" ,
941+ base_evs,
942+ field. name
943+ ) ) ?
944+ }
945+
946+ fn lookup_in_register < ' r > (
947+ base_evs : & str ,
948+ register : & ' r Register ,
949+ ) -> Result < ( & ' r EnumeratedValues , Option < Base < ' r > > ) > {
950+ let mut matches = vec ! [ ] ;
951+
952+ for f in register. fields . as_ref ( ) . map ( |v| & * * v) . unwrap_or ( & [ ] ) {
953+ if let Some ( evs) = f. enumerated_values
954+ . iter ( )
955+ . find ( |evs| evs. name . as_ref ( ) . map ( |s| & * * s) == Some ( base_evs) )
956+ {
957+ matches. push ( ( evs, & f. name ) )
958+ }
959+ }
960+
961+ match matches. first ( ) {
962+ None => Err ( format ! (
963+ "EnumeratedValues {} not found in register {}" ,
964+ base_evs,
965+ register. name
966+ ) ) ?,
967+ Some ( & ( evs, field) ) => if matches. len ( ) == 1 {
968+ return Ok ( (
969+ evs,
970+ Some ( Base {
971+ field : field,
972+ register : None ,
973+ peripheral : None ,
974+ } ) ,
975+ ) ) ;
976+ } else {
977+ let fields = matches
978+ . iter ( )
979+ . map ( |& ( ref f, _) | & f. name )
980+ . collect :: < Vec < _ > > ( ) ;
981+ Err ( format ! (
982+ "Fields {:?} have an \
983+ enumeratedValues named {}",
984+ fields,
985+ base_evs
986+ ) ) ?
987+ } ,
988+ }
989+ }
990+
991+ fn lookup_in_peripherals < ' p > (
992+ base_peripheral : & ' p str ,
993+ base_register : & ' p str ,
994+ base_field : & str ,
995+ base_evs : & str ,
996+ all_peripherals : & ' p [ Peripheral ] ,
997+ ) -> Result < ( & ' p EnumeratedValues , Option < Base < ' p > > ) > {
998+ if let Some ( peripheral) = all_peripherals. iter ( ) . find ( |p| p. name == base_peripheral) {
999+ let all_registers = peripheral
1000+ . registers
1001+ . as_ref ( )
1002+ . map ( |x| x. as_ref ( ) )
1003+ . unwrap_or ( & [ ] [ ..] ) ;
1004+ lookup_in_peripheral (
1005+ Some ( base_peripheral) ,
1006+ base_register,
1007+ base_field,
1008+ base_evs,
1009+ all_registers,
1010+ peripheral,
1011+ )
1012+ } else {
1013+ Err ( format ! ( "No peripheral {}" , base_peripheral) ) ?
1014+ }
1015+ }
0 commit comments