6648: Avoid allocation in ast::String::value if the string needs no unescaping r=lnicola a=Veykril



Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2020-11-27 11:14:14 +00:00 committed by GitHub
commit c66d477f5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -130,19 +130,28 @@ impl ast::String {
let text = self.text().as_str();
let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()];
let mut buf = String::with_capacity(text.len());
let mut buf = String::new();
let mut text_iter = text.chars();
let mut has_error = false;
unescape_literal(text, Mode::Str, &mut |_, unescaped_char| match unescaped_char {
Ok(c) => buf.push(c),
Err(_) => has_error = true,
unescape_literal(text, Mode::Str, &mut |char_range, unescaped_char| match (
unescaped_char,
buf.capacity() == 0,
) {
(Ok(c), false) => buf.push(c),
(Ok(c), true) if Some(c) == text_iter.next() => (),
(Ok(c), true) => {
buf.reserve_exact(text.len());
buf.push_str(&text[..char_range.start]);
buf.push(c);
}
(Err(_), _) => has_error = true,
});
if has_error {
return None;
match (has_error, buf.capacity() == 0) {
(true, _) => None,
(false, true) => Some(Cow::Borrowed(text)),
(false, false) => Some(Cow::Owned(buf)),
}
// FIXME: don't actually allocate for borrowed case
let res = if buf == text { Cow::Borrowed(text) } else { Cow::Owned(buf) };
Some(res)
}
pub fn quote_offsets(&self) -> Option<QuoteOffsets> {