apigate-macros 0.2.5

Procedural macros for apigate — #[service], #[hook], #[map], and route attributes
Documentation
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{Error, Ident, LitStr, Result, Token};

use crate::parse::{parse_assigned, set_once};

pub(crate) struct ServiceArgs {
    pub name: Option<LitStr>,
    pub prefix: Option<LitStr>,
    pub policy: Option<LitStr>,
}

enum ServiceArg {
    Name(LitStr),
    Prefix(LitStr),
    Policy(LitStr),
}

impl Parse for ServiceArg {
    fn parse(input: ParseStream) -> Result<Self> {
        let key: Ident = input.parse()?;
        let value: LitStr = parse_assigned(input)?;

        match key.to_string().as_str() {
            "name" => Ok(Self::Name(value)),
            "prefix" => Ok(Self::Prefix(value)),
            "policy" => Ok(Self::Policy(value)),
            _ => Err(Error::new(key.span(), format!("unknown argument `{key}`"))),
        }
    }
}

impl Parse for ServiceArgs {
    fn parse(input: ParseStream) -> Result<Self> {
        let args = input.call(Punctuated::<ServiceArg, Token![,]>::parse_terminated)?;

        let mut name = None;
        let mut prefix = None;
        let mut policy = None;

        for arg in args {
            match arg {
                ServiceArg::Name(v) => set_once(&mut name, v.clone(), v.span(), "name")?,
                ServiceArg::Prefix(v) => set_once(&mut prefix, v.clone(), v.span(), "prefix")?,
                ServiceArg::Policy(v) => set_once(&mut policy, v.clone(), v.span(), "policy")?,
            }
        }

        Ok(Self {
            name,
            prefix,
            policy,
        })
    }
}