1 use proc_macro2::TokenStream;
2 use quote::quote;
3
4 use crate::codegen_settings::{CodegenSettings, ErrorType};
5 use crate::names;
6 use witx::Module;
7
passed_by_reference(ty: &witx::Type) -> bool8 pub fn passed_by_reference(ty: &witx::Type) -> bool {
9 match ty {
10 witx::Type::Record(r) => r.bitflags_repr().is_none(),
11 witx::Type::Variant(v) => !v.is_enum(),
12 _ => false,
13 }
14 }
15
define_module_trait(m: &Module, settings: &CodegenSettings) -> TokenStream16 pub fn define_module_trait(m: &Module, settings: &CodegenSettings) -> TokenStream {
17 let traitname = names::trait_name(&m.name);
18 let traitmethods = m.funcs().map(|f| {
19 let funcname = names::func(&f.name);
20 let args = f.params.iter().map(|arg| {
21 let arg_name = names::func_param(&arg.name);
22 let arg_typename = names::type_ref(&arg.tref, quote!());
23 let arg_type = if passed_by_reference(&*arg.tref.type_()) {
24 quote!(&#arg_typename)
25 } else {
26 quote!(#arg_typename)
27 };
28 quote!(#arg_name: #arg_type)
29 });
30
31 let mut result = match f.results.len() {
32 0 if f.noreturn => quote!(wiggle::error::Error),
33 0 => quote!(()),
34 1 => {
35 let (ok, err) = match &**f.results[0].tref.type_() {
36 witx::Type::Variant(v) => match v.as_expected() {
37 Some(p) => p,
38 None => unimplemented!("anonymous variant ref {:?}", v),
39 },
40 _ => unimplemented!(),
41 };
42
43 let ok = match ok {
44 Some(ty) => names::type_ref(ty, quote!()),
45 None => quote!(()),
46 };
47 let err = match err {
48 Some(ty) => match settings.errors.for_abi_error(ty) {
49 Some(ErrorType::User(custom)) => {
50 let tn = custom.typename();
51 quote!(super::#tn)
52 }
53 Some(ErrorType::Generated(g)) => g.typename(),
54 None => names::type_ref(ty, quote!()),
55 },
56 None => quote!(()),
57 };
58 quote!(Result<#ok, #err>)
59 }
60 _ => unimplemented!(),
61 };
62
63 if !settings.get_async(&m, &f).is_sync() {
64 result = quote!(impl std::future::Future<Output = #result> + Send);
65 }
66
67 let self_ = if settings.mutable {
68 quote!(&mut self)
69 } else {
70 quote!(&self)
71 };
72 quote!(
73 fn #funcname(
74 #self_,
75 mem: &mut wiggle::GuestMemory<'_>,
76 #(#args),*
77 ) -> #result;
78 )
79 });
80
81 quote! {
82 pub trait #traitname {
83 #(#traitmethods)*
84
85 /// Indicates, if this implementation supports it, that the
86 /// specified amount of fuel should be the maximal spent for the
87 /// upcoming function call.
88 fn set_hostcall_fuel(&mut self, fuel: usize) {
89 let _ = fuel;
90 }
91 }
92 }
93 }
94