restify_macros/
lib.rs

1mod attr_parsing;
2mod config;
3mod controller;
4mod injectable;
5mod module;
6mod route;
7
8use proc_macro::TokenStream;
9use syn::{parse_macro_input, DeriveInput, Type};
10
11#[proc_macro_attribute]
12pub fn controller(args: TokenStream, input: TokenStream) -> TokenStream {
13  controller::expand(input.into(), args.into())
14    .unwrap_or_else(|e| e)
15    .into()
16}
17
18#[proc_macro_derive(Injectable, attributes(injectable))]
19pub fn injectable(item: TokenStream) -> TokenStream {
20  let item = parse_macro_input!(item as syn::Item);
21
22  injectable::expand(item)
23    .unwrap_or_else(|e| e.into_compile_error().into())
24    .into()
25}
26
27#[proc_macro_derive(Module, attributes(module))]
28pub fn module(item: TokenStream) -> TokenStream {
29  let item = parse_macro_input!(item as DeriveInput);
30
31  module::expand(item)
32    .unwrap_or_else(|e| e.into_compile_error().into())
33    .into()
34}
35
36fn infer_state_types<'a, I>(types: I) -> impl Iterator<Item = Type> + 'a
37where
38  I: Iterator<Item = &'a Type> + 'a,
39{
40  types
41    .filter_map(|ty| {
42      if let Type::Path(path) = ty {
43        Some(&path.path)
44      } else {
45        None
46      }
47    })
48    .filter_map(|path| {
49      if let Some(last_segment) = path.segments.last() {
50        if last_segment.ident != "State" {
51          return None;
52        }
53
54        match &last_segment.arguments {
55          syn::PathArguments::AngleBracketed(args) if args.args.len() == 1 => {
56            Some(args.args.first().unwrap())
57          }
58          _ => None,
59        }
60      } else {
61        None
62      }
63    })
64    .filter_map(|generic_arg| {
65      if let syn::GenericArgument::Type(ty) = generic_arg {
66        Some(ty)
67      } else {
68        None
69      }
70    })
71    .cloned()
72}