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 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}