this/core/validation/
validators.rs1use serde_json::Value;
6
7pub fn required() -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
9 |field: &str, value: &Value| {
10 if value.is_null() {
11 Err(format!("Le champ '{}' est requis", field))
12 } else {
13 Ok(())
14 }
15 }
16}
17
18pub fn optional() -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
20 |_: &str, _: &Value| Ok(())
21}
22
23pub fn positive() -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
25 |field: &str, value: &Value| {
26 if let Some(num) = value.as_f64() {
27 if num <= 0.0 {
28 Err(format!(
29 "Le champ '{}' doit être positif (valeur: {})",
30 field, num
31 ))
32 } else {
33 Ok(())
34 }
35 } else {
36 Ok(()) }
38 }
39}
40
41pub fn string_length(
43 min: usize,
44 max: usize,
45) -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
46 move |field: &str, value: &Value| {
47 if let Some(s) = value.as_str() {
48 let len = s.len();
49 if len < min {
50 Err(format!(
51 "'{}' doit avoir au moins {} caractères (actuellement: {})",
52 field, min, len
53 ))
54 } else if len > max {
55 Err(format!(
56 "'{}' ne doit pas dépasser {} caractères (actuellement: {})",
57 field, max, len
58 ))
59 } else {
60 Ok(())
61 }
62 } else {
63 Ok(())
64 }
65 }
66}
67
68pub fn max_value(max: f64) -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
70 move |field: &str, value: &Value| {
71 if let Some(num) = value.as_f64() {
72 if num > max {
73 Err(format!(
74 "'{}' ne doit pas dépasser {} (valeur: {})",
75 field, max, num
76 ))
77 } else {
78 Ok(())
79 }
80 } else {
81 Ok(())
82 }
83 }
84}
85
86pub fn in_list(
88 allowed: Vec<String>,
89) -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
90 move |field: &str, value: &Value| {
91 if let Some(s) = value.as_str() {
92 if !allowed.contains(&s.to_string()) {
93 Err(format!(
94 "'{}' doit être l'une des valeurs: {:?} (valeur actuelle: {})",
95 field, allowed, s
96 ))
97 } else {
98 Ok(())
99 }
100 } else {
101 Ok(())
102 }
103 }
104}
105
106pub fn date_format(
108 format: &'static str,
109) -> impl Fn(&str, &Value) -> Result<(), String> + Send + Sync + Clone {
110 move |field: &str, value: &Value| {
111 if let Some(s) = value.as_str() {
112 match chrono::NaiveDate::parse_from_str(s, format) {
113 Ok(_) => Ok(()),
114 Err(_) => Err(format!(
115 "'{}' doit être au format {} (valeur actuelle: {})",
116 field, format, s
117 )),
118 }
119 } else {
120 Ok(())
121 }
122 }
123}