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