axum_macros/
attr_parsing.rs

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