1 2 3 4 5 6 7 8 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
extern crate proc_macro; use proc_macro::TokenStream; use std::str::FromStr; use syn::export::ToTokens; use syn::{parse_macro_input, Fields, ItemStruct}; #[proc_macro_attribute] pub fn template(metadata: TokenStream, input: TokenStream) -> TokenStream { let template_exp = metadata.to_string(); let original_struct = input.to_string(); let input = parse_macro_input!(input as ItemStruct); let struct_name = input.ident.to_string(); let mut fields: Vec<(String, String)> = vec![]; if let Fields::Named(n) = input.fields { fields = n .named .iter() .map(|x| { ( x.ident.as_ref().unwrap().to_string(), x.ty.clone().into_token_stream().to_string(), ) }) .collect(); } let mut args: Vec<String> = vec![]; let mut extractor_exprs: Vec<String> = vec![]; let mut execute_exprs: Vec<String> = vec![]; let mut c = 0; for (field_name, field_type) in fields.iter() { if field_type == "String" { extractor_exprs.push( [ "const ", field_name, " = this.readUtf8FromMemory(a", &c.to_string(), ",a", &(c + 1).to_string(), ");", ] .join(""), ); execute_exprs.push( [ "let a", &c.to_string(), " = self.", field_name, ".as_ptr() as u32;\nlet a", &(c + 1).to_string(), " = self.", field_name, ".len() as u32;", ] .join(""), ); args.push(["a", &c.to_string()].join("")); c += 1; args.push(["a", &c.to_string()].join("")); c += 1; } else { panic!("unsupported type"); } } let args = args.join(","); let extractor_exprs = extractor_exprs.join("\n"); let execute_exprs = execute_exprs.join("\n"); TokenStream::from_str(&format!(r#" {} struct {}Builder {{ fn_builder: lit_html::js::JSFunction, }} impl Default for {}Builder {{ fn default() -> Self {{ let mut fn_text = &["function builder(","{}","){{\n","{}","const result = window.LitHtml.html`",{},"`;\nreturn this.storeObject(result);\n}}"].join(""); {}Builder {{ fn_builder: lit_html::js::register_function(&fn_text), }} }} }} impl lit_html::Template for {} {{ fn execute(&self) -> f64 {{ let builder = globals::get::<{}Builder>(); {} builder.fn_builder.invoke_{}({}) }} }} "#,original_struct,struct_name,struct_name,args,extractor_exprs,template_exp,struct_name,struct_name,struct_name,execute_exprs,c,args)).unwrap() }