oxanus-macros 1.0.1

Macros for Oxanus.
Documentation
use proc_macro_error2::abort;
use proc_macro2::TokenStream;
use quote::quote;
use syn::{Data, DeriveInput, Fields, PathArguments, Type};

pub fn expand_derive_registry(input: DeriveInput) -> TokenStream {
    if !cfg!(feature = "registry") {
        return quote!();
    }

    let inner_type = match &input.data {
        Data::Struct(data) => match &data.fields {
            Fields::Unnamed(fields) if fields.unnamed.len() == 1 => &fields.unnamed[0].ty,
            _ => abort!(
                input.ident,
                "Expected a tuple struct with exactly one field",
            ),
        },
        _ => abort!(input.ident, "Expected a struct",),
    };

    let type_path = match inner_type {
        Type::Path(path) => path,
        _ => abort!(input.ident, "Expected a struct with inner type",),
    };

    let generics = match type_path.path.segments.last() {
        Some(segment) => match &segment.arguments {
            PathArguments::AngleBracketed(args) => args,
            _ => abort!(
                inner_type,
                "Expected generic arguments <WorkerContext, WorkerError>",
            ),
        },
        _ => abort!(input.ident, "Expected a struct with inner type",),
    };

    let struct_ident = &input.ident;

    quote! {
        oxanus::create_component_registry!(#struct_ident);

        impl #struct_ident {
            pub fn build_config(storage: &oxanus::Storage) -> oxanus::Config::#generics {
                oxanus::ComponentRegistry::#generics::build_config(
                    &storage,
                    oxanus::iterate_components::<#struct_ident>().map(|x| &x.0),
                )
            }
        }
    }
}