1use std::collections::HashSet;
4
5#[derive(Clone, Debug)]
7pub struct NameFixer {
8 dic: HashSet<String>
9}
10
11impl NameFixer {
12 const RUST_KEYWORDS: [&'static str; 51] = [
13 "as", "break", "const", "continue", "crate", "else", "enum", "extern", "false", "fn", "for", "if", "impl", "in",
14 "let", "loop", "match", "mod", "move", "mut", "pub", "ref", "return", "self", "Self", "static", "struct", "super",
15 "trait", "true", "type", "unsafe", "use", "where", "while", "async", "await", "dyn", "abstract", "become", "box",
16 "do", "final", "macro", "override", "priv", "typeof", "unsized", "virtual", "yield", "try"];
17
18 pub fn new() -> Self {
23 let mut dic = HashSet::<String>::new();
24 dic.extend(Self::RUST_KEYWORDS.iter().map(|s| s.to_string()));
25 NameFixer { dic }
26 }
27
28 pub fn new_empty() -> Self {
33 let dic = HashSet::<String>::new();
34 NameFixer { dic }
35 }
36
37 pub fn add(&mut self, name: String) {
40 self.dic.insert(name);
41 }
42
43 pub fn remove(&mut self, name: &str) -> bool {
45 self.dic.remove(name)
46 }
47
48 pub fn contains(&self, name: &str) -> bool {
50 self.dic.contains(name)
51 }
52
53 pub fn get_unique_name(&mut self, mut name: String) -> String {
55 let len = name.len();
56 let mut index = 0;
57 while self.dic.contains(&name) {
58 name.truncate(len);
59 index += 1;
60 Self::add_number(&mut name, index);
61 }
62 self.dic.insert(name.clone());
63 name
64 }
65
66 pub fn get_unique_name_num(&mut self, mut name: String) -> String {
68 let len = name.len();
69 let mut index = 1;
70 Self::add_number(&mut name, index);
71 while self.dic.contains(&name) {
72 name.truncate(len);
73 index += 1;
74 Self::add_number(&mut name, index);
75 }
76 self.dic.insert(name.clone());
77 name
78 }
79
80 pub fn get_unique_name_unum(&mut self, mut name: String) -> String {
82 name.push('_');
83 self.get_unique_name_num(name)
84 }
85
86 pub fn add_number(s: &mut String, num: usize) {
89 if s.ends_with(|c: char| c.is_digit(10)) {
90 s.push('_');
91 }
92 s.push_str(&format!("{num}"));
93 }
94}
95
96pub trait NameTransformer {
98 fn to_camelcase(&self) -> String;
106
107 fn to_underscore_lowercase(&self) -> String;
116
117 fn to_underscore_uppercase(&self) -> String;
126}
127
128impl NameTransformer for str {
129 fn to_camelcase(&self) -> String {
130 let mut upper = true;
131 let result: String = self.chars().filter_map(|c| {
132 if c == '_' {
133 upper = true;
134 None
135 } else {
136 if upper {
137 upper = false;
138 Some(c.to_ascii_uppercase())
139 } else {
140 Some(c.to_ascii_lowercase())
141 }
142 }
143 }).collect();
144 assert!(!result.is_empty());
145 result
146 }
147
148 fn to_underscore_lowercase(&self) -> String {
149 let mut result = String::new();
150 for c in self.chars() {
151 if !result.is_empty() && c.is_ascii_uppercase() {
152 result.push('_');
153 }
154 result.push(c.to_ascii_lowercase());
155 }
156 result
157 }
158
159 fn to_underscore_uppercase(&self) -> String {
160 let mut result = String::new();
161 for c in self.chars() {
162 if !result.is_empty() && c.is_ascii_uppercase() {
163 result.push('_');
164 }
165 result.push(c.to_ascii_uppercase());
166 }
167 result
168 }
169}
170
171#[cfg(test)]
172mod tests {
173 use super::*;
174
175 #[test]
176 fn test_name_fixer() {
177 let mut fixer = NameFixer::new();
178 assert_eq!(fixer.get_unique_name("a".to_string()), "a");
179 assert_eq!(fixer.get_unique_name("a".to_string()), "a1");
180 assert_eq!(fixer.get_unique_name("b".to_string()), "b");
181 assert_eq!(fixer.get_unique_name("a".to_string()), "a2");
182 assert_eq!(fixer.get_unique_name("U2".to_string()), "U2");
183 assert_eq!(fixer.get_unique_name("U2".to_string()), "U2_1");
184 }
185
186 #[test]
187 fn test_name_fixer_num() {
188 let mut fixer = NameFixer::new();
189 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a1");
190 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a2");
191 assert_eq!(fixer.get_unique_name_num("b".to_string()), "b1");
192 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a3");
193 assert_eq!(fixer.get_unique_name_num("U2".to_string()), "U2_1");
194 assert_eq!(fixer.get_unique_name_num("U2".to_string()), "U2_2");
195 }
196
197 #[test]
198 fn test_name_fixer_under_num() {
199 let mut fixer = NameFixer::new();
200 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_1");
201 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_2");
202 assert_eq!(fixer.get_unique_name_unum("b".to_string()), "b_1");
203 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_3");
204 assert_eq!(fixer.get_unique_name_unum("U2".to_string()), "U2_1");
205 assert_eq!(fixer.get_unique_name_unum("U2".to_string()), "U2_2");
206 }
207
208 #[test]
209 fn test_to_camel_case() {
210 let tests = vec![
211 ("A", "A"),
212 ("AA", "Aa"),
213 ("AB1", "Ab1"),
214 ("A_1", "A1"),
215 ("NUM_VAL", "NumVal"),
216 ("a", "A"),
217 ("ab_cd_ef", "AbCdEf"),
218 ];
219 for (str, expected) in tests {
220 let result = str.to_string().to_camelcase();
221 assert_eq!(result, expected);
222 }
223 }
224
225 #[test]
226 fn test_to_underscore() {
227 let tests = vec![
228 ("a", "a", "A"),
229 ("AA", "a_a", "A_A"),
230 ("A1", "a1", "A1"),
231 ("aB1", "a_b1", "A_B1"),
232 ("A", "a", "A"),
233 ("AbCdEf", "ab_cd_ef", "AB_CD_EF"),
234 ("ANewTest", "a_new_test", "A_NEW_TEST"),
235 ];
236 for (str, expected_lower, expected_upper) in tests {
237 let result_lower = str.to_string().to_underscore_lowercase();
238 let result_upper = str.to_string().to_underscore_uppercase();
239 assert_eq!(result_lower, expected_lower);
240 assert_eq!(result_upper, expected_upper);
241 }
242 }
243}