linera_witty_macros/
lib.rs1#![deny(missing_docs)]
9
10mod util;
11mod wit_export;
12mod wit_import;
13mod wit_interface;
14mod wit_load;
15mod wit_store;
16mod wit_type;
17
18use proc_macro::TokenStream;
19use proc_macro2::Span;
20use proc_macro_error::{abort, proc_macro_error};
21use quote::{quote, ToTokens};
22#[cfg(with_wit_export)]
23use syn::ItemImpl;
24use syn::{parse_macro_input, Data, DeriveInput, Ident, ItemTrait};
25
26use self::util::{apply_specialization_attribute, AttributeParameters, Specializations};
27
28#[proc_macro_error]
32#[proc_macro_derive(WitType, attributes(witty, witty_specialize_with))]
33pub fn derive_wit_type(input: TokenStream) -> TokenStream {
34 let mut input = parse_macro_input!(input as DeriveInput);
35
36 let specializations = apply_specialization_attribute(&mut input);
37 let wit_name = wit_type::discover_wit_name(&input.attrs, &input.ident);
38
39 let body = match &input.data {
40 Data::Struct(struct_item) => wit_type::derive_for_struct(wit_name, &struct_item.fields),
41 Data::Enum(enum_item) => {
42 wit_type::derive_for_enum(&input.ident, wit_name, enum_item.variants.iter())
43 }
44 Data::Union(_union_item) => {
45 abort!(input.ident, "Can't derive `WitType` for `union`s")
46 }
47 };
48
49 derive_trait(
50 input,
51 specializations,
52 body,
53 Ident::new("WitType", Span::call_site()),
54 )
55}
56
57#[proc_macro_error]
61#[proc_macro_derive(WitLoad, attributes(witty, witty_specialize_with))]
62pub fn derive_wit_load(input: TokenStream) -> TokenStream {
63 let mut input = parse_macro_input!(input as DeriveInput);
64
65 let specializations = apply_specialization_attribute(&mut input);
66
67 let body = match &input.data {
68 Data::Struct(struct_item) => wit_load::derive_for_struct(&struct_item.fields),
69 Data::Enum(enum_item) => wit_load::derive_for_enum(&input.ident, enum_item.variants.iter()),
70 Data::Union(_union_item) => {
71 abort!(input.ident, "Can't derive `WitLoad` for `union`s")
72 }
73 };
74
75 derive_trait(
76 input,
77 specializations,
78 body,
79 Ident::new("WitLoad", Span::call_site()),
80 )
81}
82
83#[proc_macro_error]
87#[proc_macro_derive(WitStore, attributes(witty, witty_specialize_with))]
88pub fn derive_wit_store(input: TokenStream) -> TokenStream {
89 let mut input = parse_macro_input!(input as DeriveInput);
90
91 let specializations = apply_specialization_attribute(&mut input);
92
93 let body = match &input.data {
94 Data::Struct(struct_item) => wit_store::derive_for_struct(&struct_item.fields),
95 Data::Enum(enum_item) => {
96 wit_store::derive_for_enum(&input.ident, enum_item.variants.iter())
97 }
98 Data::Union(_union_item) => {
99 abort!(input.ident, "Can't derive `WitStore` for `union`s")
100 }
101 };
102
103 derive_trait(
104 input,
105 specializations,
106 body,
107 Ident::new("WitStore", Span::call_site()),
108 )
109}
110
111fn derive_trait(
115 input: DeriveInput,
116 specializations: Specializations,
117 body: impl ToTokens,
118 trait_name: Ident,
119) -> TokenStream {
120 let (generic_parameters, type_generics, where_clause) =
121 specializations.split_generics_from(&input.generics);
122 let type_name = &input.ident;
123
124 quote! {
125 impl #generic_parameters #trait_name for #type_name #type_generics #where_clause {
126 #body
127 }
128 }
129 .into()
130}
131
132#[proc_macro_error]
137#[proc_macro_attribute]
138pub fn wit_import(attribute: TokenStream, input: TokenStream) -> TokenStream {
139 let input = parse_macro_input!(input as ItemTrait);
140 let parameters = AttributeParameters::new(attribute);
141
142 wit_import::generate(input, parameters).into()
143}
144
145#[cfg(with_wit_export)]
151#[proc_macro_error]
152#[proc_macro_attribute]
153pub fn wit_export(attribute: TokenStream, input: TokenStream) -> TokenStream {
154 let input = parse_macro_input!(input as ItemImpl);
155 let parameters = AttributeParameters::new(attribute);
156
157 wit_export::generate(&input, parameters).into()
158}