axum_macros/
attr_parsing.rs1use quote::ToTokens;
2use syn::{
3 parse::{Parse, ParseStream},
4 Token,
5};
6
7pub(crate) fn parse_parenthesized_attribute<K, T>(
8 input: ParseStream,
9 out: &mut Option<(K, T)>,
10) -> syn::Result<()>
11where
12 K: Parse + ToTokens,
13 T: Parse,
14{
15 let kw = input.parse()?;
16
17 let content;
18 syn::parenthesized!(content in input);
19 let inner = content.parse()?;
20
21 if out.is_some() {
22 let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
23 let msg = format!("`{kw_name}` specified more than once");
24 return Err(syn::Error::new_spanned(kw, msg));
25 }
26
27 *out = Some((kw, inner));
28
29 Ok(())
30}
31
32pub(crate) fn parse_assignment_attribute<K, T>(
33 input: ParseStream,
34 out: &mut Option<(K, T)>,
35) -> syn::Result<()>
36where
37 K: Parse + ToTokens,
38 T: Parse,
39{
40 let kw = input.parse()?;
41 input.parse::<Token![=]>()?;
42 let inner = input.parse()?;
43
44 if out.is_some() {
45 let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
46 let msg = format!("`{kw_name}` specified more than once");
47 return Err(syn::Error::new_spanned(kw, msg));
48 }
49
50 *out = Some((kw, inner));
51
52 Ok(())
53}
54
55pub(crate) trait Combine: Sized {
56 fn combine(self, other: Self) -> syn::Result<Self>;
57}
58
59pub(crate) fn parse_attrs<T>(ident: &str, attrs: &[syn::Attribute]) -> syn::Result<T>
60where
61 T: Combine + Default + Parse,
62{
63 attrs
64 .iter()
65 .filter(|attr| attr.meta.path().is_ident(ident))
66 .map(|attr| attr.parse_args::<T>())
67 .try_fold(T::default(), |out, next| out.combine(next?))
68}
69
70pub(crate) fn combine_attribute<K, T>(a: &mut Option<(K, T)>, b: Option<(K, T)>) -> syn::Result<()>
71where
72 K: ToTokens,
73{
74 if let Some((kw, inner)) = b {
75 if a.is_some() {
76 let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
77 let msg = format!("`{kw_name}` specified more than once");
78 return Err(syn::Error::new_spanned(kw, msg));
79 }
80 *a = Some((kw, inner));
81 }
82 Ok(())
83}
84
85pub(crate) fn combine_unary_attribute<K>(a: &mut Option<K>, b: Option<K>) -> syn::Result<()>
86where
87 K: ToTokens,
88{
89 if let Some(kw) = b {
90 if a.is_some() {
91 let kw_name = std::any::type_name::<K>().split("::").last().unwrap();
92 let msg = format!("`{kw_name}` specified more than once");
93 return Err(syn::Error::new_spanned(kw, msg));
94 }
95 *a = Some(kw);
96 }
97 Ok(())
98}
99
100pub(crate) fn second<T, K>(tuple: (T, K)) -> K {
101 tuple.1
102}