Function wiggle_generate::names::module
source · Examples found in repository?
src/wasmtime.rs (line 14)
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
pub fn link_module(
module: &witx::Module,
target_path: Option<&syn::Path>,
settings: &CodegenSettings,
) -> TokenStream {
let module_ident = names::module(&module.name);
let send_bound = if settings.async_.contains_async(module) {
quote! { + Send, T: Send }
} else {
quote! {}
};
let mut bodies = Vec::new();
let mut bounds = HashSet::new();
for f in module.funcs() {
let asyncness = settings.async_.get(module.name.as_str(), f.name.as_str());
bodies.push(generate_func(&module, &f, target_path, asyncness));
let bound = func_bounds(module, &f, settings);
for b in bound {
bounds.insert(b);
}
}
let ctx_bound = if let Some(target_path) = target_path {
let bounds = bounds
.into_iter()
.map(|b| quote!(#target_path::#module_ident::#b));
quote!( #(#bounds)+* #send_bound )
} else {
let bounds = bounds.into_iter();
quote!( #(#bounds)+* #send_bound )
};
let func_name = if target_path.is_none() {
format_ident!("add_to_linker")
} else {
format_ident!("add_{}_to_linker", module_ident)
};
quote! {
/// Adds all instance items to the specified `Linker`.
pub fn #func_name<T, U>(
linker: &mut wiggle::wasmtime_crate::Linker<T>,
get_cx: impl Fn(&mut T) -> &mut U + Send + Sync + Copy + 'static,
) -> wiggle::anyhow::Result<()>
where
U: #ctx_bound #send_bound
{
#(#bodies)*
Ok(())
}
}
}
fn generate_func(
module: &witx::Module,
func: &witx::InterfaceFunc,
target_path: Option<&syn::Path>,
asyncness: Asyncness,
) -> TokenStream {
let module_str = module.name.as_str();
let module_ident = names::module(&module.name);
let field_str = func.name.as_str();
let field_ident = names::func(&func.name);
let (params, results) = func.wasm_signature();
let arg_names = (0..params.len())
.map(|i| Ident::new(&format!("arg{}", i), Span::call_site()))
.collect::<Vec<_>>();
let arg_decls = params
.iter()
.enumerate()
.map(|(i, ty)| {
let name = &arg_names[i];
let wasm = names::wasm_type(*ty);
quote! { #name: #wasm }
})
.collect::<Vec<_>>();
let ret_ty = match results.len() {
0 => quote!(()),
1 => names::wasm_type(results[0]),
_ => unimplemented!(),
};
let await_ = if asyncness.is_sync() {
quote!()
} else {
quote!(.await)
};
let abi_func = if let Some(target_path) = target_path {
quote!( #target_path::#module_ident::#field_ident )
} else {
quote!( #field_ident )
};
let body = quote! {
let export = caller.get_export("memory");
let (mem, ctx) = match &export {
Some(wiggle::wasmtime_crate::Extern::Memory(m)) => {
let (mem, ctx) = m.data_and_store_mut(&mut caller);
let ctx = get_cx(ctx);
(wiggle::wasmtime::WasmtimeGuestMemory::new(mem), ctx)
}
Some(wiggle::wasmtime_crate::Extern::SharedMemory(m)) => {
let ctx = get_cx(caller.data_mut());
(wiggle::wasmtime::WasmtimeGuestMemory::shared(m.data()), ctx)
}
_ => wiggle::anyhow::bail!("missing required memory export"),
};
Ok(<#ret_ty>::from(#abi_func(ctx, &mem #(, #arg_names)*) #await_ ?))
};
match asyncness {
Asyncness::Async => {
let wrapper = format_ident!("func_wrap{}_async", params.len());
quote! {
linker.#wrapper(
#module_str,
#field_str,
move |mut caller: wiggle::wasmtime_crate::Caller<'_, T> #(, #arg_decls)*| {
Box::new(async move { #body })
},
)?;
}
}
Asyncness::Blocking => {
quote! {
linker.func_wrap(
#module_str,
#field_str,
move |mut caller: wiggle::wasmtime_crate::Caller<'_, T> #(, #arg_decls)*| -> wiggle::anyhow::Result<#ret_ty> {
let result = async { #body };
wiggle::run_in_dummy_executor(result)?
},
)?;
}
}
Asyncness::Sync => {
quote! {
linker.func_wrap(
#module_str,
#field_str,
move |mut caller: wiggle::wasmtime_crate::Caller<'_, T> #(, #arg_decls)*| -> wiggle::anyhow::Result<#ret_ty> {
#body
},
)?;
}
}
}
}
More examples
src/lib.rs (line 57)
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
pub fn generate(doc: &witx::Document, settings: &CodegenSettings) -> TokenStream {
let types = doc
.typenames()
.map(|t| define_datatype(&t, settings.errors.for_name(&t)));
let constants = doc.constants().map(|c| {
let name = quote::format_ident!(
"{}_{}",
c.ty.as_str().to_shouty_snake_case(),
c.name.as_str().to_shouty_snake_case()
);
let ty = names::type_(&c.ty);
let value = Literal::u64_unsuffixed(c.value);
quote! {
pub const #name: #ty = #value;
}
});
let user_error_methods = settings.errors.iter().filter_map(|errtype| match errtype {
ErrorType::User(errtype) => {
let abi_typename = names::type_ref(&errtype.abi_type(), anon_lifetime());
let user_typename = errtype.typename();
let methodname = names::user_error_conversion_method(&errtype);
Some(quote! {
fn #methodname(&mut self, e: super::#user_typename)
-> wiggle::anyhow::Result<#abi_typename>;
})
}
ErrorType::Generated(_) => None,
});
let user_error_conversion = quote! {
pub trait UserErrorConversion {
#(#user_error_methods)*
}
};
let modules = doc.modules().map(|module| {
let modname = names::module(&module.name);
let fs = module.funcs().map(|f| define_func(&module, &f, &settings));
let modtrait = define_module_trait(&module, &settings);
let wasmtime = if settings.wasmtime {
crate::wasmtime::link_module(&module, None, &settings)
} else {
quote! {}
};
quote!(
pub mod #modname {
use super::types::*;
pub use super::types::UserErrorConversion;
#(#fs)*
#modtrait
#wasmtime
}
)
});
quote!(
pub mod types {
use std::convert::TryFrom;
#(#types)*
#(#constants)*
#user_error_conversion
}
#(#modules)*
)
}