use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, Error, Data};
use quote::quote;
mod handles_attr;
mod gen;
mod names;
use handles_attr::*;
use gen::*;
use names::*;
pub fn actor_impl(_args: TokenStream, input: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(input as DeriveInput);
let data = match input.data {
Data::Struct(ref mut data) => data,
_ => return Error::new(input.ident.span(), "vin only works on structs").into_compile_error().into(),
};
let name = &input.ident;
let generics = &input.generics;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let handles_attrs = input.attrs.iter()
.filter(|attr| check_if_attr_from_vin(&attr, "handles"))
.map(|attr| attr.parse_args::<HandlesAttr>())
.collect::<Result<Vec<_>, _>>();
let handles_attrs = match handles_attrs {
Ok(attrs) => attrs,
Err(err) => return err.to_compile_error().into(),
};
let other_attrs = input.attrs.iter()
.filter(|attr| !check_if_attr_from_vin(&attr, "handles"))
.collect::<Vec<_>>();
let vin_hidden_struct = form_vin_hidden_struct(name, &handles_attrs);
let vin_context_struct = form_vin_context_struct(name, &data.fields, &other_attrs, &generics);
let forwarder_traits = form_forwarder_impls(name, &handles_attrs, &impl_generics, &ty_generics, where_clause);
let actor_trait = form_actor_trait(name, &handles_attrs, &impl_generics, &ty_generics, where_clause);
let hidden_struct_name = form_hidden_struct_name(name);
let context_struct_name = form_context_struct_name(name);
input.attrs.clear();
let attrs = &input.attrs;
quote! {
#(#attrs)*
pub struct #name #generics {
vin_ctx: ::vin::tokio::sync::RwLock<#context_struct_name #ty_generics>,
vin_hidden: #hidden_struct_name,
}
#vin_context_struct
#vin_hidden_struct
#forwarder_traits
#actor_trait
}.into()
}