karbon_framework/validation/constraints/number/
numeric.rs1use crate::validation::constraints::{Constraint, ConstraintResult, ConstraintViolation};
2
3pub struct Numeric {
5 pub message: String,
6 pub allow_float: bool,
7}
8
9impl Default for Numeric {
10 fn default() -> Self {
11 Self {
12 message: "This value should be a valid number.".to_string(),
13 allow_float: true,
14 }
15 }
16}
17
18impl Numeric {
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 pub fn integer_only() -> Self {
25 Self {
26 allow_float: false,
27 ..Self::default()
28 }
29 }
30
31 pub fn with_message(mut self, message: impl Into<String>) -> Self {
32 self.message = message.into();
33 self
34 }
35}
36
37impl Constraint for Numeric {
38 fn validate(&self, value: &str) -> ConstraintResult {
39 let valid = if self.allow_float {
40 value.parse::<f64>().is_ok()
41 } else {
42 value.parse::<i64>().is_ok()
43 };
44
45 if !valid {
46 return Err(ConstraintViolation::new(
47 self.name(),
48 &self.message,
49 value,
50 ));
51 }
52 Ok(())
53 }
54
55 fn name(&self) -> &'static str {
56 "Numeric"
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 #[test]
65 fn test_valid_numbers() {
66 let constraint = Numeric::new();
67 assert!(constraint.validate("42").is_ok());
68 assert!(constraint.validate("-10").is_ok());
69 assert!(constraint.validate("3.14").is_ok());
70 assert!(constraint.validate("0").is_ok());
71 assert!(constraint.validate("-0.5").is_ok());
72 }
73
74 #[test]
75 fn test_invalid_numbers() {
76 let constraint = Numeric::new();
77 assert!(constraint.validate("").is_err());
78 assert!(constraint.validate("abc").is_err());
79 assert!(constraint.validate("12abc").is_err());
80 assert!(constraint.validate("12.34.56").is_err());
81 }
82
83 #[test]
84 fn test_integer_only() {
85 let constraint = Numeric::integer_only();
86 assert!(constraint.validate("42").is_ok());
87 assert!(constraint.validate("-10").is_ok());
88 assert!(constraint.validate("3.14").is_err());
89 assert!(constraint.validate("0.5").is_err());
90 }
91}