1use proc_macro2::{Span, TokenStream};
2use syn::{spanned::Spanned, Attribute, MetaList};
3
4use crate::{AttributeIdent, AttrsValue, ParseMeta};
5
6pub trait FromAttr: Sized {
12 type Parser: ParseMeta + Default;
14
15 fn from_parser(parser: Self::Parser, spans: &[Span]) -> syn::Result<Self>;
17
18 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 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 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 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}