Files
wasmtime/crates/wiggle/generate/src/module_trait.rs

81 lines
2.7 KiB
Rust

use proc_macro2::TokenStream;
use quote::quote;
use crate::error_transform::ErrorTransform;
use crate::lifetimes::{anon_lifetime, LifetimeExt};
use crate::names::Names;
use witx::Module;
pub fn passed_by_reference(ty: &witx::Type) -> bool {
let passed_by = match ty.passed_by() {
witx::TypePassedBy::Value { .. } => false,
witx::TypePassedBy::Pointer { .. } | witx::TypePassedBy::PointerLengthPair { .. } => true,
};
match ty {
witx::Type::Builtin(b) => match &*b {
witx::BuiltinType::String => true,
_ => passed_by,
},
witx::Type::Pointer(_) | witx::Type::ConstPointer(_) | witx::Type::Array(_) => true,
_ => passed_by,
}
}
pub fn define_module_trait(names: &Names, m: &Module, errxform: &ErrorTransform) -> TokenStream {
let traitname = names.trait_name(&m.name);
let traitmethods = m.funcs().map(|f| {
// Check if we're returning an entity anotated with a lifetime,
// in which case, we'll need to annotate the function itself, and
// hence will need an explicit lifetime (rather than anonymous)
let (lifetime, is_anonymous) = if f
.params
.iter()
.chain(&f.results)
.any(|ret| ret.tref.needs_lifetime())
{
(quote!('a), false)
} else {
(anon_lifetime(), true)
};
let funcname = names.func(&f.name);
let args = f.params.iter().map(|arg| {
let arg_name = names.func_param(&arg.name);
let arg_typename = names.type_ref(&arg.tref, lifetime.clone());
let arg_type = if passed_by_reference(&*arg.tref.type_()) {
quote!(&#arg_typename)
} else {
quote!(#arg_typename)
};
quote!(#arg_name: #arg_type)
});
let rets = f
.results
.iter()
.skip(1)
.map(|ret| names.type_ref(&ret.tref, lifetime.clone()));
let err = f
.results
.get(0)
.map(|err_result| {
if let Some(custom_err) = errxform.for_abi_error(&err_result.tref) {
let tn = custom_err.typename();
quote!(super::#tn)
} else {
names.type_ref(&err_result.tref, lifetime.clone())
}
})
.unwrap_or(quote!(()));
if is_anonymous {
quote!(fn #funcname(&self, #(#args),*) -> Result<(#(#rets),*), #err>;)
} else {
quote!(fn #funcname<#lifetime>(&self, #(#args),*) -> Result<(#(#rets),*), #err>;)
}
});
quote! {
pub trait #traitname {
#(#traitmethods)*
}
}
}