utoipa_gen/component/features/
validators.rs

1use 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                // if there is no next validator consider it valid
103                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}