ic_dbms_api/validate/
strlen.rs

1use ic_dbms_api::prelude::{IcDbmsError, Value};
2
3use crate::prelude::Validate;
4
5/// A validator that checks if the length of a string does not exceed a maximum length.
6///
7/// # Example
8///
9/// ```rust
10/// use ic_dbms_api::prelude::{MaxStrlenValidator, Validate, Value, Text};
11/// let validator = MaxStrlenValidator(10);
12/// let value = Value::Text(Text("Hello".to_string()));
13/// assert!(validator.validate(&value).is_ok());
14/// let long_value = Value::Text(Text("Hello, World!".to_string()));
15/// assert!(validator.validate(&long_value).is_err());
16/// ```
17pub struct MaxStrlenValidator(pub usize);
18
19impl Validate for MaxStrlenValidator {
20    fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
21        let Value::Text(text) = value else {
22            return Err(IcDbmsError::Validation("Value is not a `Text`".to_string()));
23        };
24
25        let s = &text.0;
26
27        if s.len() <= self.0 {
28            Ok(())
29        } else {
30            Err(IcDbmsError::Validation(format!(
31                "String length {} exceeds maximum allowed length of {}",
32                s.len(),
33                self.0
34            )))
35        }
36    }
37}
38
39/// A validator that checks if the length of a string is at least a minimum length.
40///
41/// # Example
42/// ```rust
43/// use ic_dbms_api::prelude::{MinStrlenValidator, Validate, Value, Text};
44/// let validator = MinStrlenValidator(5);
45/// let value = Value::Text(Text("Hello".to_string()));
46/// assert!(validator.validate(&value).is_ok());
47/// let short_value = Value::Text(Text("Hi".to_string()));
48/// assert!(validator.validate(&short_value).is_err());
49/// ```
50pub struct MinStrlenValidator(pub usize);
51
52impl Validate for MinStrlenValidator {
53    fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
54        let Value::Text(text) = value else {
55            return Err(IcDbmsError::Validation("Value is not a `Text`".to_string()));
56        };
57
58        let s = &text.0;
59
60        if s.len() >= self.0 {
61            Ok(())
62        } else {
63            Err(IcDbmsError::Validation(format!(
64                "String length {} is less than minimum required length of {}",
65                s.len(),
66                self.0
67            )))
68        }
69    }
70}
71
72/// A validator that checks if the length of a string is within a specified range.
73///
74/// # Example
75///
76/// ```rust
77/// use ic_dbms_api::prelude::{RangeStrlenValidator, Validate, Value, Text};
78/// let validator = RangeStrlenValidator(3, 10);
79/// let value = Value::Text(Text("Hello".to_string()));
80/// assert!(validator.validate(&value).is_ok());
81/// let short_value = Value::Text(Text("Hi".to_string()));
82/// assert!(validator.validate(&short_value).is_err());
83/// let long_value = Value::Text(Text("Hello, World!".to_string()));
84/// assert!(validator.validate(&long_value).is_err());
85/// ```
86pub struct RangeStrlenValidator(pub usize, pub usize);
87
88impl Validate for RangeStrlenValidator {
89    fn validate(&self, value: &Value) -> ic_dbms_api::prelude::IcDbmsResult<()> {
90        let Value::Text(text) = value else {
91            return Err(IcDbmsError::Validation("Value is not a `Text`".to_string()));
92        };
93
94        let s = &text.0;
95        let len = s.len();
96
97        if len >= self.0 && len <= self.1 {
98            Ok(())
99        } else {
100            Err(IcDbmsError::Validation(format!(
101                "String length {} is not within the allowed range of {} to {}",
102                len, self.0, self.1
103            )))
104        }
105    }
106}
107
108#[cfg(test)]
109mod tests {
110
111    use ic_dbms_api::prelude::Text;
112
113    use super::*;
114
115    #[test]
116    fn test_max_strlen_validator() {
117        let validator = MaxStrlenValidator(5);
118
119        let valid_value = Value::Text(Text("Hello".to_string()));
120        let invalid_value = Value::Text(Text("Hello, World!".to_string()));
121
122        assert!(validator.validate(&valid_value).is_ok());
123        assert!(validator.validate(&invalid_value).is_err());
124    }
125
126    #[test]
127    fn test_max_strlen_validator_non_text() {
128        let validator = MaxStrlenValidator(5);
129        let non_text_value = Value::Uint32(crate::prelude::Uint32(42));
130        assert!(validator.validate(&non_text_value).is_err());
131    }
132
133    #[test]
134    fn test_min_strlen_validator() {
135        let validator = MinStrlenValidator(5);
136        let valid_value = Value::Text(Text("Hello".to_string()));
137        let invalid_value = Value::Text(Text("Hi".to_string()));
138        assert!(validator.validate(&valid_value).is_ok());
139        assert!(validator.validate(&invalid_value).is_err());
140    }
141
142    #[test]
143    fn test_min_strlen_validator_non_text() {
144        let validator = MinStrlenValidator(5);
145        let non_text_value = Value::Uint32(crate::prelude::Uint32(42));
146        assert!(validator.validate(&non_text_value).is_err());
147    }
148
149    #[test]
150    fn test_range_strlen_validator() {
151        let validator = RangeStrlenValidator(3, 10);
152        let valid_value = Value::Text(Text("Hello".to_string()));
153        let too_short_value = Value::Text(Text("Hi".to_string()));
154        let too_long_value = Value::Text(Text("Hello, World!".to_string()));
155        assert!(validator.validate(&valid_value).is_ok());
156        assert!(validator.validate(&too_short_value).is_err());
157        assert!(validator.validate(&too_long_value).is_err());
158    }
159
160    #[test]
161    fn test_range_strlen_validator_non_text() {
162        let validator = RangeStrlenValidator(3, 10);
163        let non_text_value = Value::Uint32(crate::prelude::Uint32(42));
164        assert!(validator.validate(&non_text_value).is_err());
165    }
166}