@@ -68,6 +68,16 @@ pub fn camel_case_until(s: &str) -> StrIndex {
68
68
/// ```
69
69
#[ must_use]
70
70
pub fn camel_case_start ( s : & str ) -> StrIndex {
71
+ camel_case_start_from_idx ( s, 0 )
72
+ }
73
+
74
+ /// Returns `StrIndex` of the last camel-case component of `s[idx..]`.
75
+ ///
76
+ /// ```
77
+ /// assert_eq!(camel_case_start("AbcDef", 0), StrIndex::new(0, 0));
78
+ /// assert_eq!(camel_case_start("AbcDef", 1), StrIndex::new(3, 3));
79
+ /// ```
80
+ pub fn camel_case_start_from_idx ( s : & str , start_idx : usize ) -> StrIndex {
71
81
let char_count = s. chars ( ) . count ( ) ;
72
82
let range = 0 ..char_count;
73
83
let mut iter = range. rev ( ) . zip ( s. char_indices ( ) . rev ( ) ) ;
@@ -78,9 +88,13 @@ pub fn camel_case_start(s: &str) -> StrIndex {
78
88
} else {
79
89
return StrIndex :: new ( char_count, s. len ( ) ) ;
80
90
}
91
+
81
92
let mut down = true ;
82
93
let mut last_index = StrIndex :: new ( char_count, s. len ( ) ) ;
83
94
for ( char_index, ( byte_index, c) ) in iter {
95
+ if byte_index < start_idx {
96
+ continue ;
97
+ }
84
98
if down {
85
99
if c. is_uppercase ( ) {
86
100
down = false ;
@@ -98,9 +112,51 @@ pub fn camel_case_start(s: &str) -> StrIndex {
98
112
return last_index;
99
113
}
100
114
}
115
+
101
116
last_index
102
117
}
103
118
119
+ /// Get the indexes of camel case components of a string `s`
120
+ ///
121
+ /// ```
122
+ /// assert_eq!(camel_case_indexes("AbcDef"), vec![StrIndex::new(0, 0), StrIndex::new(3, 3)])
123
+ /// ```
124
+ pub fn camel_case_indexes ( s : & str ) -> Vec < StrIndex > {
125
+ let mut result = Vec :: new ( ) ;
126
+ let mut str_idx = camel_case_start ( s) ;
127
+
128
+ while str_idx. byte_index < s. len ( ) {
129
+ let next_idx = str_idx. byte_index + 1 ;
130
+ result. push ( str_idx) ;
131
+ str_idx = camel_case_start_from_idx ( s, next_idx) ;
132
+ }
133
+ result. push ( str_idx) ;
134
+
135
+ result
136
+ }
137
+
138
+ /// Split camel case string into a vector of its components
139
+ ///
140
+ /// ```
141
+ /// assert_eq!(camel_case_split("AbcDef"), vec!["Abc", "Def"]);
142
+ /// ```
143
+ pub fn camel_case_split ( s : & str ) -> Vec < & str > {
144
+ let offsets = camel_case_indexes ( s) ;
145
+ let mut idxs_iter = offsets. iter ( ) . map ( |str_idx| str_idx. byte_index ) . peekable ( ) ;
146
+ let idxs: Vec < usize > = if let Some ( & idx) = idxs_iter. peek ( ) {
147
+ if idx == 0 {
148
+ idxs_iter. collect ( )
149
+ } else {
150
+ Vec :: < usize > :: from ( [ 0 ] ) . into_iter ( ) . chain ( idxs_iter) . collect ( )
151
+ }
152
+ } else {
153
+ return vec ! [ s] ;
154
+ } ;
155
+ let split_points: Vec < ( & usize , & usize ) > = idxs[ ..idxs. len ( ) - 1 ] . iter ( ) . zip ( & idxs[ 1 ..] ) . collect ( ) ;
156
+
157
+ split_points. iter ( ) . map ( |( & start, & stop) | & s[ start..stop] ) . collect ( )
158
+ }
159
+
104
160
/// Dealing with sting comparison can be complicated, this struct ensures that both the
105
161
/// character and byte count are provided for correct indexing.
106
162
#[ derive( Debug , Default , PartialEq , Eq ) ]
@@ -231,4 +287,29 @@ mod test {
231
287
fn until_caps ( ) {
232
288
assert_eq ! ( camel_case_until( "ABCD" ) , StrIndex :: new( 0 , 0 ) ) ;
233
289
}
290
+
291
+ #[ test]
292
+ fn camel_case_indexes_full ( ) {
293
+ assert_eq ! (
294
+ camel_case_indexes( "AbcDef" ) ,
295
+ vec![ StrIndex :: new( 0 , 0 ) , StrIndex :: new( 3 , 3 ) ]
296
+ ) ;
297
+ assert_eq ! (
298
+ camel_case_indexes( "abcDef" ) ,
299
+ vec![ StrIndex :: new( 0 , 0 ) , StrIndex :: new( 3 , 3 ) ]
300
+ ) ;
301
+ assert_eq ! ( camel_case_indexes( "Abc\u{f6} \u{f6} DD" ) , vec![ StrIndex :: new( 5 , 7 ) ] ) ;
302
+ }
303
+
304
+ #[ test]
305
+ fn camel_case_split_full ( ) {
306
+ assert_eq ! ( camel_case_split( "A" ) , vec![ "A" ] ) ;
307
+ assert_eq ! ( camel_case_split( "AbcDef" ) , vec![ "Abc" , "Def" ] ) ;
308
+ assert_eq ! ( camel_case_split( "Abc" ) , vec![ "Abc" ] ) ;
309
+ assert_eq ! ( camel_case_split( "abcDef" ) , vec![ "abc" , "Def" ] ) ;
310
+ assert_eq ! (
311
+ camel_case_split( "\u{f6} \u{f6} AabABcd" ) ,
312
+ vec![ "\u{f6} \u{f6} " , "Aab" , "A" , "Bcd" ]
313
+ ) ;
314
+ }
234
315
}
0 commit comments