about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSimon Mazur <semmaz.box@gmail.com>2015-09-24 02:03:47 +0300
committerSimon Mazur <semmaz.box@gmail.com>2015-09-29 15:24:04 +0300
commit24b5d3afd75a6cdbaca1dc488d43b90f159108cb (patch)
treee69f8b7a786f7129690606def441cabadb8b9a89
parent5ca60d94316bd56f412ef4c13292237e206babf1 (diff)
downloadrust-24b5d3afd75a6cdbaca1dc488d43b90f159108cb.tar.gz
rust-24b5d3afd75a6cdbaca1dc488d43b90f159108cb.zip
Improve speed of `fmt::Debug` for `str` and `char`
fixes #26920
-rw-r--r--src/libcore/char.rs10
-rw-r--r--src/libcore/fmt/mod.rs22
2 files changed, 25 insertions, 7 deletions
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index dfcbfd476bc..a697c8c320e 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<u32>;
     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<usize>;
@@ -195,6 +196,15 @@ impl CharExt for char {
     }
 
     #[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;
         if code < MAX_ONE_B {
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index db7e6d3006f..cbcb3026a8e 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('\'')
     }
 }