sword-macros 0.3.0

Structured web framework built on top of tokio ecosystem, providing powerful features for building robust web applications.
Documentation
use crate::shared::StructFields;
use proc_macro::TokenStream;
use syn::parse::{ParseStream, Result as ParseResult};
use syn::{Ident, ItemStruct, Token, Type, parse::Parse};

pub enum InjectableKind {
    Provider,
    Component,
}

pub struct InjectableInput {
    pub struct_name: Ident,
    pub fields: Vec<(Ident, Type)>,
    pub derive_clone: bool,
    pub kind: InjectableKind,
}

struct InjectableArgs {
    kind: InjectableKind,
    derive_clone: bool,
}

impl Parse for InjectableArgs {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let mut kind = InjectableKind::Component;
        let mut derive_clone = true;

        if input.is_empty() {
            return Ok(Self { kind, derive_clone });
        }

        while !input.is_empty() {
            let arg: Ident = input.parse()?;

            match arg.to_string().as_str() {
                "provider" => kind = InjectableKind::Provider,
                "component" => kind = InjectableKind::Component,
                "no_derive_clone" => derive_clone = false,
                _ => {
                    return Err(syn::Error::new_spanned(
                        arg,
                        "Unknown attribute. Use 'provider', 'component', or 'no_derive_clone'",
                    ));
                }
            }

            if !input.is_empty() {
                input.parse::<Token![,]>()?;
            }
        }

        Ok(Self { kind, derive_clone })
    }
}

pub fn parse_injectable_input(
    attr: TokenStream,
    item: TokenStream,
) -> Result<InjectableInput, syn::Error> {
    let input = syn::parse::<ItemStruct>(item)?;
    let args = syn::parse::<InjectableArgs>(attr)?;

    Ok(InjectableInput {
        struct_name: input.clone().ident,
        fields: StructFields::parse(&input)?,
        derive_clone: args.derive_clone,
        kind: args.kind,
    })
}