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 aliase for Service's input type /// * Out -- type aliase for Service's output type /// (or type itself if `outpus` 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 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.) /// /// ## `outputs_type` (one of `outputs_type` or `outputs` required) /// Service's output type. The type have to implement [AsResponse] /// and have 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 `outputs_type`. /// /// ## `outputs` (one of `outputs_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 `outputs_type` together. /// /// ## `path` (required) /// The path where the service will be available at website. /// /// ## `kind` (required) /// Select 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 } }