Skip to content

Commit 4b90da4

Browse files
authored
perf: pre-allocate text change string capacity (#289)
1 parent 3aba071 commit 4b90da4

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

Cargo.lock

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ swc_visit = { version = "=0.6.2", optional = true }
7777
swc_visit_macros = { version = "=0.5.13", optional = true }
7878
# just for error handling
7979
sourcemap = { version = "9.0.0", optional = true }
80+
string_capacity = "0.1.4"
8081
thiserror = "2"
8182

8283
[dev-dependencies]

src/text_changes.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
use std::cmp::Ordering;
44
use std::ops::Range;
55

6+
use string_capacity::StringBuilder;
7+
68
#[derive(Clone, Debug)]
79
pub struct TextChange {
810
/// Range start to end byte index.
@@ -30,34 +32,32 @@ pub fn apply_text_changes(
3032
ordering => ordering,
3133
});
3234

33-
let mut last_index = 0;
34-
let mut final_text = String::new();
35-
36-
for (i, change) in changes.iter().enumerate() {
37-
if change.range.start > change.range.end {
38-
panic!(
39-
"Text change had start index {} greater than end index {}.\n\n{:?}",
40-
change.range.start,
41-
change.range.end,
42-
&changes[0..i + 1],
43-
)
44-
}
45-
if change.range.start < last_index {
46-
panic!("Text changes were overlapping. Past index was {}, but new change had index {}.\n\n{:?}", last_index, change.range.start, &changes[0..i + 1]);
47-
} else if change.range.start > last_index && last_index < source.len() {
48-
final_text.push_str(
49-
&source[last_index..std::cmp::min(source.len(), change.range.start)],
50-
);
35+
StringBuilder::build(|builder| {
36+
let mut last_index = 0;
37+
for (i, change) in changes.iter().enumerate() {
38+
if change.range.start > change.range.end {
39+
panic!(
40+
"Text change had start index {} greater than end index {}.\n\n{:?}",
41+
change.range.start,
42+
change.range.end,
43+
&changes[0..i + 1],
44+
)
45+
}
46+
if change.range.start < last_index {
47+
panic!("Text changes were overlapping. Past index was {}, but new change had index {}.\n\n{:?}", last_index, change.range.start, &changes[0..i + 1]);
48+
} else if change.range.start > last_index && last_index < source.len() {
49+
builder.append(
50+
&source[last_index..std::cmp::min(source.len(), change.range.start)],
51+
);
52+
}
53+
builder.append(&change.new_text);
54+
last_index = change.range.end;
5155
}
52-
final_text.push_str(&change.new_text);
53-
last_index = change.range.end;
54-
}
5556

56-
if last_index < source.len() {
57-
final_text.push_str(&source[last_index..]);
58-
}
59-
60-
final_text
57+
if last_index < source.len() {
58+
builder.append(&source[last_index..]);
59+
}
60+
}).unwrap()
6161
}
6262

6363
#[cfg(test)]

0 commit comments

Comments
 (0)