Maintain/Build/WordsFromPascal.rs
1//=============================================================================//
2// File Path: Element/Maintain/Source/Build/WordsFromPascal.rs
3//=============================================================================//
4// Module: WordsFromPascal
5//
6// Brief Description: Converts PascalCase strings into lowercase word vectors.
7//
8// RESPONSIBILITIES:
9// ================
10//
11// Primary:
12// - Convert PascalCase strings to lowercase word vectors
13// - Split PascalCase into constituent words
14// - Handle multi-letter uppercase sequences
15//
16// Secondary:
17// - None
18//
19// ARCHITECTURAL ROLE:
20// ===================
21//
22// Position:
23// - Infrastructure/Utility layer
24// - String transformation utilities
25//
26// Dependencies (What this module requires):
27// - External crates: None
28// - Internal modules: None
29// - Traits implemented: None
30//
31// Dependents (What depends on this module):
32// - Build orchestration functions
33// - Bundle identifier generation logic
34//
35// IMPLEMENTATION DETAILS:
36// =======================
37//
38// Design Patterns:
39// - String transformation pattern
40// - Functional pattern
41//
42// Performance Considerations:
43// - Complexity: O(n) - where n is the length of the input string
44// - Memory usage patterns: Creates new String for each word
45// - Hot path optimizations: None needed
46//
47// Thread Safety:
48// - Thread-safe: Yes (pure function with immutable input and output)
49// - Synchronization mechanisms used: None
50// - Interior mutability considerations: None
51//
52// Error Handling:
53// - Error types returned: None
54// - Recovery strategies: Not applicable
55//
56// EXAMPLES:
57// =========
58//
59// Example 1: Simple PascalCase
60/// ```rust
61/// use crate::Maintain::Source::Build::WordsFromPascal;
62/// let words = WordsFromPascal("Development");
63/// assert_eq!(words, vec!["development"]);
64/// ```
65// Example 2: Multi-word PascalCase
66/// ```rust
67/// use crate::Maintain::Source::Build::WordsFromPascal;
68/// let words = WordsFromPascal("NodeEnvironment");
69/// assert_eq!(words, vec!["node", "environment"]);
70/// ```
71// Example 3: Acronyms
72/// ```rust
73/// use crate::Maintain::Source::Build::WordsFromPascal;
74/// let words = WordsFromPascal("TauriAppsTauri");
75/// assert_eq!(words, vec!["tauri", "apps", "tauri"]);
76/// ```
77//
78//=============================================================================//
79// IMPLEMENTATION
80//=============================================================================//
81
82/// Converts a `PascalCase` string into a vector of its lowercase constituent
83/// words.
84///
85/// This function splits PascalCase strings into their individual words by
86/// detecting word boundaries where lowercase letters appear after uppercase
87/// letters. It handles common cases including:
88///
89/// - Simple words: `"Hello"` → `["hello"]`
90/// - Standard PascalCase: `"HelloWorld"` → `["hello", "world"]`
91/// - Multi-letter acronyms: `"TauriApps"` → `["tauri", "apps"]`
92///
93/// The algorithm tracks when transitions occur from lowercase to uppercase
94/// to determine word boundaries.
95///
96/// # Parameters
97///
98/// * `Text` - The PascalCase string to split
99///
100/// # Returns
101///
102/// A vector of lowercase strings representing the constituent words.
103///
104/// # Behavior
105///
106/// - Splits at boundaries where lowercase letters are followed by uppercase
107/// - Handles consecutive uppercase letters as part of the same word
108/// - Converts all words to lowercase
109/// - Returns an empty vector for empty strings
110///
111/// # Examples
112///
113/// ```
114/// use crate::Maintain::Source::Build::WordsFromPascal;
115/// assert_eq!(WordsFromPascal("Hello"), vec!["hello"]);
116/// assert_eq!(WordsFromPascal("HelloWorld"), vec!["hello", "world"]);
117/// assert_eq!(WordsFromPascal("NodeEnvironment"), vec!["node", "environment"]);
118/// assert_eq!(WordsFromPascal("TauriAppsTauri"), vec!["tauri", "apps", "tauri"]);
119/// assert_eq!(WordsFromPascal(""), Vec::<String>::new());
120/// ```
121///
122/// # Edge Cases
123///
124/// - Empty string returns an empty vector
125/// - Single character strings work correctly
126/// - Strings with all lowercase are treated as a single word
127/// - Strings with all uppercase are treated as a single word
128///
129/// # Algorithm
130///
131/// The function iterates through each character:
132/// 1. If the character is uppercase:
133/// - If we have accumulated lowercase characters, end the current word
134/// - Add the uppercase character to the current word
135/// - Track that we're processing uppercase characters
136/// 2. If the character is lowercase:
137/// - Add to the current word
138/// - Track that we're processing lowercase characters
139/// 3. After iteration, add the final word
140///
141/// This ensures that multi-letter sequences like "Apps" stay together while
142/// properly splitting "HelloWorld" into "hello" and "world".
143pub fn WordsFromPascal(Text:&str) -> Vec<String> {
144 if Text.is_empty() {
145 return Vec::new();
146 }
147
148 let mut Words = Vec::new();
149
150 let mut CurrentWord = String::new();
151
152 let mut LastCharWasUppercase = false;
153
154 for Char in Text.chars() {
155 if Char.is_uppercase() {
156 if !CurrentWord.is_empty() && !LastCharWasUppercase {
157 Words.push(CurrentWord.to_ascii_lowercase());
158
159 CurrentWord.clear();
160 }
161
162 CurrentWord.push(Char);
163
164 LastCharWasUppercase = true;
165 } else {
166 CurrentWord.push(Char);
167
168 LastCharWasUppercase = false;
169 }
170 }
171
172 if !CurrentWord.is_empty() {
173 Words.push(CurrentWord.to_ascii_lowercase());
174 }
175
176 Words
177}
178
179#[cfg(test)]
180mod tests {
181 use super::*;
182
183 #[test]
184 fn test_single_word() {
185 assert_eq!(WordsFromPascal("Hello"), vec!["hello"]);
186 assert_eq!(WordsFromPascal("World"), vec!["world"]);
187 }
188
189 #[test]
190 fn test_two_words() {
191 assert_eq!(WordsFromPascal("HelloWorld"), vec!["hello", "world"]);
192 assert_eq!(WordsFromPascal("NodeEnvironment"), vec!["node", "environment"]);
193 }
194
195 #[test]
196 fn test_multiple_words() {
197 assert_eq!(WordsFromPascal("TauriAppsTauri"), vec!["tauri", "apps", "tauri"]);
198 assert_eq!(WordsFromPascal("MyAwesomeAppName"), vec!["my", "awesome", "app", "name"]);
199 }
200
201 #[test]
202 fn test_empty_string() {
203 assert_eq!(WordsFromPascal(""), Vec::<String>::new());
204 }
205
206 #[test]
207 fn test_all_lowercase() {
208 assert_eq!(WordsFromPascal("hello"), vec!["hello"]);
209 }
210
211 #[test]
212 fn test_all_uppercase() {
213 assert_eq!(WordsFromPascal("HELLO"), vec!["hello"]);
214 }
215
216 #[test]
217 fn test_single_character() {
218 assert_eq!(WordsFromPascal("A"), vec!["a"]);
219 assert_eq!(WordsFromPascal("a"), vec!["a"]);
220 }
221}