from_attr/
from_attr.rs

1use proc_macro2::{Span, TokenStream};
2use syn::{spanned::Spanned, Attribute, MetaList};
3
4use crate::{AttributeIdent, AttrsValue, ParseMeta};
5
6/// Used for conversion from [`Attribute`]s, [`MetaList`], [`TokenStream`] to values.
7///
8/// Instead of converting directly from [`Attribute`]s, [`MetaList`], [`TokenStream`] to values,
9/// we need to use the helper type that implements [`ParseMeta`] and [`Default`] to convert to this type first,
10/// and then convert to the value we really need.
11pub trait FromAttr: Sized {
12    /// The helper type that implements [`ParseMeta`] and [`Default`].
13    type Parser: ParseMeta + Default;
14
15    /// Convert from [`Parser`](type@crate::FromAttr::Parser) to values.
16    fn from_parser(parser: Self::Parser, spans: &[Span]) -> syn::Result<Self>;
17
18    /// Convert from [`MetaList`] to values.
19    fn from_meta_list(list: &MetaList) -> syn::Result<Option<Self>>
20    where
21        Self: AttributeIdent,
22    {
23        if <Self as AttributeIdent>::is_ident(&list.path) {
24            let mut parser_default = Self::Parser::default();
25            let spans = vec![list.span()];
26            parser_default.parse_meta_list(list)?;
27            Ok(Some(Self::from_parser(parser_default, &spans)?))
28        } else {
29            Ok(None)
30        }
31    }
32
33    /// Convert from [`Attribute`]s to values.
34    ///
35    /// *Does not* remove [`Attribute`]s and is generally used to parse attributes of derive macros.
36    fn from_attributes(
37        attrs: &[Attribute],
38    ) -> Result<Option<AttrsValue<&Attribute, Self>>, AttrsValue<&Attribute, syn::Error>>
39    where
40        Self: AttributeIdent,
41    {
42        if attrs.is_empty() {
43            return Ok(None);
44        }
45
46        let mut matched_attr_spans = Vec::new();
47        let mut matched_attrs = Vec::new();
48        let mut parser_default = Self::Parser::default();
49        let mut errors = Vec::new();
50
51        attrs
52            .iter()
53            .filter(|attr| <Self as AttributeIdent>::is_ident(attr.path()))
54            .for_each(|attr| {
55                matched_attr_spans.push(attr.span());
56                matched_attrs.push(attr);
57
58                if let Err(err) = parser_default.parse_attr(attr) {
59                    errors.push(err);
60                };
61            });
62
63        if matched_attrs.is_empty() {
64            return Ok(None);
65        }
66
67        if let Some(e) = errors.into_iter().reduce(|mut a, b| {
68            a.combine(b);
69            a
70        }) {
71            return Err(AttrsValue {
72                attrs: matched_attrs,
73                value: e,
74            });
75        }
76
77        match Self::from_parser(parser_default, &matched_attr_spans) {
78            Ok(o) => Ok(Some(AttrsValue {
79                attrs: matched_attrs,
80                value: o,
81            })),
82            Err(err) => Err(AttrsValue {
83                attrs: matched_attrs,
84                value: err,
85            }),
86        }
87    }
88
89    /// Convert from [`Attribute`]s to values.
90    ///
91    /// *Does* remove [`Attribute`]s and is generally used to parse attributes of attribute macros.
92    fn remove_attributes(
93        attrs: &mut Vec<Attribute>,
94    ) -> Result<Option<AttrsValue<Attribute, Self>>, AttrsValue<Attribute, syn::Error>>
95    where
96        Self: AttributeIdent,
97    {
98        if attrs.is_empty() {
99            return Ok(None);
100        }
101
102        let mut matched_attr_spans = Vec::new();
103        let mut matched_attrs = Vec::new();
104        let mut parser_default = Self::Parser::default();
105        let mut errors = Vec::new();
106
107        let mut i = 0;
108
109        while i < attrs.len() {
110            if !<Self as AttributeIdent>::is_ident(attrs[i].path()) {
111                i += 1;
112            } else {
113                let attr = attrs.remove(i);
114
115                if let Err(err) = parser_default.parse_attr(&attr) {
116                    errors.push(err);
117                };
118
119                matched_attr_spans.push(attr.span());
120                matched_attrs.push(attr);
121            }
122        }
123
124        if matched_attrs.is_empty() {
125            return Ok(None);
126        }
127
128        if let Some(e) = errors.into_iter().reduce(|mut a, b| {
129            a.combine(b);
130            a
131        }) {
132            return Err(AttrsValue {
133                attrs: matched_attrs,
134                value: e,
135            });
136        }
137
138        match Self::from_parser(parser_default, &matched_attr_spans) {
139            Ok(o) => Ok(Some(AttrsValue {
140                attrs: matched_attrs,
141                value: o,
142            })),
143            Err(err) => Err(AttrsValue {
144                attrs: matched_attrs,
145                value: err,
146            }),
147        }
148    }
149
150    /// Convert from [`TokenStream`] to values.
151    ///
152    /// Generally used for parsing [`TokenStream`] for attribute macros.
153    fn from_tokens(tokens: TokenStream) -> syn::Result<Self> {
154        let mut parser_default = Self::Parser::default();
155        let spans = vec![tokens.span()];
156        parser_default.parse_tokens(tokens)?;
157        Self::from_parser(parser_default, &spans)
158    }
159}