1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
pub mod codegen;
pub mod parser;
pub mod common;
use codegen::action as action_codegen;
use codegen::collection as collection_codegen;
use codegen::error_code as error_code_codegen;
use deluxe::ExtractAttributes;
use deluxe::ParseMetaItem;
use parser::action as action_parser;
use parser::collection as collection_parser;
use parser::error_code as error_code_parser;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::ItemEnum;
use syn::Variant;
use syn::{
    parse::{Parse, ParseStream, Result as ParseResult},
    Ident, ItemFn, ItemMod, ItemStruct,
};

#[derive(Debug)]
pub struct CollectionMod {
    pub actions: Vec<Ident>,
    pub get_action_fns: Vec<ActionFn>,
    pub post_action_fns: Vec<ActionFn>,
    pub name: Ident,
    pub collection_mod: ItemMod,
}

impl Parse for CollectionMod {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let collection_mod = <ItemMod as Parse>::parse(input)?;
        collection_parser::parse(&collection_mod)
    }
}

impl From<&CollectionMod> for TokenStream {
    fn from(collection_mod: &CollectionMod) -> Self {
        collection_codegen::generate(collection_mod)
    }
}

impl ToTokens for CollectionMod {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend::<TokenStream>(self.into());
    }
}

#[derive(Debug)]
pub struct GetActionFn {
    pub raw_method: ItemFn,
    pub name: Ident,
    pub action: Ident,
}

#[derive(Debug)]
pub struct ActionFn {
    pub raw_method: ItemFn,
    pub name: Ident,
    pub action: Ident,
}

#[derive(Debug)]
pub struct ActionStruct {
    pub name: Ident,
    pub raw_struct: ItemStruct,
    pub attributes: Option<ActionAttributesStruct>,
    pub query_attrs: Option<Vec<(Ident, Ident)>>,
    pub params_attrs: Option<Vec<(Ident, Ident)>>,
}

impl Parse for ActionStruct {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let action_struct = <ItemStruct as Parse>::parse(input)?;
        action_parser::parse(&action_struct)
    }
}

impl From<&ActionStruct> for TokenStream {
    fn from(action_struct: &ActionStruct) -> Self {
        action_codegen::generate(action_struct)
    }
}

impl ToTokens for ActionStruct {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend::<TokenStream>(self.into());
    }
}

#[derive(Debug, ExtractAttributes)]
#[deluxe(attributes(action))]
pub struct ActionAttributesStruct {
    pub icon: String,
    pub title: String,
    pub description: String,
    pub label: String,
    #[deluxe(append, rename = link, default = Vec::new())]
    pub links: Vec<ActionLinkStruct>,
}

#[derive(Debug, ParseMetaItem)]
pub struct ActionLinkStruct {
    label: String,
    href: String,
    #[deluxe(append, rename = parameter, default = Vec::new())]
    parameters: Vec<ActionLinkParameterStruct>,
}

#[derive(Debug, ParseMetaItem)]
pub struct ActionLinkParameterStruct {
    label: String,
    name: String,
    #[deluxe(default = false)]
    required: bool,
}

#[derive(Debug)]
pub struct ErrorEnum {
    pub name: Ident,
    pub raw_enum: ItemEnum,
    pub error_variants: Vec<ErrorVariant>,
}

impl Parse for ErrorEnum {
    fn parse(input: ParseStream) -> ParseResult<Self> {
        let error_enum = <ItemEnum as Parse>::parse(input)?;
        error_code_parser::parse(&error_enum)
    }
}

impl From<&ErrorEnum> for TokenStream {
    fn from(error_enum: &ErrorEnum) -> Self {
        error_code_codegen::generate(error_enum)
    }
}

impl ToTokens for ErrorEnum {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.extend::<TokenStream>(self.into());
    }
}

#[derive(Debug, ExtractAttributes)]
#[deluxe(attributes(error))]
pub struct ErrorAttributesStruct {
    pub msg: String,
}

#[derive(Debug)]
pub struct ErrorVariant {
    pub name: Ident,
    pub raw_variant: Variant,
    pub msg: String,
}