From 24b5d3afd75a6cdbaca1dc488d43b90f159108cb Mon Sep 17 00:00:00 2001 From: Simon Mazur Date: Thu, 24 Sep 2015 02:03:47 +0300 Subject: [PATCH] Improve speed of `fmt::Debug` for `str` and `char` fixes #26920 --- src/libcore/char.rs | 10 ++++++++++ src/libcore/fmt/mod.rs | 22 +++++++++++++++------- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index dfcbfd476bc3..a697c8c320e3 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -147,6 +147,7 @@ pub trait CharExt { fn to_digit(self, radix: u32) -> Option; fn escape_unicode(self) -> EscapeUnicode; fn escape_default(self) -> EscapeDefault; + fn needs_escape_default(self) -> bool; fn len_utf8(self) -> usize; fn len_utf16(self) -> usize; fn encode_utf8(self, dst: &mut [u8]) -> Option; @@ -194,6 +195,15 @@ impl CharExt for char { EscapeDefault { state: init_state } } + #[inline] + fn needs_escape_default(self) -> bool { + match self { + '\\' | '\'' | '"' => true, + '\x20' ... '\x7e' => false, + _ => true + } + } + #[inline] fn len_utf8(self) -> usize { let code = self as u32; diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index db7e6d3006f3..cbcb3026a8e4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1310,11 +1310,20 @@ impl Display for bool { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for str { fn fmt(&self, f: &mut Formatter) -> Result { - try!(write!(f, "\"")); - for c in self.chars().flat_map(|c| c.escape_default()) { - try!(f.write_char(c)) + try!(f.write_char('"')); + let mut from = 0; + for (i, c) in self.char_indices() { + // If char needs escaping, flush backlog so far and write, else skip + if c.needs_escape_default() { + try!(f.write_str(&self[from..i])); + for e in c.escape_default() { + try!(f.write_char(e)); + } + from = i + c.len_utf8(); + } } - write!(f, "\"") + try!(f.write_str(&self[from..])); + f.write_char('"') } } @@ -1328,12 +1337,11 @@ impl Display for str { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for char { fn fmt(&self, f: &mut Formatter) -> Result { - use char::CharExt; - try!(write!(f, "'")); + try!(f.write_char('\'')); for c in self.escape_default() { try!(f.write_char(c)) } - write!(f, "'") + f.write_char('\'') } }