power_reqwest_lib/
parse.rs

1use syn::{
2    parse::{Parse, ParseBuffer, ParseStream},
3    spanned::Spanned,
4    token::Brace,
5    Ident, LitBool, LitFloat, LitInt, LitStr, Token,
6};
7use syn_prelude::{
8    ParseAsIdent, ParseAsLitStr, ToErr, ToSynError, TryParseAsIdent, TryParseOneOfIdents,
9    TryParseTokens,
10};
11
12use crate::{
13    model::{
14        Api, ArrayValue, Client, DataField, DataType, ObjectFieldType, ObjectFieldValue,
15        ObjectType, ObjectValue, Signing, Value,
16    },
17    ApiHeader, ApiRequest, Auth, Common,
18};
19
20trait TryParseComma {
21    fn try_parse_comma(&self) -> syn::Result<()>;
22}
23
24impl Parse for Client {
25    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
26        let whole_span = input.span();
27        let mut client_name = None;
28        let mut config = None;
29        let mut signing = None;
30        let mut auth = None;
31        let mut common = None;
32        let mut api_list = vec![];
33        while !input.is_empty() {
34            if input.try_parse_comma().is_some() || input.try_parse_semi().is_some() {
35                continue;
36            }
37
38            let decl: ClientDecl = input.parse()?;
39            match decl {
40                ClientDecl::Name(_token, name) => {
41                    if client_name.is_some() {
42                        name.to_syn_error("duplicate client name defined previously")
43                            .to_err()?;
44                    }
45                    client_name = Some(name);
46                }
47                ClientDecl::Config(decl, brace) => {
48                    if config.is_some() {
49                        brace
50                            .span
51                            .close()
52                            .to_syn_error("duplicate client config defined previously")
53                            .to_err()?;
54                    }
55                    config = Some(decl);
56                }
57                ClientDecl::Signature(decl) => {
58                    if signing.is_some() {
59                        decl.span
60                            .to_syn_error("duplicate signature/signing config defined previously")
61                            .to_err()?;
62                    }
63                    signing = Some(decl);
64                }
65                ClientDecl::Auth(decl) => {
66                    if auth.is_some() {
67                        decl.span
68                            .to_syn_error("duplicate authorization config defined previously")
69                            .to_err()?;
70                    }
71                    auth = Some(decl);
72                }
73                ClientDecl::Api(decl) => {
74                    api_list.push(decl);
75                }
76                ClientDecl::Common(decl) => {
77                    if common.is_some() {
78                        decl.span
79                            .to_syn_error("duplicate common config defined previously")
80                            .to_err()?;
81                    }
82                    common = Some(decl);
83                }
84            }
85        }
86        Ok(Self {
87            name: client_name.ok_or(whole_span.to_syn_error("missing client name!"))?,
88            config,
89            common,
90            auth,
91            signing,
92            apis: api_list,
93        })
94    }
95}
96
97enum ClientDecl {
98    Name(Ident, Ident),
99    Config(Vec<DataField>, Brace),
100    Signature(Signing),
101    Auth(Auth),
102    Api(Api),
103    Common(Common),
104}
105
106impl Parse for ClientDecl {
107    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
108        if let Some(api) = Api::try_parse(input)? {
109            Ok(Self::Api(api))
110        } else if let Some(ident) = input.try_parse_as_ident("name", true) {
111            input.parse::<Token![:]>()?;
112            Ok(Self::Name(ident, input.parse()?))
113        } else if let Some(_ident) = input.try_parse_as_ident("config", false) {
114            input.try_parse_colon();
115            let (items, brace) = parse_config_fields(input)?;
116            Ok(Self::Config(items, brace))
117        } else if let Some(signing) = Signing::try_parse(input)? {
118            Ok(Self::Signature(signing))
119        } else if let Some(auth) = Auth::try_parse(input)? {
120            Ok(Self::Auth(auth))
121        } else if let Some(common) = Common::try_parse(input)? {
122            Ok(Self::Common(common))
123        } else {
124            input.span().to_syn_error("unexpect config field").to_err()
125        }
126    }
127}
128
129impl Common {
130    fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
131        if let Some(_common) = input.try_parse_as_ident("common", false) {
132            input.try_parse_colon();
133            let inner: ParseBuffer;
134            let brace = syn::braced!(inner in input);
135            let mut unwrap_response = None;
136            while !inner.is_empty() {
137                if let Some(_) = inner.try_parse_comma() {
138                    continue;
139                }
140
141                if let Some(token) = inner.try_parse_as_ident("unwrap_response", false) {
142                    inner.parse::<Token![:]>()?;
143                    if unwrap_response.is_some() {
144                        token.span().to_syn_error("duplicate config").to_err()?;
145                    }
146                    unwrap_response = Some(inner.parse()?);
147                } else {
148                    inner
149                        .span()
150                        .to_syn_error("unexpect field for common config")
151                        .to_err()?;
152                }
153            }
154            let span = brace.span.close();
155
156            Ok(Some(Self {
157                span,
158                unwrap_response,
159            }))
160        } else {
161            Ok(None)
162        }
163    }
164}
165
166impl Signing {
167    fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
168        if let Some(_ident) = input.try_parse_one_of_idents(("signing", "signature")) {
169            input.parse::<Token![:]>()?;
170            let inner: ParseBuffer;
171            let brace = syn::braced!(inner in input);
172            let mut sign = Signing {
173                span: brace.span.close(),
174                sign_fn: Default::default(),
175            };
176            while !inner.is_empty() {
177                if let Some(_) = inner.try_parse_comma() {
178                    continue;
179                }
180
181                if let Some(_sign_token) = inner.try_parse_as_ident("sign", false) {
182                    if sign.sign_fn.is_some() {
183                        _sign_token
184                            .span()
185                            .to_syn_error("duplicate sign before")
186                            .to_err()?;
187                    }
188                    inner.parse::<Token![:]>()?;
189                    sign.sign_fn = Some(inner.parse()?);
190                } else {
191                    inner
192                        .span()
193                        .to_syn_error("unxpected signing field")
194                        .to_err()?;
195                }
196            }
197            //
198            Ok(Some(sign))
199        } else {
200            Ok(None)
201        }
202    }
203}
204
205impl Auth {
206    fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
207        if let Some(_ident) = input.try_parse_one_of_idents(("auth", "authorization")) {
208            input.parse::<Token![:]>()?;
209            let inner: ParseBuffer;
210            let brace = syn::braced!(inner in input);
211
212            let mut url = None;
213
214            while !inner.is_empty() {
215                if let Some(_) = inner.try_parse_comma() {
216                    continue;
217                }
218
219                if let Some(_url) = inner.try_parse_as_ident("url", false) {
220                    inner.parse::<Token![:]>()?;
221                    if url.is_some() {
222                        _url.to_syn_error("duplicated url config").to_err()?;
223                    }
224                    url = Some(inner.parse::<LitStr>()?);
225                } else {
226                    inner
227                        .span()
228                        .to_syn_error("unexpected authorization field")
229                        .to_err()?;
230                }
231            }
232
233            let span = brace.span.close();
234            Ok(Some(Self {
235                span,
236                url: url.ok_or(span.to_syn_error("missing authorization url"))?,
237            }))
238        } else {
239            Ok(None)
240        }
241    }
242}
243
244impl Api {
245    fn try_parse(input: ParseStream) -> syn::Result<Option<Self>> {
246        if let Some(method) = input.try_parse_one_of_idents(("get", "post", "put", "delete")) {
247            let parened: ParseBuffer;
248            syn::parenthesized!(parened in input);
249            let url: LitStr = parened.parse()?;
250            if !parened.is_empty() {
251                parened.span().to_syn_error("unexpected content").to_err()?;
252            }
253
254            let inner: ParseBuffer;
255            let brace = syn::braced!(inner in input);
256
257            let mut name = None;
258            let mut response = None;
259            let mut header = None;
260            let mut request_data = None;
261
262            while !inner.is_empty() {
263                if let Some(_) = inner.try_parse_comma() {
264                    continue;
265                }
266                if let Some(_name) = inner.try_parse_as_ident("name", false) {
267                    inner.parse::<Token![:]>()?;
268                    if name.is_some() {
269                        _name.to_syn_error("name has been configured").to_err()?;
270                    }
271                    name = Some(inner.parse_as_lit_str()?);
272                } else if let Some(_) = inner.try_parse_as_ident("request", false) {
273                    inner.try_parse_colon();
274                    let request: ParseBuffer;
275                    syn::braced!(request in inner);
276                    while !request.is_empty() {
277                        if let Some(_) = request.try_parse_comma() {
278                            continue;
279                        };
280                        if let Some(_config) = request.try_parse_as_ident("header", false) {
281                            request.try_parse_colon();
282                            if header.is_some() {
283                                _config
284                                    .span()
285                                    .to_syn_error("duplicate header config")
286                                    .to_err()?;
287                            }
288                            let header_buffer: ParseBuffer;
289                            syn::braced!(header_buffer in request);
290                            let mut list = vec![];
291                            while !header_buffer.is_empty() {
292                                if let Some(_) = header_buffer.try_parse_comma() {
293                                    continue;
294                                }
295                                list.push(header_buffer.parse()?);
296                            }
297                            header = Some(list);
298                        } else if let Some(_) = request.try_parse_as_ident("data", false) {
299                            request.try_parse_colon();
300                            let (items, brace) = parse_config_fields(&request)?;
301                            if request_data.is_some() {
302                                brace
303                                    .span
304                                    .close()
305                                    .to_syn_error("request data has been defined previously")
306                                    .to_err()?;
307                            }
308                            request_data = Some(items);
309                        } else {
310                            request
311                                .span()
312                                .to_syn_error("unexpect field for request config")
313                                .to_err()?;
314                        }
315                    }
316                } else if let Some(_response) = inner.try_parse_as_ident("response", false) {
317                    inner.try_parse_colon();
318                    if response.is_some() {
319                        _response.span().to_syn_error("duplicated field").to_err()?;
320                    }
321                    let (items, _) = parse_config_fields(&inner)?;
322                    response = Some(items);
323                } else {
324                    inner
325                        .span()
326                        .to_syn_error("unexpect contents for api config")
327                        .to_err()?;
328                }
329            }
330
331            Ok(Some(Self {
332                name: name.ok_or(brace.span.close().to_syn_error("missing api name"))?,
333                response: response.ok_or(
334                    brace
335                        .span
336                        .close()
337                        .to_syn_error("missing response type config"),
338                )?,
339                request: {
340                    if request_data.is_some() || header.is_some() {
341                        Some(ApiRequest {
342                            header: header,
343                            data: request_data,
344                        })
345                    } else {
346                        None
347                    }
348                },
349                method,
350                url,
351            }))
352        } else {
353            Ok(None)
354        }
355    }
356}
357
358fn parse_config_fields(input: ParseStream) -> syn::Result<(Vec<DataField>, Brace)> {
359    let inner: ParseBuffer;
360    let brace = syn::braced!(inner in input);
361    let mut items: Vec<DataField> = vec![];
362    while !inner.is_empty() {
363        if let Some(_) = inner.try_parse_comma() {
364            continue;
365        }
366        let item: DataField = inner.parse()?;
367        if !items.is_empty() {
368            if items.iter().find(|i| i.name.eq(&item.name)).is_some() {
369                item.name
370                    .span()
371                    .to_syn_error("same config key exists")
372                    .to_err()?;
373            }
374        }
375        items.push(item);
376    }
377    Ok((items, brace))
378}
379
380impl Parse for ApiHeader {
381    fn parse(input: ParseStream) -> syn::Result<Self> {
382        let name = input.parse_as_lit_str()?;
383        input.parse::<Token![=]>()?;
384        let value = input.parse()?;
385        Ok(Self { name, value })
386    }
387}
388
389impl Parse for DataField {
390    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
391        let name = input.parse_as_ident()?;
392        let optional = if let Some(tk) = input.try_parse_question() {
393            Some(tk.span())
394        } else {
395            None
396        };
397        input.parse::<Token![:]>()?;
398        let typ = input.parse()?;
399        let default_value = if let Some(_) = input.try_parse_eq() {
400            Some(input.parse()?)
401        } else {
402            None
403        };
404
405        Ok(Self {
406            name,
407            typ,
408            value: default_value,
409            optional,
410        })
411    }
412}
413
414impl Parse for DataType {
415    fn parse(input: ParseStream) -> syn::Result<Self> {
416        let mut typ = if input.peek(syn::token::Brace) {
417            Self::Object(input.parse()?)
418        } else {
419            let ty = input.parse_as_ident()?;
420            match ty.to_string().as_str() {
421                "string" | "String" => Self::String(ty.span()),
422                "bool" | "boolean" => Self::Bool(ty.span()),
423                "int" => Self::Int(ty.span()),
424                "uint" => Self::Uint(ty.span()),
425                "float" => Self::Float(ty.span()),
426                _ => ty.to_syn_error("illegal config value type").to_err()?,
427            }
428        };
429        if input.peek(syn::token::Bracket) {
430            let inner: ParseBuffer;
431            syn::bracketed!(inner in input);
432            if inner.is_empty() {
433                typ = Self::List(Box::new(typ));
434            } else {
435                inner
436                    .span()
437                    .to_syn_error("unexpect content for list type")
438                    .to_err()?;
439            }
440        }
441        Ok(typ)
442    }
443}
444
445impl Parse for ObjectType {
446    fn parse(input: ParseStream) -> syn::Result<Self> {
447        let inner: ParseBuffer;
448        syn::braced!(inner in input);
449        let mut fields: Vec<ObjectFieldType> = vec![];
450        while !inner.is_empty() {
451            if inner.peek(Token![,]) {
452                inner.parse::<Token![,]>()?;
453                continue;
454            }
455            let field: ObjectFieldType = inner.parse()?;
456            if !fields.is_empty() {
457                if fields.iter().find(|f| f.name.eq(&field.name)).is_some() {
458                    field.name.span().to_syn_error("duplicate key").to_err()?;
459                }
460            }
461            fields.push(field);
462        }
463        Ok(Self { fields })
464    }
465}
466
467impl Parse for ObjectFieldType {
468    fn parse(input: ParseStream) -> syn::Result<Self> {
469        let name = input.parse_as_ident()?;
470        input.parse::<Token![:]>()?;
471        let ty: DataType = input.parse()?;
472        let default_value = if input.peek(Token![=]) {
473            input.parse::<Token![=]>()?;
474            Some(input.parse::<Value>()?)
475        } else {
476            None
477        };
478        Ok(Self {
479            name,
480            value_type: ty,
481            value: default_value,
482        })
483    }
484}
485
486impl Parse for Value {
487    fn parse(input: ParseStream) -> syn::Result<Self> {
488        Ok(if let Some(_) = input.try_parse_dollar() {
489            Self::Var(input.parse()?)
490        } else if input.peek(LitStr) {
491            Self::String(input.parse()?)
492        } else if input.peek(LitInt) {
493            Self::Int(input.parse()?)
494        } else if input.peek(LitFloat) {
495            Self::Float(input.parse()?)
496        } else if input.peek(LitBool) {
497            Self::Bool(input.parse()?)
498        } else if input.peek(syn::token::Brace) {
499            Self::Object(input.parse()?)
500        } else if input.peek(syn::token::Bracket) {
501            Self::Array(input.parse()?)
502        } else {
503            input.span().to_syn_error("missing constant").to_err()?
504        })
505    }
506}
507
508impl Parse for ObjectValue {
509    fn parse(input: ParseStream) -> syn::Result<Self> {
510        let inner: ParseBuffer;
511        let brace = syn::braced!(inner in input);
512        let mut fields: Vec<ObjectFieldValue> = vec![];
513        while !inner.is_empty() {
514            if inner.peek(Token![,]) {
515                inner.parse::<Token![,]>()?;
516                continue;
517            }
518            let field: ObjectFieldValue = inner.parse()?;
519            if !fields.is_empty() {
520                if fields.iter().find(|f| f.name.eq(&field.name)).is_some() {
521                    field.name.span().to_syn_error("duplicated key").to_err()?;
522                }
523            }
524            fields.push(field);
525        }
526        Ok(Self {
527            fields,
528            span: brace.span.close(),
529        })
530    }
531}
532
533impl Parse for ArrayValue {
534    fn parse(input: ParseStream) -> syn::Result<Self> {
535        let inner: ParseBuffer;
536        let bracket = syn::bracketed!(inner in input);
537        let mut elements = vec![];
538        while !inner.is_empty() {
539            if inner.peek(Token![,]) {
540                inner.parse::<Token![,]>()?;
541                continue;
542            }
543            elements.push(inner.parse()?);
544        }
545        Ok(Self {
546            elements,
547            span: bracket.span.close(),
548        })
549    }
550}
551
552impl Parse for ObjectFieldValue {
553    fn parse(input: ParseStream) -> syn::Result<Self> {
554        let name = input.parse()?;
555        input.parse::<Token![:]>()?;
556        let value = input.parse()?;
557        Ok(Self { name, value })
558    }
559}