morphir_projection/
naming.rs1pub fn upper_camel(source: &str) -> String {
15 let words = words(source);
16 let result = words
17 .iter()
18 .map(|word| {
19 let mut chars = word.chars();
20 chars
21 .next()
22 .map(|first| first.to_uppercase().chain(chars).collect::<String>())
23 .unwrap_or_default()
24 })
25 .collect::<String>();
26 valid_identifier(result)
27}
28
29pub fn lower_camel(source: &str) -> String {
32 let upper = upper_camel(source);
33 let mut chars = upper.chars();
34 chars
35 .next()
36 .map(|first| first.to_lowercase().chain(chars).collect::<String>())
37 .unwrap_or_else(|| "_".to_owned())
38}
39
40fn words(source: &str) -> Vec<String> {
41 let mut words = Vec::new();
42 let mut current = String::new();
43 let mut previous_was_lowercase_or_digit = false;
44 for character in source.chars() {
45 if !character.is_ascii_alphanumeric() {
46 if !current.is_empty() {
47 words.push(std::mem::take(&mut current));
48 }
49 previous_was_lowercase_or_digit = false;
50 continue;
51 }
52 if character.is_ascii_uppercase() && previous_was_lowercase_or_digit && !current.is_empty()
53 {
54 words.push(std::mem::take(&mut current));
55 }
56 previous_was_lowercase_or_digit =
57 character.is_ascii_lowercase() || character.is_ascii_digit();
58 current.push(character.to_ascii_lowercase());
59 }
60 if !current.is_empty() {
61 words.push(current);
62 }
63 words
64}
65
66fn valid_identifier(mut value: String) -> String {
67 if value.is_empty() {
68 value.push('_');
69 }
70 if value.as_bytes()[0].is_ascii_digit() {
71 value.insert(0, '_');
72 }
73 value
74}