Process a single not-ASCII-printable char per iteration

This avoids having to collect a non-ASCII-printable run before processing it.
This commit is contained in:
Arpad Borsos 2024-05-20 12:04:21 +02:00
parent aaba972e06
commit 004100c222
No known key found for this signature in database
GPG Key ID: FC7BCA77824B3298

View File

@ -2407,8 +2407,8 @@ fn needs_escape(b: u8) -> bool {
b > 0x7E || b < 0x20 || b == b'\\' || b == b'"'
}
// the outer loop here splits the string into chunks of printable ASCII, which is just skipped over,
// and chunks of other chars (unicode, or ASCII that needs escaping), which is handler per-`char`.
// the loop here first skips over runs of printable ASCII as a fast path.
// other chars (unicode, or ASCII that needs escaping) are then handled per-`char`.
let mut rest = self;
while rest.len() > 0 {
let Some(non_printable_start) = rest.as_bytes().iter().position(|&b| needs_escape(b))
@ -2421,12 +2421,8 @@ fn needs_escape(b: u8) -> bool {
// SAFETY: the position was derived from an iterator, so is known to be within bounds, and at a char boundary
rest = unsafe { rest.get_unchecked(non_printable_start..) };
let printable_start =
rest.as_bytes().iter().position(|&b| !needs_escape(b)).unwrap_or(rest.len());
let prefix;
(prefix, rest) = rest.split_at(printable_start);
for c in prefix.chars() {
let mut chars = rest.chars();
if let Some(c) = chars.next() {
let esc = c.escape_debug_ext(EscapeDebugExtArgs {
escape_grapheme_extended: true,
escape_single_quote: false,
@ -2439,6 +2435,7 @@ fn needs_escape(b: u8) -> bool {
}
printable_range.end += c.len_utf8();
}
rest = chars.as_str();
}
f.write_str(&self[printable_range])?;