Skip to content

Commit 347da74

Browse files
committed
Avoid allocation in ast::String::value if the string needs no unescaping
1 parent fc0354b commit 347da74

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

crates/syntax/src/ast/token_ext.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -130,19 +130,28 @@ impl ast::String {
130130
let text = self.text().as_str();
131131
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
132132

133-
let mut buf = String::with_capacity(text.len());
133+
let mut buf = String::new();
134+
let mut text_iter = text.chars();
134135
let mut has_error = false;
135-
unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char {
136-
Ok(c) => buf.push(c),
137-
Err(_) => has_error = true,
136+
unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
137+
unescaped_char,
138+
buf.capacity() == 0,
139+
) {
140+
(Ok(c), false) => buf.push(c),
141+
(Ok(c), true) if Some(c) == text_iter.next() => (),
142+
(Ok(c), true) => {
143+
buf.reserve_exact(text.len());
144+
buf.push_str(&text[..char_range.start]);
145+
buf.push(c);
146+
}
147+
(Err(_), _) => has_error = true,
138148
});
139149

140-
if has_error {
141-
return None;
150+
match (has_error, buf.capacity() == 0) {
151+
(true, _) => None,
152+
(false, true) => Some(Cow::Borrowed(text)),
153+
(false, false) => Some(Cow::Owned(buf)),
142154
}
143-
// FIXME: don't actually allocate for borrowed case
144-
let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) };
145-
Some(res)
146155
}
147156

148157
pub fn quote_offsets(&self) -> Option<QuoteOffsets> {

0 commit comments

Comments
 (0)