1 mod codegen_settings;
2 pub mod config;
3 mod funcs;
4 mod lifetimes;
5 mod module_trait;
6 pub mod names;
7 mod types;
8 pub mod wasmtime;
9 
10 use heck::ToShoutySnakeCase;
11 use lifetimes::anon_lifetime;
12 use proc_macro2::{Literal, TokenStream};
13 use quote::quote;
14 
15 pub use codegen_settings::{CodegenSettings, ErrorType, UserErrorType};
16 pub use config::{Config, WasmtimeConfig};
17 pub use funcs::define_func;
18 pub use module_trait::define_module_trait;
19 pub use types::define_datatype;
20 
generate(doc: &witx::Document, settings: &CodegenSettings) -> TokenStream21 pub 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::error::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 
generate_metadata(doc: &witx::Document) -> TokenStream90 pub 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 }
101