castle_macro 0.20.2

Castle Macro, macros to make your life easier
Documentation
use quote::quote_spanned;
use syn::{spanned::Spanned, Fields, ItemStruct};

use crate::{shared_functions::get_input_def_and_initalizations};

pub fn derive_input(item_struct: ItemStruct) -> proc_macro2::TokenStream {
    let name = &item_struct.ident;

    let fields = match &item_struct.fields {
        Fields::Named(fields) => fields,
        _ => panic!("Only structs with named fields are supported"),
    };

    let (
        input_definitions,
        initializations
    ) = get_input_def_and_initalizations(&fields.named);

    let field_conversions = fields.named
        .iter()
        .map(|field| {
            let name = field.ident.as_ref().unwrap();
            let ty = &field.ty;
            quote_spanned!(ty.span()=> #name: inputs.get(stringify!(#name)).unwrap().try_into()?)
        });



    quote_spanned! {item_struct.span() =>
        #item_struct

        impl ::core::convert::TryFrom<&::castle_api::types::Input> for #name {
            type Error = ::castle_api::types::CastleError;

            fn try_from(input: &::castle_api::types::Input) -> Result<Self, Self::Error> {
                let inputs = input.as_map().unwrap();
                Ok(#name {
                    #(
                        #field_conversions,
                    )*
                })
            }
        }

        impl ::castle_api::types::HasKind for #name {
            fn kind() -> ::castle_api::types::Kind {
                ::castle_api::types::Kind {
                    ident: stringify!(#name).into(),
                    generics: vec![]
                }
            }
        }

        impl ::castle_api::types::SchemaItem for #name {
            fn initialize_item(schema: &mut ::castle_api::types::SchemaDefinition) {
                if !schema.kind_is_registered(&stringify!(#name)) {
                    let input_def = ::castle_api::types::InputTypeDefinition {
                        ident: stringify!(#name).into(),
                        input_definitions: [
                            #(
                                #input_definitions,
                            )*
                        ].into(),
                        directives: vec![].into(),
                    };

                    schema.register_input_type(input_def);

                    #(
                        #initializations;
                    )*
                }
            }
        }
    }
    .into()
}