avocado_schema/core/field/
integer.rs

1use crate::core::constraint::common::typed::Type;
2use crate::core::constraint::number::enumeration::Enumeration;
3use crate::core::constraint::number::exclusive_maximum::ExclusiveMaximum;
4use crate::core::constraint::number::exclusive_minimum::ExclusiveMinimum;
5use crate::core::constraint::number::maximum::Maximum;
6use crate::core::constraint::number::minimum::Minimum;
7use crate::core::constraint::Constraint;
8use crate::core::field::{Field, FieldType};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Serialize, Deserialize)]
12#[serde(tag = "type", rename = "integer")]
13pub struct IntegerField {
14    pub name: String,
15    #[serde(rename = "enum", skip_serializing_if = "Option::is_none")]
16    pub enumeration: Option<Vec<i64>>,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub maximum: Option<i64>,
19    #[serde(rename = "exclusiveMaximum", skip_serializing_if = "Option::is_none")]
20    pub exclusive_maximum: Option<i64>,
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub minimum: Option<i64>,
23    #[serde(rename = "exclusiveMinimum", skip_serializing_if = "Option::is_none")]
24    pub exclusive_minimum: Option<i64>,
25}
26
27impl Field for IntegerField {
28    const FIELD_TYPE: FieldType = FieldType::Integer;
29
30    fn name(&self) -> String {
31        self.name.clone()
32    }
33
34    fn constrains(&self) -> Vec<Box<dyn Constraint>> {
35        let mut constraints: Vec<Box<dyn Constraint>> = vec![Box::new(Type {
36            typed: Self::FIELD_TYPE,
37        })];
38        if let Some(c) = &self.enumeration {
39            constraints.push(Box::new(Enumeration { values: c.clone() }))
40        }
41        if let Some(c) = &self.maximum {
42            constraints.push(Box::new(Maximum { max_val: *c }))
43        }
44        if let Some(c) = &self.exclusive_maximum {
45            constraints.push(Box::new(ExclusiveMaximum { max_val: *c }))
46        }
47        if let Some(c) = &self.minimum {
48            constraints.push(Box::new(Minimum { min_val: *c }))
49        }
50        if let Some(c) = &self.exclusive_minimum {
51            constraints.push(Box::new(ExclusiveMinimum { min_val: *c }))
52        }
53        constraints
54    }
55}
56
57#[derive(Default)]
58pub struct IntegerFieldBuilder {
59    name: String,
60    enumeration: Option<Vec<i64>>,
61    maximum: Option<i64>,
62    exclusive_maximum: Option<i64>,
63    minimum: Option<i64>,
64    exclusive_minimum: Option<i64>,
65}
66
67impl IntegerFieldBuilder {
68    pub fn new() -> Self {
69        IntegerFieldBuilder::default()
70    }
71
72    pub fn name(mut self, name: &'static str) -> Self {
73        self.name = name.to_string();
74        self
75    }
76
77    pub fn enumeration(mut self, numbers: Vec<i64>) -> Self {
78        self.enumeration = Some(numbers);
79        self
80    }
81
82    pub fn maximum(mut self, max: i64) -> Self {
83        self.maximum = Some(max);
84        self
85    }
86
87    pub fn exclusive_maximum(mut self, max: i64) -> Self {
88        self.exclusive_maximum = Some(max);
89        self
90    }
91
92    pub fn minimum(mut self, min: i64) -> Self {
93        self.minimum = Some(min);
94        self
95    }
96
97    pub fn exclusive_minimum(mut self, min: i64) -> Self {
98        self.exclusive_minimum = Some(min);
99        self
100    }
101
102    pub fn build(self) -> IntegerField {
103        IntegerField {
104            name: self.name,
105            enumeration: self.enumeration,
106            maximum: self.maximum,
107            exclusive_maximum: self.exclusive_maximum,
108            minimum: self.minimum,
109            exclusive_minimum: self.exclusive_minimum,
110        }
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use crate::core::field::integer::{IntegerField, IntegerFieldBuilder};
117    use crate::visitor::validator::Validator;
118
119    #[test]
120    fn test_serialize() {
121        let field = IntegerFieldBuilder::new()
122            .name("age")
123            .enumeration(vec![50, 100])
124            .maximum(100)
125            .exclusive_maximum(101)
126            .minimum(1)
127            .exclusive_minimum(0)
128            .build();
129        let field_json = serde_json::to_string(&field).unwrap();
130        assert_eq!(
131            field_json,
132            r#"{"type":"integer","name":"age","enum":[50,100],"maximum":100,"exclusiveMaximum":101,"minimum":1,"exclusiveMinimum":0}"#
133        );
134    }
135
136    #[test]
137    fn test_deserialize() {
138        let field_json = r#"
139        {
140            "type":"integer",
141            "name": "age",
142            "enum": [50, 100],
143            "maximum": 100,
144            "exclusiveMaximum": 101,
145            "minimum": 1,
146            "exclusiveMinimum": 0
147        }"#;
148        let field: IntegerField = serde_json::from_str(field_json).unwrap();
149        assert_eq!(field.name, "age");
150        assert_eq!(field.enumeration.unwrap(), vec![50, 100]);
151        assert_eq!(field.maximum.unwrap(), 100);
152        assert_eq!(field.exclusive_maximum.unwrap(), 101);
153        assert_eq!(field.minimum.unwrap(), 1);
154        assert_eq!(field.exclusive_minimum.unwrap(), 0);
155    }
156
157    #[test]
158    fn test_type() {
159        let field = IntegerFieldBuilder::new().build();
160        let validator = Validator::new(field);
161
162        assert!(validator.validate(&10).is_ok());
163        assert!(validator.validate(&"meeting").is_err());
164    }
165
166    #[test]
167    fn test_enumeration() {
168        let field = IntegerFieldBuilder::new()
169            .enumeration(vec![50, 100])
170            .build();
171        let validator = Validator::new(field);
172
173        assert!(validator.validate(&50).is_ok());
174        assert!(validator.validate(&30).is_err());
175    }
176
177    #[test]
178    fn test_maximum() {
179        let field = IntegerFieldBuilder::new().maximum(100).build();
180        let validator = Validator::new(field);
181
182        assert!(validator.validate(&99).is_ok());
183        assert!(validator.validate(&100).is_ok());
184        assert!(validator.validate(&101).is_err());
185    }
186
187    #[test]
188    fn test_exclusive_maximum() {
189        let field = IntegerFieldBuilder::new().exclusive_maximum(100).build();
190        let validator = Validator::new(field);
191
192        assert!(validator.validate(&99).is_ok());
193        assert!(validator.validate(&100).is_err());
194        assert!(validator.validate(&101).is_err());
195    }
196
197    #[test]
198    fn test_minimum() {
199        let field = IntegerFieldBuilder::new().minimum(1).build();
200        let validator = Validator::new(field);
201
202        assert!(validator.validate(&2).is_ok());
203        assert!(validator.validate(&1).is_ok());
204        assert!(validator.validate(&0).is_err())
205    }
206
207    #[test]
208    fn test_exclusive_minimum() {
209        let field = IntegerFieldBuilder::new().exclusive_minimum(1).build();
210        let validator = Validator::new(field);
211
212        assert!(validator.validate(&2).is_ok());
213        assert!(validator.validate(&1).is_err());
214        assert!(validator.validate(&0).is_err())
215    }
216}