avocado_schema/core/field/
array.rs

1use crate::core::constraint::array::unique::Unique;
2use crate::core::constraint::common::typed::Type;
3use crate::core::constraint::Constraint;
4use crate::core::field::FieldEnum;
5use crate::core::field::{Field, FieldType};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Serialize, Deserialize)]
9#[serde(tag = "type", rename = "array")]
10pub struct ArrayField {
11    pub name: String,
12    pub item: Option<Box<FieldEnum>>,
13    pub unique: Option<bool>,
14}
15
16impl Field for ArrayField {
17    const FIELD_TYPE: FieldType = FieldType::Array;
18
19    fn name(&self) -> String {
20        self.name.clone()
21    }
22
23    fn constrains(&self) -> Vec<Box<dyn Constraint>> {
24        let mut constraints: Vec<Box<dyn Constraint>> = vec![Box::new(Type {
25            typed: Self::FIELD_TYPE,
26        })];
27        if let Some(c) = self.unique {
28            constraints.push(Box::new(Unique { unique: c }));
29        }
30        constraints
31    }
32}
33
34#[derive(Default)]
35pub struct ArrayFieldBuilder {
36    name: String,
37    item: Option<FieldEnum>,
38    unique: Option<bool>,
39}
40
41impl ArrayFieldBuilder {
42    pub fn new() -> ArrayFieldBuilder {
43        ArrayFieldBuilder::default()
44    }
45
46    pub fn name(mut self, name: &'static str) -> Self {
47        self.name = name.to_string();
48        self
49    }
50
51    pub fn item(mut self, item: impl Field) -> Self {
52        self.item = Some(item.into());
53        self
54    }
55
56    pub fn unique(mut self, unique: bool) -> Self {
57        self.unique = Some(unique);
58        self
59    }
60
61    pub fn build(self) -> ArrayField {
62        ArrayField {
63            name: self.name,
64            item: self.item.map(Box::new),
65            unique: self.unique,
66        }
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use crate::core::field::array::{ArrayField, ArrayFieldBuilder};
73    use crate::core::field::string::StringFieldBuilder;
74    use crate::core::field::FieldEnum;
75    use crate::visitor::validator::Validator;
76
77    #[test]
78    fn test_serialize() {
79        let field = ArrayFieldBuilder::new()
80            .name("tags")
81            .item(StringFieldBuilder::new().build())
82            .unique(true)
83            .build();
84        let field_json = serde_json::to_string(&field).unwrap();
85        assert_eq!(
86            field_json,
87            r#"{"type":"array","name":"tags","item":{"type":"string","name":""},"unique":true}"#
88        );
89    }
90
91    #[test]
92    fn test_deserialize() {
93        let field_json = r#"
94        {
95            "type":"array",
96            "name": "tags",
97            "item": {
98                "type":"string",
99                "name":"tag"
100            },
101            "unique": true
102        }"#;
103        let field: ArrayField = serde_json::from_str(field_json).unwrap();
104        assert!(matches!(*field.item.unwrap(), FieldEnum::String(_)));
105        assert!(field.unique.unwrap());
106    }
107
108    #[test]
109    fn test_type() {
110        let field = ArrayFieldBuilder::new().build();
111        let validator = Validator::new(field);
112
113        assert!(validator.validate(&vec![10, 20]).is_ok());
114        assert!(validator.validate(&"meeting").is_err());
115    }
116
117    #[test]
118    fn test_item() {
119        let field = ArrayFieldBuilder::new()
120            .item(StringFieldBuilder::new().build())
121            .build();
122        let validator = Validator::new(field);
123
124        assert!(validator.validate(&vec!["meeting", "email"]).is_ok());
125        assert!(validator.validate(&vec![1, 2]).is_err());
126    }
127
128    #[test]
129    fn test_unique() {
130        let field = ArrayFieldBuilder::new().unique(true).build();
131        let validator = Validator::new(field);
132
133        assert!(validator.validate(&vec![1, 2, 3]).is_ok());
134        assert!(validator.validate(&vec![1, 2, 2]).is_err());
135    }
136}