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_ascii_digit()) {
90 s.push('_');
91 }
92 s.push_str(&format!("{num}"));
93 }
94}
95
96impl Default for NameFixer {
97 fn default() -> Self {
98 Self::new()
99 }
100}
101
102pub trait NameTransformer {
104 fn to_camelcase(&self) -> String;
112
113 fn to_underscore_lowercase(&self) -> String;
122
123 fn to_underscore_uppercase(&self) -> String;
132}
133
134impl NameTransformer for str {
135 fn to_camelcase(&self) -> String {
136 let mut upper = true;
137 let result: String = self.chars().filter_map(|c| {
138 if c == '_' {
139 upper = true;
140 None
141 } else if upper {
142 upper = false;
143 Some(c.to_ascii_uppercase())
144 } else {
145 Some(c.to_ascii_lowercase())
146 }
147 }).collect();
148 assert!(!result.is_empty());
149 result
150 }
151
152 fn to_underscore_lowercase(&self) -> String {
153 let mut result = String::new();
154 for c in self.chars() {
155 if !result.is_empty() && c.is_ascii_uppercase() {
156 result.push('_');
157 }
158 result.push(c.to_ascii_lowercase());
159 }
160 result
161 }
162
163 fn to_underscore_uppercase(&self) -> String {
164 let mut result = String::new();
165 for c in self.chars() {
166 if !result.is_empty() && c.is_ascii_uppercase() {
167 result.push('_');
168 }
169 result.push(c.to_ascii_uppercase());
170 }
171 result
172 }
173}
174
175#[cfg(test)]
176mod tests {
177 use super::*;
178
179 #[test]
180 fn test_name_fixer() {
181 let mut fixer = NameFixer::new();
182 assert_eq!(fixer.get_unique_name("a".to_string()), "a");
183 assert_eq!(fixer.get_unique_name("a".to_string()), "a1");
184 assert_eq!(fixer.get_unique_name("b".to_string()), "b");
185 assert_eq!(fixer.get_unique_name("a".to_string()), "a2");
186 assert_eq!(fixer.get_unique_name("U2".to_string()), "U2");
187 assert_eq!(fixer.get_unique_name("U2".to_string()), "U2_1");
188 }
189
190 #[test]
191 fn test_name_fixer_num() {
192 let mut fixer = NameFixer::new();
193 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a1");
194 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a2");
195 assert_eq!(fixer.get_unique_name_num("b".to_string()), "b1");
196 assert_eq!(fixer.get_unique_name_num("a".to_string()), "a3");
197 assert_eq!(fixer.get_unique_name_num("U2".to_string()), "U2_1");
198 assert_eq!(fixer.get_unique_name_num("U2".to_string()), "U2_2");
199 }
200
201 #[test]
202 fn test_name_fixer_under_num() {
203 let mut fixer = NameFixer::new();
204 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_1");
205 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_2");
206 assert_eq!(fixer.get_unique_name_unum("b".to_string()), "b_1");
207 assert_eq!(fixer.get_unique_name_unum("a".to_string()), "a_3");
208 assert_eq!(fixer.get_unique_name_unum("U2".to_string()), "U2_1");
209 assert_eq!(fixer.get_unique_name_unum("U2".to_string()), "U2_2");
210 }
211
212 #[test]
213 fn test_to_camel_case() {
214 let tests = vec![
215 ("A", "A"),
216 ("AA", "Aa"),
217 ("AB1", "Ab1"),
218 ("A_1", "A1"),
219 ("NUM_VAL", "NumVal"),
220 ("a", "A"),
221 ("ab_cd_ef", "AbCdEf"),
222 ];
223 for (str, expected) in tests {
224 let result = str.to_string().to_camelcase();
225 assert_eq!(result, expected);
226 }
227 }
228
229 #[test]
230 fn test_to_underscore() {
231 let tests = vec![
232 ("a", "a", "A"),
233 ("AA", "a_a", "A_A"),
234 ("A1", "a1", "A1"),
235 ("aB1", "a_b1", "A_B1"),
236 ("A", "a", "A"),
237 ("AbCdEf", "ab_cd_ef", "AB_CD_EF"),
238 ("ANewTest", "a_new_test", "A_NEW_TEST"),
239 ];
240 for (str, expected_lower, expected_upper) in tests {
241 let result_lower = str.to_string().to_underscore_lowercase();
242 let result_upper = str.to_string().to_underscore_uppercase();
243 assert_eq!(result_lower, expected_lower);
244 assert_eq!(result_upper, expected_upper);
245 }
246 }
247}