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
157
158
159
160
161
162
163
164
165
166
167
168
169
extern crate proc_macro;

mod define_service;
mod define_type;
mod define_ui_page;

use proc_macro::TokenStream;

/// Helps to define new [UiPage](ui_page::UiPage)
///
/// ```
/// define_ui_page!(
///    name: PAGE_INDEX,
///    parameter: String,
///    path: "/",
/// );
/// ```
#[proc_macro]
pub fn define_ui_page(input: TokenStream) -> TokenStream {
	return define_ui_page::define_ui_page(input);
}

/// Helps to define new [Service](service::Service)
///
/// The macros generates new module where all Service-related data will be placed.
///
/// There will be:
/// * In -- type alias for Service's input type
/// * Out -- type alias for Service's output type
/// (or type itself if `outputs` used instead of `output_type`)
/// * Struct -- the structure for which [Service] trait will be implemented
/// * INSTANCE -- const instance of the Struct
/// * REF -- 'static ref for Struct (pointing to the INSTANCE)
///
/// # Parameters
/// ## `doc` (optional)
/// String literal which will be used as a documentation for a new module.
/// The explanation of the service functionality may be placed here.
///
/// ## `name` (required)
/// Identifier (name) for new module.
///
/// ## `input` (required)
/// Service's input type.
///
/// Right now for King::Get services you have to use structure or enum (not String or i32
/// or etc.)
///
/// ## `output_type` (one of `output_type` or `outputs` required)
/// Service's output type. The type has to implement [AsResponse]
/// and has to have
/// `pub fn from_response(response: uni_components::::Response) -> Result<Self,
/// uni_components::Response>` function.
///
/// The best way to implement the type is to use [define_type!] macro.
///
/// Otherwise you can use `outputs` parameter and skip `output_type`.
///
/// ## `outputs` (one of `output_type` or `outputs` required)
/// There you can specify variants how you do for [define_type!]'s `variants` parameter.
///
/// You can not have both `outputs` and `output_type` together.
///
/// ## `path` (required)
/// The path where the service will be available at website.
///
/// ## `kind` (required)
/// Select a kind of your servce. It should be one of [Kind]s.
///
/// # Example
/// ```
/// define_service!(
///    doc: "
///    Authentication service.
///
///    It receives user credentials (as a part of authorization request) and
///    then provides token as a response.
///    ",
///    name: AUTH_ACTION,
///    kind: uni_components::Kind::Post,
///    input: common::Auth,
///    outputs: [
///        AuthorizedToken {
///            code: 200,
///            body: String,
///            doc: "You are authorized to use the service. Token provided"
///        },
///        NonAuthorized {
///            code: 401,
///            doc: "Non authorized. Probably credentials are incorrect",
///        },
///    ],
///    path: "/api/login/",
/// );
/// ```
#[proc_macro]
pub fn define_service(input: TokenStream) -> TokenStream {
	return define_service::define_service(input);
}

/// Helps to define type for service output
///
/// Two parameters have to be specified: `name` and `variants` (`doc` is optional).
///
/// # `doc` (optional)
/// Provide string literal there. It'll be used as doc for the new type.
///
/// # `name` (required)
/// It'll become the name of a new type so any identifier will works.
/// Generic types may be specified as
///
/// ```
/// //...
///      name: TypeName<T,K> where T: Send, K: Sync {},
/// //...
/// ```
/// Please take a look at `{}` at the end of the line.
/// The minimal bound should be
/// `T: 'static + Send + Sync + serde::Serialize + serde::de::DeserializeOwned`.
///
/// # `variants` (required)
/// It looks like array where each element are one possible vairant of service answer:
/// ```
/// <VariantName> {
///     code: <code_value>,
///     body: <body_type>,
///     doc: <doc_content>,
/// }
/// ```
/// * <VariantName> will become identifier for the variant,
/// * <code_value> (required) should be u16 and recommended to be one of allowed
/// [HTTP codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
/// * `body` (optional) parameter is optional and <body_type> have to be the type of data
///   represented by the variant
/// * `doc` (optional) parameter is optional and <doc_content> have to be string literal,
///   that literal will be added as documentation to the variant
///
/// # Example
/// ```
/// define_type!{
///     doc: "
///     The type repsersents an answer for the question.
///
///     Server may have the answer or may have not.
///     ",
///     name: QuestionAnswer,
///     variants:[
///         Ok{
///             code: 200,
///             body: String,
///             doc: "Answer found:",
///         },
///         NumberNotFound{
///             code: 404,
///             doc: "Answer not found",
///         },
///     ]
/// }
/// ```
#[proc_macro]
pub fn define_type(input: TokenStream) -> TokenStream {
	return define_type::define_type(input);
}

fn the_crate_name() -> proc_macro2::TokenStream {
	quote::quote! {
		uni_components
	}
}