chrome_native_macros/
lib.rs1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, DeriveInput};
4
5#[proc_macro_attribute]
6pub fn chrome_native_task(
7 _metadata: proc_macro::TokenStream,
8 input: proc_macro::TokenStream,
9) -> proc_macro::TokenStream {
10 let input: TokenStream = input.into();
11
12 let expanded = quote! {
13 #[derive(serde::Serialize, serde::Deserialize)]
14 #[serde(tag = "task", content = "message")]
15 #input
16 };
17
18 expanded.into()
19}
20
21#[proc_macro_attribute]
22pub fn chrome_native_data(
23 _metadata: proc_macro::TokenStream,
24 input: proc_macro::TokenStream,
25) -> proc_macro::TokenStream {
26 let input: TokenStream = input.into();
27
28 let expanded = quote! {
29 #[derive(serde::Serialize, serde::Deserialize)]
30 #input
31 };
32
33 expanded.into()
34}
35
36fn generator(ast: &DeriveInput) -> TokenStream {
37 let name = &ast.ident;
38
39 if let syn::Data::Struct(syn::DataStruct {
40 fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }),
41 ..
42 }) = ast.data
43 {
44 if ast.attrs.len() != 0 {
45 let default_gen: syn::LitBool = ast.attrs[0].parse_args().unwrap();
46 let generate = default_gen.value();
47 if generate {
48 let all_option = named.iter().all(|f| {
49 if let syn::Type::Path(ref p) = f.ty {
50 p.path.segments.len() == 1 && p.path.segments[0].ident == "Option"
51 } else {
52 false
53 }
54 });
55 if all_option {
56 let options_value = named.iter().map(|f| {
57 let name = &f.ident;
58 quote! {
59 #name: None
60 }
61 });
62 return quote! {
63 impl #name {
64 fn create_self() -> Self {
65 Self {
66 #(#options_value,)*
67 }
68 }
69 }
70 }
71 .into();
72 }
73 }
74 }
75 }
76 quote! {}.into()
77}
78
79#[proc_macro_derive(Plugin, attributes(default_gen))]
80pub fn plugin_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
81 let ast = parse_macro_input!(input as DeriveInput);
82 let name = &ast.ident;
83 let generated = &generator(&ast);
84
85 let expanded = quote! {
86 #generated
87
88 #[no_mangle]
89 pub extern fn get_plugin() -> *mut dyn chrome_native::Plugin {
90 Box::into_raw(Box::new(#name::create_self()))
91 }
92 };
93
94 expanded.into()
95}