use proc_macro2::TokenStream;
use syn::{Attribute, ItemFn, LitStr};
pub fn parse_route_path(attr: TokenStream) -> Result<LitStr, TokenStream> {
let path: LitStr = syn::parse2(attr).map_err(|err| err.to_compile_error())?;
if path.value().is_empty() {
return Err(syn::Error::new(path.span(), "Route path must not be empty").to_compile_error());
}
if !path.value().starts_with('/') {
let suggested = format!("/{}", path.value());
return Err(syn::Error::new(
path.span(),
format!("Route path must start with '/'. Did you mean \"{suggested}\"?"),
)
.to_compile_error());
}
Ok(path)
}
pub fn parse_async_handler(item: TokenStream) -> Result<ItemFn, TokenStream> {
let input_fn: ItemFn = syn::parse2(item.clone()).map_err(|_| {
syn::Error::new_spanned(item, "route macros can only be applied to functions")
.to_compile_error()
})?;
if input_fn.sig.asyncness.is_none() {
return Err(syn::Error::new_spanned(
input_fn.sig.fn_token,
"Autumn route handlers must be async functions",
)
.to_compile_error());
}
Ok(input_fn)
}
pub fn extract_interceptors(attrs: &mut Vec<Attribute>) -> Vec<syn::Path> {
let mut interceptors = Vec::new();
attrs.retain(|attr| {
if attr.path().is_ident("intercept") {
if let Ok(path) = attr.parse_args::<syn::Path>() {
interceptors.push(path);
}
false } else {
true }
});
interceptors
}