utoipa_gen/
security_requirement.rs1use 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 SecurityRequirementsAttrItem {
16 pub name: Option<String>,
17 pub scopes: Option<Vec<String>>,
18}
19
20#[derive(Default)]
21#[cfg_attr(feature = "debug", derive(Debug))]
22pub struct SecurityRequirementsAttr(Punctuated<SecurityRequirementsAttrItem, Comma>);
23
24impl Parse for SecurityRequirementsAttr {
25 fn parse(input: ParseStream) -> syn::Result<Self> {
26 Punctuated::<SecurityRequirementsAttrItem, Comma>::parse_terminated(input)
27 .map(|o| Self(o.into_iter().collect()))
28 }
29}
30
31impl Parse for SecurityRequirementsAttrItem {
32 fn parse(input: ParseStream) -> syn::Result<Self> {
33 let name = input.parse::<LitStr>()?.value();
34
35 input.parse::<Token![=]>()?;
36
37 let scopes_stream;
38 bracketed!(scopes_stream in input);
39
40 let scopes = Punctuated::<LitStr, Comma>::parse_terminated(&scopes_stream)?
41 .iter()
42 .map(LitStr::value)
43 .collect::<Vec<_>>();
44
45 Ok(Self {
46 name: Some(name),
47 scopes: Some(scopes),
48 })
49 }
50}
51
52impl ToTokens for SecurityRequirementsAttr {
53 fn to_tokens(&self, tokens: &mut TokenStream) {
54 tokens.extend(quote! {
55 utoipa::openapi::security::SecurityRequirement::default()
56 });
57
58 for requirement in &self.0 {
59 if let (Some(name), Some(scopes)) = (&requirement.name, &requirement.scopes) {
60 let scopes = scopes.iter().collect::<Array<&String>>();
61 let scopes_len = scopes.len();
62
63 tokens.extend(quote! {
64 .add::<&str, [&str; #scopes_len], &str>(#name, #scopes)
65 });
66 }
67 }
68 }
69}