@@ -23,6 +23,7 @@ struct C {
2323 needs_string : bool ,
2424 world : String ,
2525 sizes : SizeAlign ,
26+ renamed_interfaces : HashMap < WorldKey , String > ,
2627
2728 world_id : Option < WorldId > ,
2829 dtor_funcs : HashMap < TypeId , String > ,
@@ -43,15 +44,34 @@ pub struct Opts {
4344 /// Skip emitting component allocation helper functions
4445 #[ cfg_attr( feature = "clap" , arg( long) ) ]
4546 pub no_helpers : bool ,
47+
4648 /// Set component string encoding
4749 #[ cfg_attr( feature = "clap" , arg( long, default_value_t = StringEncoding :: default ( ) ) ) ]
4850 pub string_encoding : StringEncoding ,
49- // Skip optional null pointer and boolean result argument signature flattening
51+
52+ /// Skip optional null pointer and boolean result argument signature
53+ /// flattening
5054 #[ cfg_attr( feature = "clap" , arg( long, default_value_t = false ) ) ]
5155 pub no_sig_flattening : bool ,
52- // Skip generating C object file
56+
57+ /// Skip generating an object file which contains type information for the
58+ /// world that is being generated.
5359 #[ cfg_attr( feature = "clap" , arg( long, default_value_t = false ) ) ]
5460 pub no_object_file : bool ,
61+
62+ /// Rename the interface `K` to `V` in the generated source code.
63+ #[ cfg_attr( feature = "clap" , arg( long, name = "K=V" , value_parser = parse_rename) ) ]
64+ pub rename : Vec < ( String , String ) > ,
65+ }
66+
67+ #[ cfg( feature = "clap" ) ]
68+ fn parse_rename ( name : & str ) -> Result < ( String , String ) > {
69+ let mut parts = name. splitn ( 2 , '=' ) ;
70+ let to_rename = parts. next ( ) . unwrap ( ) ;
71+ match parts. next ( ) {
72+ Some ( part) => Ok ( ( to_rename. to_string ( ) , part. to_string ( ) ) ) ,
73+ None => anyhow:: bail!( "`--rename` option must have an `=` in it (e.g. `--rename a=b`)" ) ,
74+ }
5575}
5676
5777impl Opts {
@@ -90,6 +110,24 @@ impl WorldGenerator for C {
90110 self . world = name. to_string ( ) ;
91111 self . sizes . fill ( resolve) ;
92112 self . world_id = Some ( world) ;
113+
114+ let mut interfaces = HashMap :: new ( ) ;
115+ let world = & resolve. worlds [ world] ;
116+ for ( key, _item) in world. imports . iter ( ) . chain ( world. exports . iter ( ) ) {
117+ let name = resolve. name_world_key ( key) ;
118+ interfaces. insert ( name, key. clone ( ) ) ;
119+ }
120+
121+ for ( from, to) in self . opts . rename . iter ( ) {
122+ match interfaces. get ( from) {
123+ Some ( key) => {
124+ self . renamed_interfaces . insert ( key. clone ( ) , to. clone ( ) ) ;
125+ }
126+ None => {
127+ eprintln ! ( "warning: rename of `{from}` did not match any interfaces" ) ;
128+ }
129+ }
130+ }
93131 }
94132
95133 fn import_interface (
@@ -602,13 +640,14 @@ pub fn owner_namespace<'a>(
602640 world : String ,
603641 resolve : & Resolve ,
604642 id : TypeId ,
643+ renamed_interfaces : & HashMap < WorldKey , String > ,
605644) -> String {
606645 let ty = & resolve. types [ id] ;
607646 match ( ty. owner , interface) {
608647 // If this type is owned by an interface, then we must be generating
609648 // bindings for that interface to proceed.
610649 ( TypeOwner :: Interface ( a) , Some ( ( b, key) ) ) if a == b => {
611- interface_identifier ( key, resolve, !in_import)
650+ interface_identifier ( key, resolve, !in_import, renamed_interfaces )
612651 }
613652 ( TypeOwner :: Interface ( _) , None ) => unreachable ! ( ) ,
614653 ( TypeOwner :: Interface ( _) , Some ( _) ) => unreachable ! ( ) ,
@@ -620,12 +659,28 @@ pub fn owner_namespace<'a>(
620659
621660 // If this type has no owner then it's an anonymous type. Here it's
622661 // assigned to whatever we happen to be generating bindings for.
623- ( TypeOwner :: None , Some ( ( _, key) ) ) => interface_identifier ( key, resolve, !in_import) ,
662+ ( TypeOwner :: None , Some ( ( _, key) ) ) => {
663+ interface_identifier ( key, resolve, !in_import, renamed_interfaces)
664+ }
624665 ( TypeOwner :: None , None ) => world. to_snake_case ( ) ,
625666 }
626667}
627668
628- pub fn interface_identifier ( interface_id : & WorldKey , resolve : & Resolve , in_export : bool ) -> String {
669+ fn interface_identifier (
670+ interface_id : & WorldKey ,
671+ resolve : & Resolve ,
672+ in_export : bool ,
673+ renamed_interfaces : & HashMap < WorldKey , String > ,
674+ ) -> String {
675+ if let Some ( rename) = renamed_interfaces. get ( interface_id) {
676+ let mut ns = String :: new ( ) ;
677+ if in_export && matches ! ( interface_id, WorldKey :: Interface ( _) ) {
678+ ns. push_str ( "exports_" ) ;
679+ }
680+ ns. push_str ( rename) ;
681+ return ns;
682+ }
683+
629684 match interface_id {
630685 WorldKey :: Name ( name) => name. to_snake_case ( ) ,
631686 WorldKey :: Interface ( id) => {
@@ -660,10 +715,16 @@ pub fn c_func_name(
660715 world : & str ,
661716 interface_id : Option < & WorldKey > ,
662717 func : & Function ,
718+ renamed_interfaces : & HashMap < WorldKey , String > ,
663719) -> String {
664720 let mut name = String :: new ( ) ;
665721 match interface_id {
666- Some ( id) => name. push_str ( & interface_identifier ( id, resolve, !in_import) ) ,
722+ Some ( id) => name. push_str ( & interface_identifier (
723+ id,
724+ resolve,
725+ !in_import,
726+ renamed_interfaces,
727+ ) ) ,
667728 None => name. push_str ( & world. to_snake_case ( ) ) ,
668729 }
669730 name. push_str ( "_" ) ;
@@ -1348,6 +1409,7 @@ impl InterfaceGenerator<'_> {
13481409 & self . gen . world ,
13491410 interface_id,
13501411 func,
1412+ & self . gen . renamed_interfaces ,
13511413 )
13521414 }
13531415
@@ -1682,6 +1744,7 @@ impl InterfaceGenerator<'_> {
16821744 self . gen . world . clone ( ) ,
16831745 self . resolve ,
16841746 id,
1747+ & self . gen . renamed_interfaces ,
16851748 )
16861749 }
16871750
0 commit comments