Skip to content

Commit 178a351

Browse files
authored
Fix big performance issue in string serialization (#1848)
1 parent 6120bb5 commit 178a351

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/ast/value.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -456,30 +456,38 @@ impl fmt::Display for EscapeQuotedString<'_> {
456456
// | `"A\"B\"A"` | default | `DoubleQuotedString(String::from("A\"B\"A"))` | `"A""B""A"` |
457457
let quote = self.quote;
458458
let mut previous_char = char::default();
459-
let mut peekable_chars = self.string.chars().peekable();
460-
while let Some(&ch) = peekable_chars.peek() {
459+
let mut start_idx = 0;
460+
let mut peekable_chars = self.string.char_indices().peekable();
461+
while let Some(&(idx, ch)) = peekable_chars.peek() {
461462
match ch {
462463
char if char == quote => {
463464
if previous_char == '\\' {
464-
write!(f, "{char}")?;
465+
// the quote is already escaped with a backslash, skip
465466
peekable_chars.next();
466467
continue;
467468
}
468469
peekable_chars.next();
469-
if peekable_chars.peek().map(|c| *c == quote).unwrap_or(false) {
470-
write!(f, "{char}{char}")?;
471-
peekable_chars.next();
472-
} else {
473-
write!(f, "{char}{char}")?;
470+
match peekable_chars.peek() {
471+
Some((_, c)) if *c == quote => {
472+
// the quote is already escaped with another quote, skip
473+
peekable_chars.next();
474+
}
475+
_ => {
476+
// The quote is not escaped.
477+
// Including idx in the range, so the quote at idx will be printed twice:
478+
// in this call to write_str() and in the next one.
479+
f.write_str(&self.string[start_idx..=idx])?;
480+
start_idx = idx;
481+
}
474482
}
475483
}
476484
_ => {
477-
write!(f, "{ch}")?;
478485
peekable_chars.next();
479486
}
480487
}
481488
previous_char = ch;
482489
}
490+
f.write_str(&self.string[start_idx..])?;
483491
Ok(())
484492
}
485493
}

0 commit comments

Comments
 (0)