argos-macros 0.1.0

Argos's proc macros.
Documentation

use syn::parse::{Parse, ParseStream};
use syn::{ Ident, Token, token, LitStr, Error, LitInt};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct RouteAttribute {
    pub(crate) http_method: Ident,
    pub(crate) path: LitStr,
    pub(crate) formatter: LitStr,
}

impl Parse for RouteAttribute {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let methods = vec!["GET", "POST", "OPTIONS", "HEAD", "DELETE", "PUT", "TRACE", "CONNECT", "PATCH"];
        let http_method: Ident = input.parse()?;
        
        if methods.iter().find(|m| m.to_string() == http_method.to_string()).is_none() {
            return Err(Error::new(http_method.span(), "expected http method"));
        }
        let _comma = input.parse::<Token![,]>()?;
        let path_ident: Ident = input.parse()?;
        if path_ident != "path" || !input.peek(token::Eq) {
            return Err(Error::new(path_ident.span(), "expected path"));
        }
        let _eq = input.parse::<Token![=]>()?;
        let path = input.parse::<LitStr>()?;
        let _comma = input.parse::<Token![,]>()?;
        let formatter_ident: Ident = input.parse()?;
        if formatter_ident != "formatter" || !input.peek(token::Eq) {
            return Err(Error::new(formatter_ident.span(), "expected formatter"));
        }
        let _eq = input.parse::<Token![=]>()?;
        let formatter = input.parse::<LitStr>()?;
        let formatters = vec!["json", "text", "html"];
        if formatters.iter().find(|f| f.to_string() == formatter.value()).is_none() {
            return Err(Error::new(formatter.span(), "formatter only support json, text, html"));
        }
        Ok(RouteAttribute {
            http_method,
            path,
            formatter,
        })
    }
}

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct FilterAttribute {
    pub(crate) predicate_type: Ident,
    pub(crate) predicate_value: LitStr,
    pub(crate) order: LitInt,
}


impl Parse for FilterAttribute {
    fn parse(input: ParseStream) -> syn::Result<Self> {
        let predicate_ident: Ident = input.parse()?;
        if predicate_ident == "path_pattern" && input.peek(token::Eq) {
            let _eq = input.parse::<Token![=]>()?;
            let path_pattern: LitStr = input.parse()?;
            let _comma = input.parse::<Token![,]>()?;
            let order_ident: Ident = input.parse()?;
            if order_ident == "order" && input.peek(token::Eq) {
                let _eq = input.parse::<Token![=]>()?;
                let order = input.parse::<LitInt>()?;
                Ok(FilterAttribute {
                    predicate_type: predicate_ident,
                    predicate_value: path_pattern,
                    order,
                })
            } else {
                Err(Error::new(order_ident.span(), "expected order"))
            }
        } else {
            Err(Error::new(predicate_ident.span(), "expected path_pattern"))
        }
    }
}