#![deny(missing_docs)]
mod util;
mod wit_export;
mod wit_import;
mod wit_interface;
mod wit_load;
mod wit_store;
mod wit_type;
use proc_macro::TokenStream;
use proc_macro2::Span;
use proc_macro_error::{abort, proc_macro_error};
use quote::{quote, ToTokens};
#[cfg(with_wit_export)]
use syn::ItemImpl;
use syn::{parse_macro_input, Data, DeriveInput, Ident, ItemTrait};
use self::util::{apply_specialization_attribute, AttributeParameters, Specializations};
#[proc_macro_error]
#[proc_macro_derive(WitType, attributes(witty, witty_specialize_with))]
pub fn derive_wit_type(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
let specializations = apply_specialization_attribute(&mut input);
let wit_name = wit_type::discover_wit_name(&input.attrs, &input.ident);
let body = match &input.data {
Data::Struct(struct_item) => wit_type::derive_for_struct(wit_name, &struct_item.fields),
Data::Enum(enum_item) => {
wit_type::derive_for_enum(&input.ident, wit_name, enum_item.variants.iter())
}
Data::Union(_union_item) => {
abort!(input.ident, "Can't derive `WitType` for `union`s")
}
};
derive_trait(
input,
specializations,
body,
Ident::new("WitType", Span::call_site()),
)
}
#[proc_macro_error]
#[proc_macro_derive(WitLoad, attributes(witty, witty_specialize_with))]
pub fn derive_wit_load(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
let specializations = apply_specialization_attribute(&mut input);
let body = match &input.data {
Data::Struct(struct_item) => wit_load::derive_for_struct(&struct_item.fields),
Data::Enum(enum_item) => wit_load::derive_for_enum(&input.ident, enum_item.variants.iter()),
Data::Union(_union_item) => {
abort!(input.ident, "Can't derive `WitLoad` for `union`s")
}
};
derive_trait(
input,
specializations,
body,
Ident::new("WitLoad", Span::call_site()),
)
}
#[proc_macro_error]
#[proc_macro_derive(WitStore, attributes(witty, witty_specialize_with))]
pub fn derive_wit_store(input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
let specializations = apply_specialization_attribute(&mut input);
let body = match &input.data {
Data::Struct(struct_item) => wit_store::derive_for_struct(&struct_item.fields),
Data::Enum(enum_item) => {
wit_store::derive_for_enum(&input.ident, enum_item.variants.iter())
}
Data::Union(_union_item) => {
abort!(input.ident, "Can't derive `WitStore` for `union`s")
}
};
derive_trait(
input,
specializations,
body,
Ident::new("WitStore", Span::call_site()),
)
}
fn derive_trait(
input: DeriveInput,
specializations: Specializations,
body: impl ToTokens,
trait_name: Ident,
) -> TokenStream {
let (generic_parameters, type_generics, where_clause) =
specializations.split_generics_from(&input.generics);
let type_name = &input.ident;
quote! {
impl #generic_parameters #trait_name for #type_name #type_generics #where_clause {
#body
}
}
.into()
}
#[proc_macro_error]
#[proc_macro_attribute]
pub fn wit_import(attribute: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemTrait);
let parameters = AttributeParameters::new(attribute);
wit_import::generate(input, parameters).into()
}
#[cfg(with_wit_export)]
#[proc_macro_error]
#[proc_macro_attribute]
pub fn wit_export(attribute: TokenStream, input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as ItemImpl);
let parameters = AttributeParameters::new(attribute);
wit_export::generate(&input, parameters).into()
}