1use std::{fmt::Display, mem, str::FromStr};
2
3use proc_macro2::{Ident, Span, TokenStream};
4use proc_macro_error::abort;
5use quote::{quote, ToTokens};
6use syn::{parenthesized, parse::ParseStream, LitFloat, LitInt, LitStr, TypePath};
7
8use crate::{
9 parse_utils,
10 path::parameter::{self, ParameterStyle},
11 schema_type::{SchemaFormat, SchemaType},
12 AnyValue,
13};
14
15use super::{schema, serde::RenameRule, GenericType, TypeTree};
16
17fn parse_integer<T: FromStr + Display>(input: ParseStream) -> syn::Result<T>
19where
20 <T as FromStr>::Err: Display,
21{
22 parse_utils::parse_next(input, || input.parse::<LitInt>()?.base10_parse())
23}
24
25fn parse_number<T>(input: ParseStream) -> syn::Result<T>
27where
28 T: FromStr,
29 <T as FromStr>::Err: Display,
30{
31 parse_utils::parse_next(input, || {
32 let lookup = input.lookahead1();
33 if lookup.peek(LitInt) {
34 input.parse::<LitInt>()?.base10_parse()
35 } else if lookup.peek(LitFloat) {
36 input.parse::<LitFloat>()?.base10_parse()
37 } else {
38 Err(lookup.error())
39 }
40 })
41}
42
43pub trait Name {
44 fn get_name() -> &'static str
45 where
46 Self: Sized;
47}
48
49macro_rules! name {
50 ( $ident:ident = $name:literal ) => {
51 impl Name for $ident {
52 fn get_name() -> &'static str {
53 $name
54 }
55 }
56
57 impl Display for $ident {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 let name = <Self as Name>::get_name();
60 write!(f, "{name}")
61 }
62 }
63 };
64}
65
66pub trait Validatable {
68 fn is_validatable(&self) -> bool {
69 false
70 }
71}
72
73pub trait Validate: Validatable {
74 fn validate(&self, validator: impl Validator);
76}
77
78pub trait Parse {
79 fn parse(input: ParseStream, attribute: Ident) -> syn::Result<Self>
80 where
81 Self: std::marker::Sized;
82}
83
84#[cfg_attr(feature = "debug", derive(Debug))]
85#[derive(Clone)]
86pub enum Feature {
87 Example(Example),
88 Default(Default),
89 Inline(Inline),
90 XmlAttr(XmlAttr),
91 Format(Format),
92 ValueType(ValueType),
93 WriteOnly(WriteOnly),
94 ReadOnly(ReadOnly),
95 Title(Title),
96 Nullable(Nullable),
97 Rename(Rename),
98 RenameAll(RenameAll),
99 Style(Style),
100 AllowReserved(AllowReserved),
101 Explode(Explode),
102 ParameterIn(ParameterIn),
103 IntoParamsNames(Names),
104 MultipleOf(MultipleOf),
105 Maximum(Maximum),
106 Minimum(Minimum),
107 ExclusiveMaximum(ExclusiveMaximum),
108 ExclusiveMinimum(ExclusiveMinimum),
109 MaxLength(MaxLength),
110 MinLength(MinLength),
111 Pattern(Pattern),
112 MaxItems(MaxItems),
113 MinItems(MinItems),
114 MaxProperties(MaxProperties),
115 MinProperties(MinProperties),
116 SchemaWith(SchemaWith),
117 Description(Description),
118 Deprecated(Deprecated),
119 As(As),
120 AdditionalProperties(AdditionalProperties),
121 Required(Required),
122}
123
124impl Feature {
125 pub fn validate(&self, schema_type: &SchemaType, type_tree: &TypeTree) {
126 match self {
127 Feature::MultipleOf(multiple_of) => multiple_of.validate(
128 ValidatorChain::new(&IsNumber(schema_type)).next(&AboveZeroF64(multiple_of.0)),
129 ),
130 Feature::Maximum(maximum) => maximum.validate(IsNumber(schema_type)),
131 Feature::Minimum(minimum) => minimum.validate(IsNumber(schema_type)),
132 Feature::ExclusiveMaximum(exclusive_maximum) => {
133 exclusive_maximum.validate(IsNumber(schema_type))
134 }
135 Feature::ExclusiveMinimum(exclusive_minimum) => {
136 exclusive_minimum.validate(IsNumber(schema_type))
137 }
138 Feature::MaxLength(max_length) => max_length.validate(
139 ValidatorChain::new(&IsString(schema_type)).next(&AboveZeroUsize(max_length.0)),
140 ),
141 Feature::MinLength(min_length) => min_length.validate(
142 ValidatorChain::new(&IsString(schema_type)).next(&AboveZeroUsize(min_length.0)),
143 ),
144 Feature::Pattern(pattern) => pattern.validate(IsString(schema_type)),
145 Feature::MaxItems(max_items) => max_items.validate(
146 ValidatorChain::new(&AboveZeroUsize(max_items.0)).next(&IsVec(type_tree)),
147 ),
148 Feature::MinItems(min_items) => min_items.validate(
149 ValidatorChain::new(&AboveZeroUsize(min_items.0)).next(&IsVec(type_tree)),
150 ),
151 _unsupported_variant => {
152 const SUPPORTED_VARIANTS: [&str; 10] = [
153 "multiple_of",
154 "maximum",
155 "minimum",
156 "exclusive_maximum",
157 "exclusive_minimum",
158 "max_length",
159 "min_length",
160 "pattern",
161 "max_items",
162 "min_items",
163 ];
164 panic!(
165 "Unsupported variant: `{variant}` for Validate::validate, expected one of: {variants}",
166 variant = _unsupported_variant,
167 variants = SUPPORTED_VARIANTS.join(", ")
168 )
169 }
170 }
171 }
172}
173
174impl ToTokens for Feature {
175 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
176 let feature = match &self {
177 Feature::Default(default) => quote! { .default(#default) },
178 Feature::Example(example) => quote! { .example(Some(#example)) },
179 Feature::XmlAttr(xml) => quote! { .xml(Some(#xml)) },
180 Feature::Format(format) => quote! { .format(Some(#format)) },
181 Feature::WriteOnly(write_only) => quote! { .write_only(Some(#write_only)) },
182 Feature::ReadOnly(read_only) => quote! { .read_only(Some(#read_only)) },
183 Feature::Title(title) => quote! { .title(Some(#title)) },
184 Feature::Nullable(nullable) => quote! { .nullable(#nullable) },
185 Feature::Rename(rename) => rename.to_token_stream(),
186 Feature::Style(style) => quote! { .style(Some(#style)) },
187 Feature::ParameterIn(parameter_in) => quote! { .parameter_in(#parameter_in) },
188 Feature::MultipleOf(multiple_of) => quote! { .multiple_of(Some(#multiple_of)) },
189 Feature::AllowReserved(allow_reserved) => {
190 quote! { .allow_reserved(Some(#allow_reserved)) }
191 }
192 Feature::Explode(explode) => quote! { .explode(Some(#explode)) },
193 Feature::Maximum(maximum) => quote! { .maximum(Some(#maximum)) },
194 Feature::Minimum(minimum) => quote! { .minimum(Some(#minimum)) },
195 Feature::ExclusiveMaximum(exclusive_maximum) => {
196 quote! { .exclusive_maximum(Some(#exclusive_maximum)) }
197 }
198 Feature::ExclusiveMinimum(exclusive_minimum) => {
199 quote! { .exclusive_minimum(Some(#exclusive_minimum)) }
200 }
201 Feature::MaxLength(max_length) => quote! { .max_length(Some(#max_length)) },
202 Feature::MinLength(min_length) => quote! { .min_length(Some(#min_length)) },
203 Feature::Pattern(pattern) => quote! { .pattern(Some(#pattern)) },
204 Feature::MaxItems(max_items) => quote! { .max_items(Some(#max_items)) },
205 Feature::MinItems(min_items) => quote! { .min_items(Some(#min_items)) },
206 Feature::MaxProperties(max_properties) => {
207 quote! { .max_properties(Some(#max_properties)) }
208 }
209 Feature::MinProperties(min_properties) => {
210 quote! { .max_properties(Some(#min_properties)) }
211 }
212 Feature::SchemaWith(schema_with) => schema_with.to_token_stream(),
213 Feature::Description(description) => quote! { .description(Some(#description)) },
214 Feature::Deprecated(deprecated) => quote! { .deprecated(Some(#deprecated)) },
215 Feature::AdditionalProperties(additional_properties) => {
216 quote! { .additional_properties(Some(#additional_properties)) }
217 }
218 Feature::RenameAll(_) => {
219 abort! {
220 Span::call_site(),
221 "RenameAll feature does not support `ToTokens`"
222 }
223 }
224 Feature::ValueType(_) => {
225 abort! {
226 Span::call_site(),
227 "ValueType feature does not support `ToTokens`";
228 help = "ValueType is supposed to be used with `TypeTree` in same manner as a resolved struct/field type.";
229 }
230 }
231 Feature::Inline(_) => {
232 TokenStream::new()
234 }
235 Feature::IntoParamsNames(_) => {
236 abort! {
237 Span::call_site(),
238 "Names feature does not support `ToTokens`";
239 help = "Names is only used with IntoParams to artificially give names for unnamed struct type `IntoParams`."
240 }
241 }
242 Feature::As(_) => {
243 abort!(Span::call_site(), "As does not support `ToTokens`")
244 }
245 Feature::Required(required) => {
246 let name = <Required as Name>::get_name();
247 quote! { .#name(#required) }
248 }
249 };
250
251 tokens.extend(feature)
252 }
253}
254
255impl Display for Feature {
256 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
257 match self {
258 Feature::Default(default) => default.fmt(f),
259 Feature::Example(example) => example.fmt(f),
260 Feature::XmlAttr(xml) => xml.fmt(f),
261 Feature::Format(format) => format.fmt(f),
262 Feature::WriteOnly(write_only) => write_only.fmt(f),
263 Feature::ReadOnly(read_only) => read_only.fmt(f),
264 Feature::Title(title) => title.fmt(f),
265 Feature::Nullable(nullable) => nullable.fmt(f),
266 Feature::Rename(rename) => rename.fmt(f),
267 Feature::Style(style) => style.fmt(f),
268 Feature::ParameterIn(parameter_in) => parameter_in.fmt(f),
269 Feature::AllowReserved(allow_reserved) => allow_reserved.fmt(f),
270 Feature::Explode(explode) => explode.fmt(f),
271 Feature::RenameAll(rename_all) => rename_all.fmt(f),
272 Feature::ValueType(value_type) => value_type.fmt(f),
273 Feature::Inline(inline) => inline.fmt(f),
274 Feature::IntoParamsNames(names) => names.fmt(f),
275 Feature::MultipleOf(multiple_of) => multiple_of.fmt(f),
276 Feature::Maximum(maximum) => maximum.fmt(f),
277 Feature::Minimum(minimum) => minimum.fmt(f),
278 Feature::ExclusiveMaximum(exclusive_maximum) => exclusive_maximum.fmt(f),
279 Feature::ExclusiveMinimum(exclusive_minimum) => exclusive_minimum.fmt(f),
280 Feature::MaxLength(max_length) => max_length.fmt(f),
281 Feature::MinLength(min_length) => min_length.fmt(f),
282 Feature::Pattern(pattern) => pattern.fmt(f),
283 Feature::MaxItems(max_items) => max_items.fmt(f),
284 Feature::MinItems(min_items) => min_items.fmt(f),
285 Feature::MaxProperties(max_properties) => max_properties.fmt(f),
286 Feature::MinProperties(min_properties) => min_properties.fmt(f),
287 Feature::SchemaWith(schema_with) => schema_with.fmt(f),
288 Feature::Description(description) => description.fmt(f),
289 Feature::Deprecated(deprecated) => deprecated.fmt(f),
290 Feature::As(as_feature) => as_feature.fmt(f),
291 Feature::AdditionalProperties(additional_properties) => additional_properties.fmt(f),
292 Feature::Required(required) => required.fmt(f),
293 }
294 }
295}
296
297impl Validatable for Feature {
298 fn is_validatable(&self) -> bool {
299 match &self {
300 Feature::Default(default) => default.is_validatable(),
301 Feature::Example(example) => example.is_validatable(),
302 Feature::XmlAttr(xml) => xml.is_validatable(),
303 Feature::Format(format) => format.is_validatable(),
304 Feature::WriteOnly(write_only) => write_only.is_validatable(),
305 Feature::ReadOnly(read_only) => read_only.is_validatable(),
306 Feature::Title(title) => title.is_validatable(),
307 Feature::Nullable(nullable) => nullable.is_validatable(),
308 Feature::Rename(rename) => rename.is_validatable(),
309 Feature::Style(style) => style.is_validatable(),
310 Feature::ParameterIn(parameter_in) => parameter_in.is_validatable(),
311 Feature::AllowReserved(allow_reserved) => allow_reserved.is_validatable(),
312 Feature::Explode(explode) => explode.is_validatable(),
313 Feature::RenameAll(rename_all) => rename_all.is_validatable(),
314 Feature::ValueType(value_type) => value_type.is_validatable(),
315 Feature::Inline(inline) => inline.is_validatable(),
316 Feature::IntoParamsNames(names) => names.is_validatable(),
317 Feature::MultipleOf(multiple_of) => multiple_of.is_validatable(),
318 Feature::Maximum(maximum) => maximum.is_validatable(),
319 Feature::Minimum(minimum) => minimum.is_validatable(),
320 Feature::ExclusiveMaximum(exclusive_maximum) => exclusive_maximum.is_validatable(),
321 Feature::ExclusiveMinimum(exclusive_minimum) => exclusive_minimum.is_validatable(),
322 Feature::MaxLength(max_length) => max_length.is_validatable(),
323 Feature::MinLength(min_length) => min_length.is_validatable(),
324 Feature::Pattern(pattern) => pattern.is_validatable(),
325 Feature::MaxItems(max_items) => max_items.is_validatable(),
326 Feature::MinItems(min_items) => min_items.is_validatable(),
327 Feature::MaxProperties(max_properties) => max_properties.is_validatable(),
328 Feature::MinProperties(min_properties) => min_properties.is_validatable(),
329 Feature::SchemaWith(schema_with) => schema_with.is_validatable(),
330 Feature::Description(description) => description.is_validatable(),
331 Feature::Deprecated(deprecated) => deprecated.is_validatable(),
332 Feature::As(as_feature) => as_feature.is_validatable(),
333 Feature::AdditionalProperties(additional_properties) => {
334 additional_properties.is_validatable()
335 }
336 Feature::Required(required) => required.is_validatable(),
337 }
338 }
339}
340
341macro_rules! is_validatable {
342 ( $( $ident:ident => $validatable:literal ),* ) => {
343 $(
344 impl Validatable for $ident {
345 fn is_validatable(&self) -> bool {
346 $validatable
347 }
348 }
349 )*
350 };
351}
352
353is_validatable! {
354 Default => false,
355 Example => false,
356 XmlAttr => false,
357 Format => false,
358 WriteOnly => false,
359 ReadOnly => false,
360 Title => false,
361 Nullable => false,
362 Rename => false,
363 Style => false,
364 ParameterIn => false,
365 AllowReserved => false,
366 Explode => false,
367 RenameAll => false,
368 ValueType => false,
369 Inline => false,
370 Names => false,
371 MultipleOf => true,
372 Maximum => true,
373 Minimum => true,
374 ExclusiveMaximum => true,
375 ExclusiveMinimum => true,
376 MaxLength => true,
377 MinLength => true,
378 Pattern => true,
379 MaxItems => true,
380 MinItems => true,
381 MaxProperties => false,
382 MinProperties => false,
383 SchemaWith => false,
384 Description => false,
385 Deprecated => false,
386 As => false,
387 AdditionalProperties => false,
388 Required => false
389}
390
391#[derive(Clone)]
392#[cfg_attr(feature = "debug", derive(Debug))]
393pub struct Example(AnyValue);
394
395impl Parse for Example {
396 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
397 parse_utils::parse_next(input, || AnyValue::parse_any(input)).map(Self)
398 }
399}
400
401impl ToTokens for Example {
402 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
403 tokens.extend(self.0.to_token_stream())
404 }
405}
406
407impl From<Example> for Feature {
408 fn from(value: Example) -> Self {
409 Feature::Example(value)
410 }
411}
412
413name!(Example = "example");
414
415#[derive(Clone)]
416#[cfg_attr(feature = "debug", derive(Debug))]
417pub struct Default(pub(crate) Option<AnyValue>);
418
419impl Default {
420 pub fn new_default_trait(struct_ident: Ident, field_ident: syn::Member) -> Self {
421 Self(Some(AnyValue::new_default_trait(struct_ident, field_ident)))
422 }
423}
424
425impl Parse for Default {
426 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
427 if input.peek(syn::Token![=]) {
428 parse_utils::parse_next(input, || AnyValue::parse_any(input)).map(|any| Self(Some(any)))
429 } else {
430 Ok(Self(None))
431 }
432 }
433}
434
435impl ToTokens for Default {
436 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
437 match &self.0 {
438 Some(inner) => tokens.extend(quote! {Some(#inner)}),
439 None => tokens.extend(quote! {None}),
440 }
441 }
442}
443
444impl From<self::Default> for Feature {
445 fn from(value: self::Default) -> Self {
446 Feature::Default(value)
447 }
448}
449
450name!(Default = "default");
451
452#[derive(Clone)]
453#[cfg_attr(feature = "debug", derive(Debug))]
454pub struct Inline(bool);
455
456impl Parse for Inline {
457 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
458 parse_utils::parse_bool_or_true(input).map(Self)
459 }
460}
461
462impl From<bool> for Inline {
463 fn from(value: bool) -> Self {
464 Inline(value)
465 }
466}
467
468impl From<Inline> for Feature {
469 fn from(value: Inline) -> Self {
470 Feature::Inline(value)
471 }
472}
473
474name!(Inline = "inline");
475
476#[derive(Default, Clone)]
477#[cfg_attr(feature = "debug", derive(Debug))]
478pub struct XmlAttr(schema::xml::XmlAttr);
479
480impl XmlAttr {
481 pub fn split_for_vec(&mut self, type_tree: &TypeTree) -> (Option<XmlAttr>, Option<XmlAttr>) {
484 if matches!(type_tree.generic_type, Some(GenericType::Vec)) {
485 let mut value_xml = mem::take(self);
486 let vec_xml = schema::xml::XmlAttr::with_wrapped(
487 mem::take(&mut value_xml.0.is_wrapped),
488 mem::take(&mut value_xml.0.wrap_name),
489 );
490
491 (Some(XmlAttr(vec_xml)), Some(value_xml))
492 } else {
493 self.validate_xml(&self.0);
494
495 (None, Some(mem::take(self)))
496 }
497 }
498
499 #[inline]
500 fn validate_xml(&self, xml: &schema::xml::XmlAttr) {
501 if let Some(wrapped_ident) = xml.is_wrapped.as_ref() {
502 abort! {wrapped_ident, "cannot use `wrapped` attribute in non slice field type";
503 help = "Try removing `wrapped` attribute or make your field `Vec`"
504 }
505 }
506 }
507}
508
509impl Parse for XmlAttr {
510 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
511 let xml;
512 parenthesized!(xml in input);
513 xml.parse::<schema::xml::XmlAttr>().map(Self)
514 }
515}
516
517impl ToTokens for XmlAttr {
518 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
519 tokens.extend(self.0.to_token_stream())
520 }
521}
522
523impl From<XmlAttr> for Feature {
524 fn from(value: XmlAttr) -> Self {
525 Feature::XmlAttr(value)
526 }
527}
528
529name!(XmlAttr = "xml");
530
531#[derive(Clone)]
532#[cfg_attr(feature = "debug", derive(Debug))]
533pub struct Format(SchemaFormat<'static>);
534
535impl Parse for Format {
536 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
537 parse_utils::parse_next(input, || input.parse::<SchemaFormat>()).map(Self)
538 }
539}
540
541impl ToTokens for Format {
542 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
543 tokens.extend(self.0.to_token_stream())
544 }
545}
546
547impl From<Format> for Feature {
548 fn from(value: Format) -> Self {
549 Feature::Format(value)
550 }
551}
552
553name!(Format = "format");
554
555#[derive(Clone)]
556#[cfg_attr(feature = "debug", derive(Debug))]
557pub struct ValueType(syn::Type);
558
559impl ValueType {
560 pub fn as_type_tree(&self) -> TypeTree {
562 TypeTree::from_type(&self.0)
563 }
564}
565
566impl Parse for ValueType {
567 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
568 parse_utils::parse_next(input, || input.parse::<syn::Type>()).map(Self)
569 }
570}
571
572impl From<ValueType> for Feature {
573 fn from(value: ValueType) -> Self {
574 Feature::ValueType(value)
575 }
576}
577
578name!(ValueType = "value_type");
579
580#[derive(Clone, Copy)]
581#[cfg_attr(feature = "debug", derive(Debug))]
582pub struct WriteOnly(bool);
583
584impl Parse for WriteOnly {
585 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
586 parse_utils::parse_bool_or_true(input).map(Self)
587 }
588}
589
590impl ToTokens for WriteOnly {
591 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
592 tokens.extend(self.0.to_token_stream())
593 }
594}
595
596impl From<WriteOnly> for Feature {
597 fn from(value: WriteOnly) -> Self {
598 Feature::WriteOnly(value)
599 }
600}
601
602name!(WriteOnly = "write_only");
603
604#[derive(Clone, Copy)]
605#[cfg_attr(feature = "debug", derive(Debug))]
606pub struct ReadOnly(bool);
607
608impl Parse for ReadOnly {
609 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
610 parse_utils::parse_bool_or_true(input).map(Self)
611 }
612}
613
614impl ToTokens for ReadOnly {
615 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
616 tokens.extend(self.0.to_token_stream())
617 }
618}
619
620impl From<ReadOnly> for Feature {
621 fn from(value: ReadOnly) -> Self {
622 Feature::ReadOnly(value)
623 }
624}
625
626name!(ReadOnly = "read_only");
627
628#[derive(Clone)]
629#[cfg_attr(feature = "debug", derive(Debug))]
630pub struct Title(String);
631
632impl Parse for Title {
633 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
634 parse_utils::parse_next_literal_str(input).map(Self)
635 }
636}
637
638impl ToTokens for Title {
639 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
640 tokens.extend(self.0.to_token_stream())
641 }
642}
643
644impl From<Title> for Feature {
645 fn from(value: Title) -> Self {
646 Feature::Title(value)
647 }
648}
649
650name!(Title = "title");
651
652#[derive(Clone, Copy)]
653#[cfg_attr(feature = "debug", derive(Debug))]
654pub struct Nullable(bool);
655
656impl Nullable {
657 pub fn new() -> Self {
658 Self(true)
659 }
660}
661
662impl Parse for Nullable {
663 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
664 parse_utils::parse_bool_or_true(input).map(Self)
665 }
666}
667
668impl ToTokens for Nullable {
669 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
670 tokens.extend(self.0.to_token_stream())
671 }
672}
673
674impl From<Nullable> for Feature {
675 fn from(value: Nullable) -> Self {
676 Feature::Nullable(value)
677 }
678}
679
680name!(Nullable = "nullable");
681
682#[cfg_attr(feature = "debug", derive(Debug))]
683#[derive(Clone)]
684pub struct Rename(String);
685
686impl Rename {
687 pub fn into_value(self) -> String {
688 self.0
689 }
690}
691
692impl Parse for Rename {
693 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
694 parse_utils::parse_next_literal_str(input).map(Self)
695 }
696}
697
698impl ToTokens for Rename {
699 fn to_tokens(&self, tokens: &mut TokenStream) {
700 tokens.extend(self.0.to_token_stream())
701 }
702}
703
704impl From<Rename> for Feature {
705 fn from(value: Rename) -> Self {
706 Feature::Rename(value)
707 }
708}
709
710name!(Rename = "rename");
711
712#[cfg_attr(feature = "debug", derive(Debug))]
713#[derive(Clone)]
714pub struct RenameAll(RenameRule);
715
716impl RenameAll {
717 pub fn as_rename_rule(&self) -> &RenameRule {
718 &self.0
719 }
720}
721
722impl Parse for RenameAll {
723 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
724 let litstr = parse_utils::parse_next(input, || input.parse::<LitStr>())?;
725
726 litstr
727 .value()
728 .parse::<RenameRule>()
729 .map_err(|error| syn::Error::new(litstr.span(), error.to_string()))
730 .map(Self)
731 }
732}
733
734impl From<RenameAll> for Feature {
735 fn from(value: RenameAll) -> Self {
736 Feature::RenameAll(value)
737 }
738}
739
740name!(RenameAll = "rename_all");
741
742#[cfg_attr(feature = "debug", derive(Debug))]
743#[derive(Clone)]
744pub struct Style(ParameterStyle);
745
746impl From<ParameterStyle> for Style {
747 fn from(style: ParameterStyle) -> Self {
748 Self(style)
749 }
750}
751
752impl Parse for Style {
753 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
754 parse_utils::parse_next(input, || input.parse::<ParameterStyle>().map(Self))
755 }
756}
757
758impl ToTokens for Style {
759 fn to_tokens(&self, tokens: &mut TokenStream) {
760 self.0.to_tokens(tokens)
761 }
762}
763
764impl From<Style> for Feature {
765 fn from(value: Style) -> Self {
766 Feature::Style(value)
767 }
768}
769
770name!(Style = "style");
771
772#[cfg_attr(feature = "debug", derive(Debug))]
773#[derive(Clone)]
774pub struct AllowReserved(bool);
775
776impl Parse for AllowReserved {
777 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
778 parse_utils::parse_bool_or_true(input).map(Self)
779 }
780}
781
782impl ToTokens for AllowReserved {
783 fn to_tokens(&self, tokens: &mut TokenStream) {
784 self.0.to_tokens(tokens)
785 }
786}
787
788impl From<AllowReserved> for Feature {
789 fn from(value: AllowReserved) -> Self {
790 Feature::AllowReserved(value)
791 }
792}
793
794name!(AllowReserved = "allow_reserved");
795
796#[cfg_attr(feature = "debug", derive(Debug))]
797#[derive(Clone)]
798pub struct Explode(bool);
799
800impl Parse for Explode {
801 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
802 parse_utils::parse_bool_or_true(input).map(Self)
803 }
804}
805
806impl ToTokens for Explode {
807 fn to_tokens(&self, tokens: &mut TokenStream) {
808 self.0.to_tokens(tokens)
809 }
810}
811
812impl From<Explode> for Feature {
813 fn from(value: Explode) -> Self {
814 Feature::Explode(value)
815 }
816}
817
818name!(Explode = "explode");
819
820#[cfg_attr(feature = "debug", derive(Debug))]
821#[derive(Clone)]
822pub struct ParameterIn(parameter::ParameterIn);
823
824impl Parse for ParameterIn {
825 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
826 parse_utils::parse_next(input, || input.parse::<parameter::ParameterIn>().map(Self))
827 }
828}
829
830impl ToTokens for ParameterIn {
831 fn to_tokens(&self, tokens: &mut TokenStream) {
832 self.0.to_tokens(tokens);
833 }
834}
835
836impl From<ParameterIn> for Feature {
837 fn from(value: ParameterIn) -> Self {
838 Feature::ParameterIn(value)
839 }
840}
841
842name!(ParameterIn = "parameter_in");
843
844#[cfg_attr(feature = "debug", derive(Debug))]
846#[derive(Clone)]
847pub struct Names(Vec<String>);
848
849impl Names {
850 pub fn into_values(self) -> Vec<String> {
851 self.0
852 }
853}
854
855impl Parse for Names {
856 fn parse(input: syn::parse::ParseStream, _: Ident) -> syn::Result<Self> {
857 Ok(Self(
858 parse_utils::parse_punctuated_within_parenthesis::<LitStr>(input)?
859 .iter()
860 .map(LitStr::value)
861 .collect(),
862 ))
863 }
864}
865
866impl From<Names> for Feature {
867 fn from(value: Names) -> Self {
868 Feature::IntoParamsNames(value)
869 }
870}
871
872name!(Names = "names");
873
874#[cfg_attr(feature = "debug", derive(Debug))]
875#[derive(Clone)]
876pub struct MultipleOf(f64, Ident);
877
878impl Validate for MultipleOf {
879 fn validate(&self, validator: impl Validator) {
880 if let Err(error) = validator.is_valid() {
881 abort! {self.1, "`multiple_of` error: {}", error;
882 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-multipleof`"
883 }
884 };
885 }
886}
887
888impl Parse for MultipleOf {
889 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self> {
890 parse_number(input).map(|multiple_of| Self(multiple_of, ident))
891 }
892}
893
894impl ToTokens for MultipleOf {
895 fn to_tokens(&self, tokens: &mut TokenStream) {
896 self.0.to_tokens(tokens);
897 }
898}
899
900impl From<MultipleOf> for Feature {
901 fn from(value: MultipleOf) -> Self {
902 Feature::MultipleOf(value)
903 }
904}
905
906name!(MultipleOf = "multiple_of");
907
908#[cfg_attr(feature = "debug", derive(Debug))]
909#[derive(Clone)]
910pub struct Maximum(f64, Ident);
911
912impl Validate for Maximum {
913 fn validate(&self, validator: impl Validator) {
914 if let Err(error) = validator.is_valid() {
915 abort! {self.1, "`maximum` error: {}", error;
916 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-maximum`"
917 }
918 }
919 }
920}
921
922impl Parse for Maximum {
923 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
924 where
925 Self: Sized,
926 {
927 parse_number(input).map(|maximum| Self(maximum, ident))
928 }
929}
930
931impl ToTokens for Maximum {
932 fn to_tokens(&self, tokens: &mut TokenStream) {
933 self.0.to_tokens(tokens);
934 }
935}
936
937impl From<Maximum> for Feature {
938 fn from(value: Maximum) -> Self {
939 Feature::Maximum(value)
940 }
941}
942
943name!(Maximum = "maximum");
944
945#[cfg_attr(feature = "debug", derive(Debug))]
946#[derive(Clone)]
947pub struct Minimum(f64, Ident);
948
949impl Minimum {
950 pub fn new(value: f64, span: Span) -> Self {
951 Self(value, Ident::new("empty", span))
952 }
953}
954
955impl Validate for Minimum {
956 fn validate(&self, validator: impl Validator) {
957 if let Err(error) = validator.is_valid() {
958 abort! {self.1, "`minimum` error: {}", error;
959 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-minimum`"
960 }
961 }
962 }
963}
964
965impl Parse for Minimum {
966 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
967 where
968 Self: Sized,
969 {
970 parse_number(input).map(|maximum| Self(maximum, ident))
971 }
972}
973
974impl ToTokens for Minimum {
975 fn to_tokens(&self, tokens: &mut TokenStream) {
976 self.0.to_tokens(tokens);
977 }
978}
979
980impl From<Minimum> for Feature {
981 fn from(value: Minimum) -> Self {
982 Feature::Minimum(value)
983 }
984}
985
986name!(Minimum = "minimum");
987
988#[cfg_attr(feature = "debug", derive(Debug))]
989#[derive(Clone)]
990pub struct ExclusiveMaximum(f64, Ident);
991
992impl Validate for ExclusiveMaximum {
993 fn validate(&self, validator: impl Validator) {
994 if let Err(error) = validator.is_valid() {
995 abort! {self.1, "`exclusive_maximum` error: {}", error;
996 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-exclusivemaximum`"
997 }
998 }
999 }
1000}
1001
1002impl Parse for ExclusiveMaximum {
1003 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1004 where
1005 Self: Sized,
1006 {
1007 parse_number(input).map(|max| Self(max, ident))
1008 }
1009}
1010
1011impl ToTokens for ExclusiveMaximum {
1012 fn to_tokens(&self, tokens: &mut TokenStream) {
1013 self.0.to_tokens(tokens);
1014 }
1015}
1016
1017impl From<ExclusiveMaximum> for Feature {
1018 fn from(value: ExclusiveMaximum) -> Self {
1019 Feature::ExclusiveMaximum(value)
1020 }
1021}
1022
1023name!(ExclusiveMaximum = "exclusive_maximum");
1024
1025#[cfg_attr(feature = "debug", derive(Debug))]
1026#[derive(Clone)]
1027pub struct ExclusiveMinimum(f64, Ident);
1028
1029impl Validate for ExclusiveMinimum {
1030 fn validate(&self, validator: impl Validator) {
1031 if let Err(error) = validator.is_valid() {
1032 abort! {self.1, "`exclusive_minimum` error: {}", error;
1033 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-exclusiveminimum`"
1034 }
1035 }
1036 }
1037}
1038
1039impl Parse for ExclusiveMinimum {
1040 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1041 where
1042 Self: Sized,
1043 {
1044 parse_number(input).map(|min| Self(min, ident))
1045 }
1046}
1047
1048impl ToTokens for ExclusiveMinimum {
1049 fn to_tokens(&self, tokens: &mut TokenStream) {
1050 self.0.to_tokens(tokens);
1051 }
1052}
1053
1054impl From<ExclusiveMinimum> for Feature {
1055 fn from(value: ExclusiveMinimum) -> Self {
1056 Feature::ExclusiveMinimum(value)
1057 }
1058}
1059
1060name!(ExclusiveMinimum = "exclusive_minimum");
1061
1062#[cfg_attr(feature = "debug", derive(Debug))]
1063#[derive(Clone)]
1064pub struct MaxLength(usize, Ident);
1065
1066impl Validate for MaxLength {
1067 fn validate(&self, validator: impl Validator) {
1068 if let Err(error) = validator.is_valid() {
1069 abort! {self.1, "`max_length` error: {}", error;
1070 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-maxlength`"
1071 }
1072 }
1073 }
1074}
1075
1076impl Parse for MaxLength {
1077 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1078 where
1079 Self: Sized,
1080 {
1081 parse_integer(input).map(|max_length| Self(max_length, ident))
1082 }
1083}
1084
1085impl ToTokens for MaxLength {
1086 fn to_tokens(&self, tokens: &mut TokenStream) {
1087 self.0.to_tokens(tokens);
1088 }
1089}
1090
1091impl From<MaxLength> for Feature {
1092 fn from(value: MaxLength) -> Self {
1093 Feature::MaxLength(value)
1094 }
1095}
1096
1097name!(MaxLength = "max_length");
1098
1099#[cfg_attr(feature = "debug", derive(Debug))]
1100#[derive(Clone)]
1101pub struct MinLength(usize, Ident);
1102
1103impl Validate for MinLength {
1104 fn validate(&self, validator: impl Validator) {
1105 if let Err(error) = validator.is_valid() {
1106 abort! {self.1, "`min_length` error: {}", error;
1107 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-minlength`"
1108 }
1109 }
1110 }
1111}
1112
1113impl Parse for MinLength {
1114 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1115 where
1116 Self: Sized,
1117 {
1118 parse_integer(input).map(|max_length| Self(max_length, ident))
1119 }
1120}
1121
1122impl ToTokens for MinLength {
1123 fn to_tokens(&self, tokens: &mut TokenStream) {
1124 self.0.to_tokens(tokens);
1125 }
1126}
1127
1128impl From<MinLength> for Feature {
1129 fn from(value: MinLength) -> Self {
1130 Feature::MinLength(value)
1131 }
1132}
1133
1134name!(MinLength = "min_length");
1135
1136#[cfg_attr(feature = "debug", derive(Debug))]
1137#[derive(Clone)]
1138pub struct Pattern(String, Ident);
1139
1140impl Validate for Pattern {
1141 fn validate(&self, validator: impl Validator) {
1142 if let Err(error) = validator.is_valid() {
1143 abort! {self.1, "`pattern` error: {}", error;
1144 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-pattern`"
1145 }
1146 }
1147 }
1148}
1149
1150impl Parse for Pattern {
1151 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1152 where
1153 Self: Sized,
1154 {
1155 parse_utils::parse_next(input, || input.parse::<LitStr>())
1156 .map(|pattern| Self(pattern.value(), ident))
1157 }
1158}
1159
1160impl ToTokens for Pattern {
1161 fn to_tokens(&self, tokens: &mut TokenStream) {
1162 self.0.to_tokens(tokens);
1163 }
1164}
1165
1166impl From<Pattern> for Feature {
1167 fn from(value: Pattern) -> Self {
1168 Feature::Pattern(value)
1169 }
1170}
1171
1172name!(Pattern = "pattern");
1173
1174#[cfg_attr(feature = "debug", derive(Debug))]
1175#[derive(Clone)]
1176pub struct MaxItems(usize, Ident);
1177
1178impl Validate for MaxItems {
1179 fn validate(&self, validator: impl Validator) {
1180 if let Err(error) = validator.is_valid() {
1181 abort! {self.1, "`max_items` error: {}", error;
1182 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-maxitems"
1183 }
1184 }
1185 }
1186}
1187
1188impl Parse for MaxItems {
1189 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1190 where
1191 Self: Sized,
1192 {
1193 parse_number(input).map(|max_items| Self(max_items, ident))
1194 }
1195}
1196
1197impl ToTokens for MaxItems {
1198 fn to_tokens(&self, tokens: &mut TokenStream) {
1199 self.0.to_tokens(tokens);
1200 }
1201}
1202
1203impl From<MaxItems> for Feature {
1204 fn from(value: MaxItems) -> Self {
1205 Feature::MaxItems(value)
1206 }
1207}
1208
1209name!(MaxItems = "max_items");
1210
1211#[cfg_attr(feature = "debug", derive(Debug))]
1212#[derive(Clone)]
1213pub struct MinItems(usize, Ident);
1214
1215impl Validate for MinItems {
1216 fn validate(&self, validator: impl Validator) {
1217 if let Err(error) = validator.is_valid() {
1218 abort! {self.1, "`min_items` error: {}", error;
1219 help = "See more details: `http://json-schema.org/draft/2020-12/json-schema-validation.html#name-minitems"
1220 }
1221 }
1222 }
1223}
1224
1225impl Parse for MinItems {
1226 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1227 where
1228 Self: Sized,
1229 {
1230 parse_number(input).map(|max_items| Self(max_items, ident))
1231 }
1232}
1233
1234impl ToTokens for MinItems {
1235 fn to_tokens(&self, tokens: &mut TokenStream) {
1236 self.0.to_tokens(tokens);
1237 }
1238}
1239
1240impl From<MinItems> for Feature {
1241 fn from(value: MinItems) -> Self {
1242 Feature::MinItems(value)
1243 }
1244}
1245
1246name!(MinItems = "min_items");
1247
1248#[cfg_attr(feature = "debug", derive(Debug))]
1249#[derive(Clone)]
1250pub struct MaxProperties(usize, Ident);
1251
1252impl Parse for MaxProperties {
1253 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1254 where
1255 Self: Sized,
1256 {
1257 parse_integer(input).map(|max_properties| Self(max_properties, ident))
1258 }
1259}
1260
1261impl ToTokens for MaxProperties {
1262 fn to_tokens(&self, tokens: &mut TokenStream) {
1263 self.0.to_tokens(tokens);
1264 }
1265}
1266
1267impl From<MaxProperties> for Feature {
1268 fn from(value: MaxProperties) -> Self {
1269 Feature::MaxProperties(value)
1270 }
1271}
1272
1273name!(MaxProperties = "max_properties");
1274
1275#[cfg_attr(feature = "debug", derive(Debug))]
1276#[derive(Clone)]
1277pub struct MinProperties(usize, Ident);
1278
1279impl Parse for MinProperties {
1280 fn parse(input: ParseStream, ident: Ident) -> syn::Result<Self>
1281 where
1282 Self: Sized,
1283 {
1284 parse_integer(input).map(|min_properties| Self(min_properties, ident))
1285 }
1286}
1287
1288impl ToTokens for MinProperties {
1289 fn to_tokens(&self, tokens: &mut TokenStream) {
1290 self.0.to_tokens(tokens);
1291 }
1292}
1293
1294impl From<MinProperties> for Feature {
1295 fn from(value: MinProperties) -> Self {
1296 Feature::MinProperties(value)
1297 }
1298}
1299
1300name!(MinProperties = "min_properties");
1301
1302#[cfg_attr(feature = "debug", derive(Debug))]
1303#[derive(Clone)]
1304pub struct SchemaWith(TypePath);
1305
1306impl Parse for SchemaWith {
1307 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self> {
1308 parse_utils::parse_next(input, || input.parse::<TypePath>().map(Self))
1309 }
1310}
1311
1312impl ToTokens for SchemaWith {
1313 fn to_tokens(&self, tokens: &mut TokenStream) {
1314 let path = &self.0;
1315 tokens.extend(quote! {
1316 #path()
1317 })
1318 }
1319}
1320
1321impl From<SchemaWith> for Feature {
1322 fn from(value: SchemaWith) -> Self {
1323 Feature::SchemaWith(value)
1324 }
1325}
1326
1327name!(SchemaWith = "schema_with");
1328
1329#[cfg_attr(feature = "debug", derive(Debug))]
1330#[derive(Clone)]
1331pub struct Description(String);
1332
1333impl Parse for Description {
1334 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self>
1335 where
1336 Self: std::marker::Sized,
1337 {
1338 parse_utils::parse_next_literal_str(input).map(Self)
1339 }
1340}
1341
1342impl ToTokens for Description {
1343 fn to_tokens(&self, tokens: &mut TokenStream) {
1344 self.0.to_tokens(tokens);
1345 }
1346}
1347
1348impl From<String> for Description {
1349 fn from(value: String) -> Self {
1350 Self(value)
1351 }
1352}
1353
1354impl From<Description> for Feature {
1355 fn from(value: Description) -> Self {
1356 Self::Description(value)
1357 }
1358}
1359
1360name!(Description = "description");
1361
1362#[cfg_attr(feature = "debug", derive(Debug))]
1367#[derive(Clone)]
1368pub struct Deprecated(bool);
1369
1370impl Parse for Deprecated {
1371 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self>
1372 where
1373 Self: std::marker::Sized,
1374 {
1375 parse_utils::parse_bool_or_true(input).map(Self)
1376 }
1377}
1378
1379impl ToTokens for Deprecated {
1380 fn to_tokens(&self, tokens: &mut TokenStream) {
1381 let deprecated: crate::Deprecated = self.0.into();
1382 deprecated.to_tokens(tokens);
1383 }
1384}
1385
1386impl From<Deprecated> for Feature {
1387 fn from(value: Deprecated) -> Self {
1388 Self::Deprecated(value)
1389 }
1390}
1391
1392name!(Deprecated = "deprecated");
1393
1394#[cfg_attr(feature = "debug", derive(Debug))]
1395#[derive(Clone)]
1396pub struct As(pub TypePath);
1397
1398impl Parse for As {
1399 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self>
1400 where
1401 Self: std::marker::Sized,
1402 {
1403 parse_utils::parse_next(input, || input.parse()).map(Self)
1404 }
1405}
1406
1407impl From<As> for Feature {
1408 fn from(value: As) -> Self {
1409 Self::As(value)
1410 }
1411}
1412
1413name!(As = "as");
1414
1415#[cfg_attr(feature = "debug", derive(Debug))]
1416#[derive(Clone)]
1417pub struct AdditionalProperties(bool);
1418
1419impl Parse for AdditionalProperties {
1420 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self>
1421 where
1422 Self: std::marker::Sized,
1423 {
1424 parse_utils::parse_bool_or_true(input).map(Self)
1425 }
1426}
1427
1428impl ToTokens for AdditionalProperties {
1429 fn to_tokens(&self, tokens: &mut TokenStream) {
1430 let additional_properties = &self.0;
1431 tokens.extend(quote!(
1432 utoipa::openapi::schema::AdditionalProperties::FreeForm(
1433 #additional_properties
1434 )
1435 ))
1436 }
1437}
1438
1439name!(AdditionalProperties = "additional_properties");
1440
1441impl From<AdditionalProperties> for Feature {
1442 fn from(value: AdditionalProperties) -> Self {
1443 Self::AdditionalProperties(value)
1444 }
1445}
1446
1447#[derive(Clone)]
1448#[cfg_attr(feature = "debug", derive(Debug))]
1449pub struct Required(pub bool);
1450
1451impl Required {
1452 pub fn is_true(&self) -> bool {
1453 self.0
1454 }
1455}
1456
1457impl Parse for Required {
1458 fn parse(input: ParseStream, _: Ident) -> syn::Result<Self>
1459 where
1460 Self: std::marker::Sized,
1461 {
1462 parse_utils::parse_bool_or_true(input).map(Self)
1463 }
1464}
1465
1466impl ToTokens for Required {
1467 fn to_tokens(&self, tokens: &mut TokenStream) {
1468 self.0.to_tokens(tokens)
1469 }
1470}
1471
1472impl From<crate::Required> for Required {
1473 fn from(value: crate::Required) -> Self {
1474 if value == crate::Required::True {
1475 Self(true)
1476 } else {
1477 Self(false)
1478 }
1479 }
1480}
1481
1482impl From<bool> for Required {
1483 fn from(value: bool) -> Self {
1484 Self(value)
1485 }
1486}
1487
1488impl From<Required> for Feature {
1489 fn from(value: Required) -> Self {
1490 Self::Required(value)
1491 }
1492}
1493
1494name!(Required = "required");
1495
1496pub trait Validator {
1497 fn is_valid(&self) -> Result<(), &'static str>;
1498}
1499
1500pub struct IsNumber<'a>(pub &'a SchemaType<'a>);
1501
1502impl Validator for IsNumber<'_> {
1503 fn is_valid(&self) -> Result<(), &'static str> {
1504 if self.0.is_number() {
1505 Ok(())
1506 } else {
1507 Err("can only be used with `number` type")
1508 }
1509 }
1510}
1511
1512pub struct IsString<'a>(&'a SchemaType<'a>);
1513
1514impl Validator for IsString<'_> {
1515 fn is_valid(&self) -> Result<(), &'static str> {
1516 if self.0.is_string() {
1517 Ok(())
1518 } else {
1519 Err("can only be used with `string` type")
1520 }
1521 }
1522}
1523
1524pub struct IsInteger<'a>(&'a SchemaType<'a>);
1525
1526impl Validator for IsInteger<'_> {
1527 fn is_valid(&self) -> Result<(), &'static str> {
1528 if self.0.is_integer() {
1529 Ok(())
1530 } else {
1531 Err("can only be used with `integer` type")
1532 }
1533 }
1534}
1535
1536pub struct IsVec<'a>(&'a TypeTree<'a>);
1537
1538impl Validator for IsVec<'_> {
1539 fn is_valid(&self) -> Result<(), &'static str> {
1540 if self.0.generic_type == Some(GenericType::Vec) {
1541 Ok(())
1542 } else {
1543 Err("can only be used with `Vec`, `array` or `slice` types")
1544 }
1545 }
1546}
1547
1548pub struct AboveZeroUsize(usize);
1549
1550impl Validator for AboveZeroUsize {
1551 fn is_valid(&self) -> Result<(), &'static str> {
1552 if self.0 != 0 {
1553 Ok(())
1554 } else {
1555 Err("can only be above zero value")
1556 }
1557 }
1558}
1559
1560pub struct AboveZeroF64(f64);
1561
1562impl Validator for AboveZeroF64 {
1563 fn is_valid(&self) -> Result<(), &'static str> {
1564 if self.0 > 0.0 {
1565 Ok(())
1566 } else {
1567 Err("can only be above zero value")
1568 }
1569 }
1570}
1571
1572pub struct ValidatorChain<'c> {
1573 inner: &'c dyn Validator,
1574 next: Option<&'c dyn Validator>,
1575}
1576
1577impl Validator for ValidatorChain<'_> {
1578 fn is_valid(&self) -> Result<(), &'static str> {
1579 self.inner.is_valid().and_then(|_| {
1580 if let Some(validator) = self.next.as_ref() {
1581 validator.is_valid()
1582 } else {
1583 Ok(())
1585 }
1586 })
1587 }
1588}
1589
1590impl<'c> ValidatorChain<'c> {
1591 pub fn new(validator: &'c dyn Validator) -> Self {
1592 Self {
1593 inner: validator,
1594 next: None,
1595 }
1596 }
1597
1598 pub fn next(mut self, validator: &'c dyn Validator) -> Self {
1599 self.next = Some(validator);
1600
1601 self
1602 }
1603}
1604
1605macro_rules! parse_features {
1606 ($ident:ident as $( $feature:path ),*) => {
1607 {
1608 fn parse(input: syn::parse::ParseStream) -> syn::Result<Vec<crate::component::features::Feature>> {
1609 let names = [$( <crate::component::features::parse_features!(@as_ident $feature) as crate::component::features::Name>::get_name(), )* ];
1610 let mut features = Vec::<crate::component::features::Feature>::new();
1611 let attributes = names.join(", ");
1612
1613 while !input.is_empty() {
1614 let ident = input.parse::<syn::Ident>().or_else(|_| {
1615 input.parse::<syn::Token![as]>().map(|as_| syn::Ident::new("as", as_.span))
1616 }).map_err(|error| {
1617 syn::Error::new(
1618 error.span(),
1619 format!("unexpected attribute, expected any of: {attributes}, {error}"),
1620 )
1621 })?;
1622 let name = &*ident.to_string();
1623
1624 $(
1625 if name == <crate::component::features::parse_features!(@as_ident $feature) as crate::component::features::Name>::get_name() {
1626 features.push(<$feature as crate::component::features::Parse>::parse(input, ident)?.into());
1627 if !input.is_empty() {
1628 input.parse::<syn::Token![,]>()?;
1629 }
1630 continue;
1631 }
1632 )*
1633
1634 if !names.contains(&name) {
1635 return Err(syn::Error::new(ident.span(), format!("unexpected attribute: {name}, expected any of: {attributes}")))
1636 }
1637 }
1638
1639 Ok(features)
1640 }
1641
1642 parse($ident)?
1643 }
1644 };
1645 (@as_ident $( $tt:tt )* ) => {
1646 $( $tt )*
1647 }
1648}
1649
1650pub(crate) use parse_features;
1651
1652pub trait IsInline {
1653 fn is_inline(&self) -> bool;
1654}
1655
1656impl IsInline for Vec<Feature> {
1657 fn is_inline(&self) -> bool {
1658 self.iter()
1659 .find_map(|feature| match feature {
1660 Feature::Inline(inline) if inline.0 => Some(inline),
1661 _ => None,
1662 })
1663 .is_some()
1664 }
1665}
1666
1667pub trait ToTokensExt {
1668 fn to_token_stream(&self) -> TokenStream;
1669}
1670
1671impl ToTokensExt for Vec<Feature> {
1672 fn to_token_stream(&self) -> TokenStream {
1673 self.iter().fold(TokenStream::new(), |mut tokens, item| {
1674 item.to_tokens(&mut tokens);
1675 tokens
1676 })
1677 }
1678}
1679
1680pub trait FeaturesExt {
1681 fn pop_by(&mut self, op: impl FnMut(&Feature) -> bool) -> Option<Feature>;
1682
1683 fn pop_value_type_feature(&mut self) -> Option<super::features::ValueType>;
1684
1685 fn pop_rename_feature(&mut self) -> Option<Rename>;
1687
1688 fn pop_rename_all_feature(&mut self) -> Option<RenameAll>;
1690
1691 fn extract_vec_xml_feature(&mut self, type_tree: &TypeTree) -> Option<Feature>;
1693}
1694
1695impl FeaturesExt for Vec<Feature> {
1696 fn pop_by(&mut self, op: impl FnMut(&Feature) -> bool) -> Option<Feature> {
1697 self.iter()
1698 .position(op)
1699 .map(|index| self.swap_remove(index))
1700 }
1701
1702 fn pop_value_type_feature(&mut self) -> Option<super::features::ValueType> {
1703 self.pop_by(|feature| matches!(feature, Feature::ValueType(_)))
1704 .and_then(|feature| match feature {
1705 Feature::ValueType(value_type) => Some(value_type),
1706 _ => None,
1707 })
1708 }
1709
1710 fn pop_rename_feature(&mut self) -> Option<Rename> {
1711 self.pop_by(|feature| matches!(feature, Feature::Rename(_)))
1712 .and_then(|feature| match feature {
1713 Feature::Rename(rename) => Some(rename),
1714 _ => None,
1715 })
1716 }
1717
1718 fn pop_rename_all_feature(&mut self) -> Option<RenameAll> {
1719 self.pop_by(|feature| matches!(feature, Feature::RenameAll(_)))
1720 .and_then(|feature| match feature {
1721 Feature::RenameAll(rename_all) => Some(rename_all),
1722 _ => None,
1723 })
1724 }
1725
1726 fn extract_vec_xml_feature(&mut self, type_tree: &TypeTree) -> Option<Feature> {
1727 self.iter_mut().find_map(|feature| match feature {
1728 Feature::XmlAttr(xml_feature) => {
1729 let (vec_xml, value_xml) = xml_feature.split_for_vec(type_tree);
1730
1731 if let Some(mut xml) = value_xml {
1733 mem::swap(xml_feature, &mut xml)
1734 }
1735
1736 vec_xml.map(Feature::XmlAttr)
1737 }
1738 _ => None,
1739 })
1740 }
1741}
1742
1743impl FeaturesExt for Option<Vec<Feature>> {
1744 fn pop_by(&mut self, op: impl FnMut(&Feature) -> bool) -> Option<Feature> {
1745 self.as_mut().and_then(|features| features.pop_by(op))
1746 }
1747
1748 fn pop_value_type_feature(&mut self) -> Option<super::features::ValueType> {
1749 self.as_mut()
1750 .and_then(|features| features.pop_value_type_feature())
1751 }
1752
1753 fn pop_rename_feature(&mut self) -> Option<Rename> {
1754 self.as_mut()
1755 .and_then(|features| features.pop_rename_feature())
1756 }
1757
1758 fn pop_rename_all_feature(&mut self) -> Option<RenameAll> {
1759 self.as_mut()
1760 .and_then(|features| features.pop_rename_all_feature())
1761 }
1762
1763 fn extract_vec_xml_feature(&mut self, type_tree: &TypeTree) -> Option<Feature> {
1764 self.as_mut()
1765 .and_then(|features| features.extract_vec_xml_feature(type_tree))
1766 }
1767}
1768
1769macro_rules! pop_feature {
1770 ($features:ident => $value:pat_param) => {{
1771 $features.pop_by(|feature| matches!(feature, $value))
1772 }};
1773}
1774
1775pub(crate) use pop_feature;
1776
1777macro_rules! pop_feature_as_inner {
1778 ( $features:ident => $($value:tt)* ) => {
1779 crate::component::features::pop_feature!($features => $( $value )* )
1780 .map(|f| match f {
1781 $( $value )* => {
1782 crate::component::features::pop_feature_as_inner!( @as_value $( $value )* )
1783 },
1784 _ => unreachable!()
1785 })
1786 };
1787 ( @as_value $tt:tt :: $tr:tt ( $v:tt ) ) => {
1788 $v
1789 }
1790}
1791
1792pub(crate) use pop_feature_as_inner;
1793
1794pub trait IntoInner<T> {
1795 fn into_inner(self) -> T;
1796}
1797
1798macro_rules! impl_into_inner {
1799 ($ident:ident) => {
1800 impl crate::component::features::IntoInner<Vec<Feature>> for $ident {
1801 fn into_inner(self) -> Vec<Feature> {
1802 self.0
1803 }
1804 }
1805
1806 impl crate::component::features::IntoInner<Option<Vec<Feature>>> for Option<$ident> {
1807 fn into_inner(self) -> Option<Vec<Feature>> {
1808 self.map(crate::component::features::IntoInner::into_inner)
1809 }
1810 }
1811 };
1812}
1813
1814pub(crate) use impl_into_inner;
1815
1816pub trait Merge<T>: IntoInner<Vec<Feature>> {
1817 fn merge(self, from: T) -> Self;
1818}
1819
1820macro_rules! impl_merge {
1821 ( $($ident:ident),* ) => {
1822 $(
1823 impl AsMut<Vec<Feature>> for $ident {
1824 fn as_mut(&mut self) -> &mut Vec<Feature> {
1825 &mut self.0
1826 }
1827 }
1828
1829 impl crate::component::features::Merge<$ident> for $ident {
1830 fn merge(mut self, from: $ident) -> Self {
1831 let a = self.as_mut();
1832 let mut b = from.into_inner();
1833
1834 a.append(&mut b);
1835
1836 self
1837 }
1838 }
1839 )*
1840 };
1841}
1842
1843pub(crate) use impl_merge;
1844
1845impl IntoInner<Vec<Feature>> for Vec<Feature> {
1846 fn into_inner(self) -> Vec<Feature> {
1847 self
1848 }
1849}
1850
1851impl Merge<Vec<Feature>> for Vec<Feature> {
1852 fn merge(mut self, mut from: Vec<Feature>) -> Self {
1853 self.append(&mut from);
1854 self
1855 }
1856}