utoipa_gen/component/features/
validators.rs1use crate::component::{GenericType, TypeTree};
2use crate::schema_type::SchemaType;
3
4use super::validation::NumberValue;
5
6pub trait Validator {
7 fn is_valid(&self) -> Result<(), &'static str>;
8}
9
10pub struct IsNumber<'a>(pub &'a SchemaType<'a>);
11
12impl Validator for IsNumber<'_> {
13 fn is_valid(&self) -> Result<(), &'static str> {
14 if self.0.is_number() {
15 Ok(())
16 } else {
17 Err("can only be used with `number` type")
18 }
19 }
20}
21
22pub struct IsString<'a>(pub(super) &'a SchemaType<'a>);
23
24impl Validator for IsString<'_> {
25 fn is_valid(&self) -> Result<(), &'static str> {
26 if self.0.is_string() {
27 Ok(())
28 } else {
29 Err("can only be used with `string` type")
30 }
31 }
32}
33
34pub struct IsInteger<'a>(&'a SchemaType<'a>);
35
36impl Validator for IsInteger<'_> {
37 fn is_valid(&self) -> Result<(), &'static str> {
38 if self.0.is_integer() {
39 Ok(())
40 } else {
41 Err("can only be used with `integer` type")
42 }
43 }
44}
45
46pub struct IsVec<'a>(pub(super) &'a TypeTree<'a>);
47
48impl Validator for IsVec<'_> {
49 fn is_valid(&self) -> Result<(), &'static str> {
50 if self.0.generic_type == Some(GenericType::Vec) {
51 Ok(())
52 } else {
53 Err("can only be used with `Vec`, `array` or `slice` types")
54 }
55 }
56}
57
58pub struct AboveZeroUsize<'a>(pub(super) &'a NumberValue);
59
60impl Validator for AboveZeroUsize<'_> {
61 fn is_valid(&self) -> Result<(), &'static str> {
62 let usize: usize = self
63 .0
64 .try_from_str()
65 .map_err(|_| "invalid type, expected `usize`")?;
66
67 if usize != 0 {
68 Ok(())
69 } else {
70 Err("can only be above zero value")
71 }
72 }
73}
74
75pub struct AboveZeroF64<'a>(pub(super) &'a NumberValue);
76
77impl Validator for AboveZeroF64<'_> {
78 fn is_valid(&self) -> Result<(), &'static str> {
79 let float: f64 = self
80 .0
81 .try_from_str()
82 .map_err(|_| "invalid type, expected `f64`")?;
83 if float > 0.0 {
84 Ok(())
85 } else {
86 Err("can only be above zero value")
87 }
88 }
89}
90
91pub struct ValidatorChain<'c> {
92 inner: &'c dyn Validator,
93 next: Option<&'c dyn Validator>,
94}
95
96impl Validator for ValidatorChain<'_> {
97 fn is_valid(&self) -> Result<(), &'static str> {
98 self.inner.is_valid().and_then(|_| {
99 if let Some(validator) = self.next.as_ref() {
100 validator.is_valid()
101 } else {
102 Ok(())
104 }
105 })
106 }
107}
108
109impl<'c> ValidatorChain<'c> {
110 pub fn new(validator: &'c dyn Validator) -> Self {
111 Self {
112 inner: validator,
113 next: None,
114 }
115 }
116
117 pub fn next(mut self, validator: &'c dyn Validator) -> Self {
118 self.next = Some(validator);
119
120 self
121 }
122}