utoipa_gen/component/schema/
features.rs1use syn::{
2 parse::{Parse, ParseBuffer, ParseStream},
3 Attribute,
4};
5
6use crate::{
7 component::features::{
8 attributes::{
9 AdditionalProperties, As, Bound, ContentEncoding, ContentMediaType, Deprecated,
10 Description, Discriminator, Example, Examples, Format, Ignore, Inline, NoRecursion,
11 Nullable, ReadOnly, Rename, RenameAll, Required, SchemaWith, Title, ValueType,
12 WriteOnly, XmlAttr,
13 },
14 impl_into_inner, impl_merge, parse_features,
15 validation::{
16 ExclusiveMaximum, ExclusiveMinimum, MaxItems, MaxLength, MaxProperties, Maximum,
17 MinItems, MinLength, MinProperties, Minimum, MultipleOf, Pattern,
18 },
19 Feature, Merge,
20 },
21 Diagnostics,
22};
23
24#[cfg_attr(feature = "debug", derive(Debug))]
25pub struct NamedFieldStructFeatures(Vec<Feature>);
26
27impl Parse for NamedFieldStructFeatures {
28 fn parse(input: ParseStream) -> syn::Result<Self> {
29 Ok(NamedFieldStructFeatures(parse_features!(
30 input as Example,
31 Examples,
32 XmlAttr,
33 Title,
34 RenameAll,
35 MaxProperties,
36 MinProperties,
37 As,
38 crate::component::features::attributes::Default,
39 Deprecated,
40 Description,
41 Bound,
42 NoRecursion
43 )))
44 }
45}
46
47impl_into_inner!(NamedFieldStructFeatures);
48
49#[cfg_attr(feature = "debug", derive(Debug))]
50pub struct UnnamedFieldStructFeatures(Vec<Feature>);
51
52impl Parse for UnnamedFieldStructFeatures {
53 fn parse(input: ParseStream) -> syn::Result<Self> {
54 Ok(UnnamedFieldStructFeatures(parse_features!(
55 input as Example,
56 Examples,
57 crate::component::features::attributes::Default,
58 Title,
59 Format,
60 ValueType,
61 As,
62 Deprecated,
63 Description,
64 ContentEncoding,
65 ContentMediaType,
66 Bound,
67 NoRecursion,
68 Pattern
69 )))
70 }
71}
72
73impl_into_inner!(UnnamedFieldStructFeatures);
74
75pub struct EnumFeatures(Vec<Feature>);
76
77impl Parse for EnumFeatures {
78 fn parse(input: ParseStream) -> syn::Result<Self> {
79 Ok(EnumFeatures(parse_features!(
80 input as Example,
81 Examples,
82 crate::component::features::attributes::Default,
83 Title,
84 RenameAll,
85 As,
86 Deprecated,
87 Description,
88 Bound
89 )))
90 }
91}
92
93impl_into_inner!(EnumFeatures);
94
95pub struct MixedEnumFeatures(Vec<Feature>);
96
97impl Parse for MixedEnumFeatures {
98 fn parse(input: ParseStream) -> syn::Result<Self> {
99 Ok(MixedEnumFeatures(parse_features!(
100 input as Example,
101 Examples,
102 crate::component::features::attributes::Default,
103 Title,
104 RenameAll,
105 As,
106 Deprecated,
107 Description,
108 Discriminator,
109 NoRecursion
110 )))
111 }
112}
113
114impl_into_inner!(MixedEnumFeatures);
115
116pub struct NamedFieldFeatures(Vec<Feature>);
117
118impl Parse for NamedFieldFeatures {
119 fn parse(input: ParseStream) -> syn::Result<Self> {
120 Ok(NamedFieldFeatures(parse_features!(
121 input as Example,
122 Examples,
123 ValueType,
124 Format,
125 crate::component::features::attributes::Default,
126 WriteOnly,
127 ReadOnly,
128 XmlAttr,
129 Inline,
130 Nullable,
131 Rename,
132 MultipleOf,
133 Maximum,
134 Minimum,
135 ExclusiveMaximum,
136 ExclusiveMinimum,
137 MaxLength,
138 MinLength,
139 Pattern,
140 MaxItems,
141 MinItems,
142 SchemaWith,
143 AdditionalProperties,
144 Required,
145 Deprecated,
146 ContentEncoding,
147 ContentMediaType,
148 Ignore,
149 NoRecursion
150 )))
151 }
152}
153
154impl_into_inner!(NamedFieldFeatures);
155
156pub struct EnumNamedFieldVariantFeatures(Vec<Feature>);
157
158impl Parse for EnumNamedFieldVariantFeatures {
159 fn parse(input: ParseStream) -> syn::Result<Self> {
160 Ok(EnumNamedFieldVariantFeatures(parse_features!(
161 input as Example,
162 Examples,
163 crate::component::features::attributes::Default,
164 XmlAttr,
165 Title,
166 Rename,
167 RenameAll,
168 Deprecated,
169 MaxProperties,
170 MinProperties,
171 NoRecursion
172 )))
173 }
174}
175
176impl_into_inner!(EnumNamedFieldVariantFeatures);
177
178pub struct EnumUnnamedFieldVariantFeatures(Vec<Feature>);
179
180impl Parse for EnumUnnamedFieldVariantFeatures {
181 fn parse(input: ParseStream) -> syn::Result<Self> {
182 Ok(EnumUnnamedFieldVariantFeatures(parse_features!(
183 input as Example,
184 Examples,
185 crate::component::features::attributes::Default,
186 Title,
187 Format,
188 ValueType,
189 Rename,
190 Deprecated,
191 NoRecursion
192 )))
193 }
194}
195
196impl_into_inner!(EnumUnnamedFieldVariantFeatures);
197
198pub trait FromAttributes {
199 fn parse_features<T>(&self) -> Result<Option<T>, Diagnostics>
200 where
201 T: Parse + Merge<T>;
202}
203
204impl FromAttributes for &'_ [Attribute] {
205 fn parse_features<T>(&self) -> Result<Option<T>, Diagnostics>
206 where
207 T: Parse + Merge<T>,
208 {
209 parse_schema_features::<T>(self)
210 }
211}
212
213impl FromAttributes for Vec<Attribute> {
214 fn parse_features<T>(&self) -> Result<Option<T>, Diagnostics>
215 where
216 T: Parse + Merge<T>,
217 {
218 parse_schema_features::<T>(self)
219 }
220}
221
222impl_merge!(
223 NamedFieldStructFeatures,
224 UnnamedFieldStructFeatures,
225 EnumFeatures,
226 MixedEnumFeatures,
227 NamedFieldFeatures,
228 EnumNamedFieldVariantFeatures,
229 EnumUnnamedFieldVariantFeatures
230);
231
232pub fn parse_schema_features<T: Sized + Parse + Merge<T>>(
233 attributes: &[Attribute],
234) -> Result<Option<T>, Diagnostics> {
235 Ok(attributes
236 .iter()
237 .filter(|attribute| {
238 attribute
239 .path()
240 .get_ident()
241 .map(|ident| *ident == "schema")
242 .unwrap_or(false)
243 })
244 .map(|attribute| attribute.parse_args::<T>().map_err(Diagnostics::from))
245 .collect::<Result<Vec<T>, Diagnostics>>()?
246 .into_iter()
247 .reduce(|acc, item| acc.merge(item)))
248}
249
250pub fn parse_schema_features_with<
251 T: Merge<T>,
252 P: for<'r> FnOnce(&'r ParseBuffer<'r>) -> syn::Result<T> + Copy,
253>(
254 attributes: &[Attribute],
255 parser: P,
256) -> Result<Option<T>, Diagnostics> {
257 Ok(attributes
258 .iter()
259 .filter(|attribute| {
260 attribute
261 .path()
262 .get_ident()
263 .map(|ident| *ident == "schema")
264 .unwrap_or(false)
265 })
266 .map(|attributes| {
267 attributes
268 .parse_args_with(parser)
269 .map_err(Diagnostics::from)
270 })
271 .collect::<Result<Vec<T>, Diagnostics>>()?
272 .into_iter()
273 .reduce(|acc, item| acc.merge(item)))
274}