utoipa_gen/
security_requirement.rs

1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::{
4    bracketed,
5    parse::{Parse, ParseStream},
6    punctuated::Punctuated,
7    token::Comma,
8    LitStr, Token,
9};
10
11use crate::Array;
12
13#[derive(Default)]
14#[cfg_attr(feature = "debug", derive(Debug))]
15pub struct SecurityRequirementAttr {
16    name: Option<String>,
17    scopes: Option<Vec<String>>,
18}
19
20impl Parse for SecurityRequirementAttr {
21    fn parse(input: ParseStream) -> syn::Result<Self> {
22        if input.is_empty() {
23            return Ok(Self {
24                ..Default::default()
25            });
26        }
27        let name = input.parse::<LitStr>()?.value();
28        input.parse::<Token![=]>()?;
29
30        let scopes_stream;
31        bracketed!(scopes_stream in input);
32        let scopes = Punctuated::<LitStr, Comma>::parse_terminated(&scopes_stream)?
33            .iter()
34            .map(LitStr::value)
35            .collect::<Vec<_>>();
36
37        Ok(Self {
38            name: Some(name),
39            scopes: Some(scopes),
40        })
41    }
42}
43
44impl ToTokens for SecurityRequirementAttr {
45    fn to_tokens(&self, tokens: &mut TokenStream) {
46        if let (Some(name), Some(scopes)) = (&self.name, &self.scopes) {
47            let scopes_array = scopes.iter().collect::<Array<&String>>();
48            let scopes_len = scopes.len();
49
50            tokens.extend(quote! {
51                utoipa::openapi::security::SecurityRequirement::new::<&str, [&str; #scopes_len], &str>(#name, #scopes_array)
52            })
53        } else {
54            tokens.extend(quote! {
55                utoipa::openapi::security::SecurityRequirement::default()
56            })
57        }
58    }
59}