1use std::time::Duration;
4
5pub fn parse_duration(s: &str) -> Option<Duration> {
16 let s = s.trim();
17 if let Some(num) = s.strip_suffix("ms") {
18 num.parse::<u64>().ok().map(Duration::from_millis)
19 } else if let Some(num) = s.strip_suffix('s') {
20 num.parse::<u64>().ok().map(Duration::from_secs)
21 } else if let Some(num) = s.strip_suffix('m') {
22 num.parse::<u64>().ok().map(|m| Duration::from_secs(m * 60))
23 } else if let Some(num) = s.strip_suffix('h') {
24 num.parse::<u64>()
25 .ok()
26 .map(|h| Duration::from_secs(h * 3600))
27 } else if let Some(num) = s.strip_suffix('d') {
28 num.parse::<u64>()
29 .ok()
30 .map(|d| Duration::from_secs(d * 86400))
31 } else {
32 s.parse::<u64>().ok().map(Duration::from_secs)
33 }
34}
35
36pub fn to_pascal_case(s: &str) -> String {
38 s.split('_')
39 .map(|part| {
40 let mut chars = part.chars();
41 match chars.next() {
42 None => String::new(),
43 Some(first) => first.to_uppercase().chain(chars).collect(),
44 }
45 })
46 .collect()
47}
48
49pub fn to_snake_case(s: &str) -> String {
51 let mut result = String::new();
52 for (i, c) in s.chars().enumerate() {
53 if c.is_uppercase() {
54 if i > 0 {
55 result.push('_');
56 }
57 result.extend(c.to_lowercase());
58 } else {
59 result.push(c);
60 }
61 }
62 result
63}
64
65pub fn to_camel_case(s: &str) -> String {
67 let mut result = String::new();
68 let mut capitalize_next = false;
69 for c in s.chars() {
70 if c == '_' {
71 capitalize_next = true;
72 } else if capitalize_next {
73 result.extend(c.to_uppercase());
74 capitalize_next = false;
75 } else {
76 result.push(c);
77 }
78 }
79 result
80}
81
82#[cfg(test)]
83#[allow(clippy::unwrap_used, clippy::indexing_slicing)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test_parse_duration_milliseconds() {
89 assert_eq!(parse_duration("100ms"), Some(Duration::from_millis(100)));
90 assert_eq!(parse_duration("1000ms"), Some(Duration::from_millis(1000)));
91 }
92
93 #[test]
94 fn test_parse_duration_seconds() {
95 assert_eq!(parse_duration("30s"), Some(Duration::from_secs(30)));
96 assert_eq!(parse_duration("60s"), Some(Duration::from_secs(60)));
97 }
98
99 #[test]
100 fn test_parse_duration_minutes() {
101 assert_eq!(parse_duration("5m"), Some(Duration::from_secs(300)));
102 assert_eq!(parse_duration("10m"), Some(Duration::from_secs(600)));
103 }
104
105 #[test]
106 fn test_parse_duration_hours() {
107 assert_eq!(parse_duration("1h"), Some(Duration::from_secs(3600)));
108 assert_eq!(parse_duration("24h"), Some(Duration::from_secs(86400)));
109 }
110
111 #[test]
112 fn test_parse_duration_days() {
113 assert_eq!(parse_duration("1d"), Some(Duration::from_secs(86400)));
114 assert_eq!(parse_duration("7d"), Some(Duration::from_secs(604800)));
115 }
116
117 #[test]
118 fn test_parse_duration_bare_number() {
119 assert_eq!(parse_duration("60"), Some(Duration::from_secs(60)));
120 assert_eq!(parse_duration("3600"), Some(Duration::from_secs(3600)));
121 }
122
123 #[test]
124 fn test_parse_duration_whitespace() {
125 assert_eq!(parse_duration(" 30s "), Some(Duration::from_secs(30)));
126 }
127
128 #[test]
129 fn test_parse_duration_invalid() {
130 assert_eq!(parse_duration("invalid"), None);
131 assert_eq!(parse_duration("abc123"), None);
132 assert_eq!(parse_duration(""), None);
133 }
134
135 #[test]
136 fn test_to_snake_case() {
137 assert_eq!(to_snake_case("GetUser"), "get_user");
138 assert_eq!(to_snake_case("ListAllProjects"), "list_all_projects");
139 assert_eq!(to_snake_case("Simple"), "simple");
140 assert_eq!(to_snake_case("ProjectStatus"), "project_status");
141 }
142
143 #[test]
144 fn test_to_pascal_case() {
145 assert_eq!(to_pascal_case("get_user"), "GetUser");
146 assert_eq!(to_pascal_case("list_all_projects"), "ListAllProjects");
147 assert_eq!(to_pascal_case("simple"), "Simple");
148 }
149
150 #[test]
151 fn test_to_camel_case() {
152 assert_eq!(to_camel_case("get_user"), "getUser");
153 assert_eq!(to_camel_case("list_all_projects"), "listAllProjects");
154 assert_eq!(to_camel_case("simple"), "simple");
155 }
156}