@ -25,6 +25,15 @@ mod source;
mod types ;
use source ::Source ;
struct InterfaceName {
/// True when this interface name has been remapped through the use of `with` in the `bindgen!`
/// macro invocation.
remapped : bool ,
/// The string name for this interface.
name : String ,
}
#[ derive(Default) ]
struct Wasmtime {
src : Source ,
@ -33,7 +42,7 @@ struct Wasmtime {
exports : Exports ,
types : Types ,
sizes : SizeAlign ,
interface_names : HashMap < InterfaceId , String > ,
interface_names : HashMap < InterfaceId , InterfaceName > ,
}
enum Import {
@ -66,6 +75,13 @@ pub struct Opts {
/// WIT type if necessary, for example if it's used as both an import and an
/// export.
pub duplicate_if_necessary : bool ,
/// Whether or not to generate code for only the interfaces of this wit file or not.
pub only_interfaces : bool ,
/// Remapping of interface names to rust module names.
/// TODO: is there a better type to use for the value of this map?
pub with : HashMap < String , String > ,
}
#[ derive(Debug, Clone) ]
@ -95,14 +111,37 @@ impl Opts {
}
impl Wasmtime {
fn name_interface ( & mut self , id : InterfaceId , name : String ) -> bool {
let entry = if let Some ( remapped_name ) = self . opts . with . get ( & name ) {
InterfaceName {
remapped : true ,
name : remapped_name . clone ( ) ,
}
} else {
InterfaceName {
remapped : false ,
name ,
}
} ;
let remapped = entry . remapped ;
self . interface_names . insert ( id , entry ) ;
remapped
}
fn generate ( & mut self , resolve : & Resolve , id : WorldId ) -> String {
self . types . analyze ( resolve , id ) ;
let world = & resolve . worlds [ id ] ;
for ( name , import ) in world . imports . iter ( ) {
self . import ( resolve , name , import ) ;
if ! self . opts . only_interfaces | | matches ! ( import , WorldItem ::Interface ( _ ) ) {
self . import ( resolve , name , import ) ;
}
}
for ( name , export ) in world . exports . iter ( ) {
self . export ( resolve , name , export ) ;
if ! self . opts . only_interfaces | | matches ! ( export , WorldItem ::Interface ( _ ) ) {
self . export ( resolve , name , export ) ;
}
}
self . finish ( resolve , id )
}
@ -119,7 +158,9 @@ impl Wasmtime {
Import ::Function { sig , add_to_linker }
}
WorldItem ::Interface ( id ) = > {
gen . gen . interface_names . insert ( * id , snake . clone ( ) ) ;
if gen . gen . name_interface ( * id , snake . clone ( ) ) {
return ;
}
gen . current_interface = Some ( * id ) ;
gen . types ( * id ) ;
gen . generate_trappable_error_types ( TypeOwner ::Interface ( * id ) ) ;
@ -166,7 +207,7 @@ impl Wasmtime {
}
WorldItem ::Type ( _ ) = > unreachable ! ( ) ,
WorldItem ::Interface ( id ) = > {
gen . gen . interface_names . insert ( * id , snake . clone ( ) ) ;
gen . gen . name_interface ( * id , snake . clone ( ) ) ;
gen . current_interface = Some ( * id ) ;
gen . types ( * id ) ;
gen . generate_trappable_error_types ( TypeOwner ::Interface ( * id ) ) ;
@ -246,7 +287,7 @@ impl Wasmtime {
assert ! ( prev . is_none ( ) ) ;
}
fn finish ( & mut self , resolve : & Resolve , world : WorldId ) -> String {
fn build_struct ( & mut self , resolve : & Resolve , world : WorldId ) {
let camel = to_rust_upper_camel_case ( & resolve . worlds [ world ] . name ) ;
uwriteln ! ( self . src , "pub struct {camel} {{" ) ;
for ( name , ( ty , _ ) ) in self . exports . fields . iter ( ) {
@ -327,6 +368,12 @@ impl Wasmtime {
uwriteln ! ( self . src , "}}" ) ; // close `impl {camel}`
uwriteln ! ( self . src , "}};" ) ; // close `const _: () = ...
}
fn finish ( & mut self , resolve : & Resolve , world : WorldId ) -> String {
if ! self . opts . only_interfaces {
self . build_struct ( resolve , world )
}
let mut src = mem ::take ( & mut self . src ) ;
if self . opts . rustfmt {
@ -1398,8 +1445,8 @@ impl<'a> RustGenerator<'a> for InterfaceGenerator<'a> {
match self . current_interface {
Some ( id ) if id = = interface = > None ,
_ = > {
let name = & self . gen . interface_names [ & interface ] ;
Some ( if self . current_interface . is_some ( ) {
let InterfaceName { remapped , name } = & self . gen . interface_names [ & interface ] ;
Some ( if self . current_interface . is_some ( ) & & ! remapped {
format ! ( "super::{name}" )
} else {
name . clone ( )