wiggle_generate/
lib.rs

1mod codegen_settings;
2pub mod config;
3mod funcs;
4mod lifetimes;
5mod module_trait;
6pub mod names;
7mod types;
8pub mod wasmtime;
9
10use heck::ToShoutySnakeCase;
11use lifetimes::anon_lifetime;
12use proc_macro2::{Literal, TokenStream};
13use quote::quote;
14
15pub use codegen_settings::{CodegenSettings, ErrorType, UserErrorType};
16pub use config::{Config, WasmtimeConfig};
17pub use funcs::define_func;
18pub use module_trait::define_module_trait;
19pub use types::define_datatype;
20
21pub fn generate(doc: &witx::Document, settings: &CodegenSettings) -> TokenStream {
22    let types = doc
23        .typenames()
24        .map(|t| define_datatype(&t, settings.errors.for_name(&t)));
25
26    let constants = doc.constants().map(|c| {
27        let name = quote::format_ident!(
28            "{}_{}",
29            c.ty.as_str().to_shouty_snake_case(),
30            c.name.as_str().to_shouty_snake_case()
31        );
32        let ty = names::type_(&c.ty);
33        let value = Literal::u64_unsuffixed(c.value);
34        quote! {
35            pub const #name: #ty = #value;
36        }
37    });
38
39    let user_error_methods = settings.errors.iter().filter_map(|errtype| match errtype {
40        ErrorType::User(errtype) => {
41            let abi_typename = names::type_ref(&errtype.abi_type(), anon_lifetime());
42            let user_typename = errtype.typename();
43            let methodname = names::user_error_conversion_method(&errtype);
44            Some(quote! {
45                fn #methodname(&mut self, e: super::#user_typename)
46                    -> wiggle::anyhow::Result<#abi_typename>;
47            })
48        }
49        ErrorType::Generated(_) => None,
50    });
51    let user_error_conversion = quote! {
52        pub trait UserErrorConversion {
53            #(#user_error_methods)*
54        }
55    };
56    let modules = doc.modules().map(|module| {
57        let modname = names::module(&module.name);
58        let fs = module.funcs().map(|f| define_func(&module, &f, &settings));
59        let modtrait = define_module_trait(&module, &settings);
60        let wasmtime = if settings.wasmtime {
61            crate::wasmtime::link_module(&module, None, &settings)
62        } else {
63            quote! {}
64        };
65        quote!(
66            pub mod #modname {
67                use super::types::*;
68                pub use super::types::UserErrorConversion;
69                #(#fs)*
70
71                #modtrait
72
73                #wasmtime
74            }
75        )
76    });
77
78    quote!(
79        pub mod types {
80            use std::convert::TryFrom;
81
82            #(#types)*
83            #(#constants)*
84            #user_error_conversion
85        }
86        #(#modules)*
87    )
88}
89
90pub fn generate_metadata(doc: &witx::Document) -> TokenStream {
91    let doc_text = &format!("{doc}");
92    quote! {
93        pub mod metadata {
94            pub const DOC_TEXT: &str = #doc_text;
95            pub fn document() -> wiggle::witx::Document {
96                wiggle::witx::parse(DOC_TEXT).unwrap()
97            }
98        }
99    }
100}