data_protocol_validator/
format.rs1use regex::Regex;
2
3pub fn validate_format(value: &str, format: &str) -> bool {
9 match format {
10 "date" => validate_date(value),
11 "date-time" => validate_datetime(value),
12 "email" => validate_email(value),
13 "uri" => validate_uri(value),
14 "uuid" => validate_uuid(value),
15 _ => true, }
17}
18
19fn validate_date(value: &str) -> bool {
20 let re = Regex::new(r"^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$").unwrap();
21 if !re.is_match(value) {
22 return false;
23 }
24 chrono::NaiveDate::parse_from_str(value, "%Y-%m-%d").is_ok()
26}
27
28fn validate_datetime(value: &str) -> bool {
29 let re = Regex::new(
30 r"^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$"
31 ).unwrap();
32 if !re.is_match(value) {
33 return false;
34 }
35 use chrono::{DateTime, FixedOffset};
37 DateTime::<FixedOffset>::parse_from_rfc3339(value).is_ok()
38 || chrono::NaiveDateTime::parse_from_str(value, "%Y-%m-%dT%H:%M:%S%.fZ").is_ok()
39}
40
41fn validate_email(value: &str) -> bool {
42 let re = Regex::new(r"^[^\s@]+@[^\s@]+\.[^\s@]+$").unwrap();
43 re.is_match(value)
44}
45
46fn validate_uri(value: &str) -> bool {
47 let re = Regex::new(r"^[a-zA-Z][a-zA-Z0-9+\-.]*://[^\s]+$").unwrap();
48 re.is_match(value)
49}
50
51fn validate_uuid(value: &str) -> bool {
52 let re =
53 Regex::new(r"(?i)^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$").unwrap();
54 re.is_match(value)
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_date_valid() {
63 assert!(validate_format("2024-01-15", "date"));
64 }
65
66 #[test]
67 fn test_date_invalid_month() {
68 assert!(!validate_format("2024-13-01", "date"));
69 }
70
71 #[test]
72 fn test_datetime_valid() {
73 assert!(validate_format("2024-01-15T10:30:00Z", "date-time"));
74 }
75
76 #[test]
77 fn test_datetime_with_offset() {
78 assert!(validate_format("2024-01-15T10:30:00+09:00", "date-time"));
79 }
80
81 #[test]
82 fn test_email_valid() {
83 assert!(validate_format("user@example.com", "email"));
84 }
85
86 #[test]
87 fn test_email_invalid() {
88 assert!(!validate_format("not-an-email", "email"));
89 }
90
91 #[test]
92 fn test_uri_valid() {
93 assert!(validate_format("https://example.com/path", "uri"));
94 }
95
96 #[test]
97 fn test_uuid_valid() {
98 assert!(validate_format(
99 "550e8400-e29b-41d4-a716-446655440000",
100 "uuid"
101 ));
102 }
103
104 #[test]
105 fn test_unknown_format_passes() {
106 assert!(validate_format("anything", "unknown-format"));
107 }
108}