Maintain/Build/
Pascalize.rs

1//=============================================================================//
2// File Path: Element/Maintain/Source/Build/Pascalize.rs
3//=============================================================================//
4// Module: Pascalize
5//
6// Brief Description: Converts kebab-case and snake_case strings to PascalCase.
7//
8// RESPONSIBILITIES:
9// ================
10//
11// Primary:
12// - Convert kebab-case strings to PascalCase
13// - Convert snake_case strings to PascalCase
14// - Handle delimiter-separated strings of any length
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// - Product name generation logic
34// - Bundle identifier generation logic
35//
36// IMPLEMENTATION DETAILS:
37// =======================
38//
39// Design Patterns:
40// - String transformation pattern
41// - Functional pattern
42//
43// Performance Considerations:
44// - Complexity: O(n) - where n is the length of the input string
45// - Memory usage patterns: Creates new String with allocated capacity
46// - Hot path optimizations: None needed
47//
48// Thread Safety:
49// - Thread-safe: Yes (pure function with immutable input and output)
50// - Synchronization mechanisms used: None
51// - Interior mutability considerations: None
52//
53// Error Handling:
54// - Error types returned: None
55// - Recovery strategies: Not applicable
56//
57// EXAMPLES:
58// =========
59//
60// Example 1: Kebab-case conversion
61/// ```rust
62/// use crate::Maintain::Source::Build::Pascalize;
63/// let result = Pascalize("development");
64/// assert_eq!(result, "Development");
65/// ```
66//
67// Example 2: Snake_case conversion
68/// ```rust
69/// use crate::Maintain::Source::Build::Pascalize;
70/// let result = Pascalize("node_environment");
71/// assert_eq!(result, "NodeEnvironment");
72/// ```
73//
74// Example 3: Mixed delimiters
75/// ```rust
76/// use crate::Maintain::Source::Build::Pascalize;
77/// let result = Pascalize("tauri-apps_tauri");
78/// assert_eq!(result, "TauriAppsTauri");
79/// ```
80//
81//=============================================================================//
82// IMPLEMENTATION
83//=============================================================================//
84
85/// Converts a kebab-case or snake_case string to `PascalCase`.
86///
87/// This function processes strings separated by hyphens (`-`) or underscores (`_`)
88/// and converts them to PascalCase by capitalizing the first letter of each word.
89/// The function handles strings with single or multiple delimiters and filters
90/// out empty segments.
91///
92/// # Parameters
93///
94/// * `Text` - The input string to convert (kebab-case or snake_case)
95///
96/// # Returns
97///
98/// A new String in PascalCase format.
99///
100/// # Behavior
101///
102/// - Splits the input on both hyphen (`-`) and underscore (`_`) characters
103/// - Filters out empty segments (from consecutive delimiters)
104/// - Capitalizes the first character of each segment
105/// - Preserves the case of remaining characters
106/// - Joins all segments together without delimiters
107///
108/// # Examples
109///
110/// ```
111/// use crate::Maintain::Source::Build::Pascalize;
112/// assert_eq!(Pascalize("development"), "Development");
113/// assert_eq!(Pascalize("node_environment"), "NodeEnvironment");
114/// assert_eq!(Pascalize("tauri-apps"), "TauriApps");
115/// assert_eq!(Pascalize("my-app_name"), "MyAppName");
116/// ```
117///
118/// # Edge Cases
119///
120/// - Empty string returns an empty string
121/// - Strings with only delimiters return an empty string
122/// - Single word strings are capitalized
123/// - Words already in PascalCase are not modified (no delimiter detection)
124pub fn Pascalize(Text: &str) -> String {
125    Text
126        .split(|c: char| c == '-' || c == '_')
127        .filter(|s| !s.is_empty())
128        .map(|s| {
129            let mut c = s.chars();
130
131            c.next()
132                .map_or(String::new(), |f| f.to_uppercase().collect::<String>() + c.as_str())
133        })
134        .collect()
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140
141    #[test]
142    fn test_kebab_case() {
143        assert_eq!(Pascalize("development"), "Development");
144        assert_eq!(Pascalize("node-version"), "NodeVersion");
145        assert_eq!(Pascalize("tauri-apps"), "TauriApps");
146    }
147
148    #[test]
149    fn test_snake_case() {
150        assert_eq!(Pascalize("node_environment"), "NodeEnvironment");
151        assert_eq!(Pascalize("my_variable_name"), "MyVariableName");
152    }
153
154    #[test]
155    fn test_mixed_delimiters() {
156        assert_eq!(Pascalize("tauri-apps_tauri"), "TauriAppsTauri");
157        assert_eq!(Pascalize("my-app_name"), "MyAppName");
158    }
159
160    #[test]
161    fn test_empty_string() {
162        assert_eq!(Pascalize(""), "");
163    }
164
165    #[test]
166    fn test_only_delimiters() {
167        assert_eq!(Pascalize("---"), "");
168        assert_eq!(Pascalize("___"), "");
169        assert_eq!(Pascalize("-_-"), "");
170    }
171
172    #[test]
173    fn test_single_word() {
174        assert_eq!(Pascalize("hello"), "Hello");
175        assert_eq!(Pascalize("WORLD"), "WORLD");
176    }
177}