rocketmq_common/utils/
string_utils.rs1use std::collections::BTreeMap;
18use std::collections::HashMap;
19
20use cheetah_string::CheetahString;
21
22pub struct StringUtils;
23
24impl StringUtils {
25 #[inline]
26 pub fn is_not_empty_str(s: Option<&str>) -> bool {
27 s.is_some_and(|s| !s.is_empty())
28 }
29
30 #[inline]
31 pub fn is_not_empty_string(s: Option<&String>) -> bool {
32 s.is_some_and(|s| !s.is_empty())
33 }
34
35 #[inline]
36 pub fn is_not_empty_ch_string(s: Option<&CheetahString>) -> bool {
37 s.is_some_and(|s| !s.is_empty())
38 }
39
40 pub fn parse_delay_level(level_string: &str) -> Result<(BTreeMap<i32, i64>, i32), String> {
41 let time_unit_table = HashMap::from([
42 ('s', 1000),
43 ('m', 1000 * 60),
44 ('h', 1000 * 60 * 60),
45 ('d', 1000 * 60 * 60 * 24),
46 ]);
47
48 let mut delay_level_table = BTreeMap::new();
49
50 let level_array: Vec<&str> = level_string.split(' ').collect();
51 let mut max_delay_level = 0;
52
53 for (i, value) in level_array.iter().enumerate() {
54 let ch = match value.chars().last() {
56 None => {
57 return Err("Empty time unit".to_string());
58 }
59 Some(value) => value,
60 };
61 let tu = *time_unit_table
62 .get(&ch)
63 .ok_or(format!("Unknown time unit: {ch}"))?;
64
65 let level = i as i32 + 1;
66 if level > max_delay_level {
67 max_delay_level = level;
68 }
69
70 let num_str = &value[0..value.len() - 1];
71 let num = num_str.parse::<i64>().map_err(|e| e.to_string())?;
72 let delay_time_millis = tu * num;
73 delay_level_table.insert(level, delay_time_millis);
74 }
75
76 Ok((delay_level_table, max_delay_level))
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::StringUtils;
83
84 #[test]
85 fn is_not_empty_str_with_some_non_empty_str() {
86 assert!(StringUtils::is_not_empty_str(Some("hello")));
87 }
88
89 #[test]
90 fn is_not_empty_str_with_some_empty_str() {
91 assert!(!StringUtils::is_not_empty_str(Some("")));
92 }
93
94 #[test]
95 fn is_not_empty_str_with_none() {
96 assert!(!StringUtils::is_not_empty_str(None));
97 }
98
99 #[test]
100 fn is_not_empty_string_with_some_non_empty_string() {
101 assert!(StringUtils::is_not_empty_string(Some(&"hello".to_string())));
102 }
103
104 #[test]
105 fn is_not_empty_string_with_some_empty_string() {
106 assert!(!StringUtils::is_not_empty_string(Some(&"".to_string())));
107 }
108
109 #[test]
110 fn is_not_empty_string_with_none() {
111 assert!(!StringUtils::is_not_empty_string(None));
112 }
113
114 #[test]
115 fn parse_delay_level_with_valid_input() {
116 let result = StringUtils::parse_delay_level("1s 2m 3h 4d").unwrap();
117 let (delay_level_table, max_delay_level) = result;
118 assert_eq!(delay_level_table[&1], 1000);
119 assert_eq!(delay_level_table[&2], 2 * 60 * 1000);
120 assert_eq!(delay_level_table[&3], 3 * 60 * 60 * 1000);
121 assert_eq!(delay_level_table[&4], 4 * 24 * 60 * 60 * 1000);
122 assert_eq!(max_delay_level, 4);
123 }
124
125 #[test]
126 fn parse_delay_level_with_unknown_time_unit() {
127 let result = StringUtils::parse_delay_level("1x");
128 assert!(result.is_err());
129 assert_eq!(result.err().unwrap(), "Unknown time unit: x");
130 }
131
132 #[test]
133 fn parse_delay_level_with_invalid_number() {
134 let result = StringUtils::parse_delay_level("1s 2m 3h 4d 5z");
135 assert!(result.is_err());
136 assert_eq!(result.err().unwrap(), "Unknown time unit: z");
137 }
138
139 #[test]
140 fn parse_delay_level_with_empty_string() {
141 let result = StringUtils::parse_delay_level("");
142 assert!(result.is_err());
143 }
144}