1use chrono::{DateTime, TimeZone, Utc};
16use convert_case::{Case, Casing};
17use time::OffsetDateTime;
18use uuid::Uuid;
19
20pub mod date {
21 use super::*;
22
23 pub fn now_utc() -> DateTime<Utc> {
26 Utc::now()
27 }
28
29 pub fn to_gmt_string(dt: DateTime<Utc>) -> String {
31 dt.format("%a, %d %b %Y %H:%M:%S GMT").to_string()
32 }
33}
34
35pub mod string {
36 use super::*;
37
38 pub trait StringExt {
39 fn to_camel_case(&self) -> String;
40 fn to_snake_case(&self) -> String;
41 fn to_kebab_case(&self) -> String;
42 fn mask(&self, keep_start: usize, keep_end: usize) -> String;
43 }
44
45 impl StringExt for String {
46 fn to_camel_case(&self) -> String {
47 self.to_case(Case::Camel)
48 }
49
50 fn to_snake_case(&self) -> String {
51 self.to_case(Case::Snake)
52 }
53
54 fn to_kebab_case(&self) -> String {
55 self.to_case(Case::Kebab)
56 }
57
58 fn mask(&self, keep_start: usize, keep_end: usize) -> String {
59 if self.len() <= keep_start + keep_end {
60 return self.clone();
61 }
62
63 let start = &self[..keep_start];
64 let end = &self[self.len() - keep_end..];
65 let masked_len = self.len() - keep_start - keep_end;
66 let mask_chars = "*".repeat(masked_len);
67
68 format!("{}{}{}", start, mask_chars, end)
69 }
70 }
71}
72
73pub fn generate_uuid() -> String {
75 Uuid::now_v7().to_string()
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use super::date::*;
82 use super::string::*;
83
84 #[test]
85 fn test_generate_uuid() {
86 let id1 = generate_uuid();
87 let id2 = generate_uuid();
88
89 assert_eq!(id1.len(), 36);
90 assert_ne!(id1, id2);
91 }
92
93 #[test]
94 fn test_date_utilities() {
95 let utc = now_utc();
96 let gmt_str = to_gmt_string(utc);
97 assert!(gmt_str.ends_with("GMT"));
98 }
99
100 #[test]
101 fn test_string_casing() {
102 let original = String::from("hello world test");
103 assert_eq!(original.to_camel_case(), "helloWorldTest");
104 assert_eq!(original.to_snake_case(), "hello_world_test");
105 assert_eq!(original.to_kebab_case(), "hello-world-test");
106 }
107
108 #[test]
109 fn test_string_masking() {
110 let email = String::from("admin@antigravity.com");
111 let masked = email.mask(3, 4); assert!(masked.starts_with("adm"));
114 assert!(masked.ends_with(".com"));
115 assert!(masked.contains("*"));
116 assert_eq!(masked.len(), email.len());
117
118 let short = String::from("a");
120 assert_eq!(short.mask(3, 4), "a");
121
122 let exact = String::from("abcdefg");
124 assert_eq!(exact.mask(3, 4), "abcdefg");
125 }
126}