Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c76e2d1

Browse files
committed
Add str_util helpers to split camelcase strings
1 parent d58fdfb commit c76e2d1

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

clippy_utils/src/str_utils.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ pub fn camel_case_until(s: &str) -> StrIndex {
6868
/// ```
6969
#[must_use]
7070
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 {
7181
let char_count = s.chars().count();
7282
let range = 0..char_count;
7383
let mut iter = range.rev().zip(s.char_indices().rev());
@@ -78,9 +88,13 @@ pub fn camel_case_start(s: &str) -> StrIndex {
7888
} else {
7989
return StrIndex::new(char_count, s.len());
8090
}
91+
8192
let mut down = true;
8293
let mut last_index = StrIndex::new(char_count, s.len());
8394
for (char_index, (byte_index, c)) in iter {
95+
if byte_index < start_idx {
96+
continue;
97+
}
8498
if down {
8599
if c.is_uppercase() {
86100
down = false;
@@ -98,9 +112,51 @@ pub fn camel_case_start(s: &str) -> StrIndex {
98112
return last_index;
99113
}
100114
}
115+
101116
last_index
102117
}
103118

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+
104160
/// Dealing with sting comparison can be complicated, this struct ensures that both the
105161
/// character and byte count are provided for correct indexing.
106162
#[derive(Debug, Default, PartialEq, Eq)]
@@ -231,4 +287,29 @@ mod test {
231287
fn until_caps() {
232288
assert_eq!(camel_case_until("ABCD"), StrIndex::new(0, 0));
233289
}
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+
}
234315
}

0 commit comments

Comments
 (0)