about summary refs log tree commit diff
path: root/src/libcollections
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-12-12 10:59:41 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-01-01 22:04:46 -0800
commite423fcf0e0166da55f88233e0be5eacba55bc0bc (patch)
tree0c4a4ffadfa870dcf23e1d55b224a1d7c2805f2a /src/libcollections
parentcd614164e692cca3a1460737f581fcb6d4630baf (diff)
downloadrust-e423fcf0e0166da55f88233e0be5eacba55bc0bc.tar.gz
rust-e423fcf0e0166da55f88233e0be5eacba55bc0bc.zip
std: Enforce Unicode in fmt::Writer
This commit is an implementation of [RFC 526][rfc] which is a change to alter
the definition of the old `fmt::FormatWriter`. The new trait, renamed to
`Writer`, now only exposes one method `write_str` in order to guarantee that all
implementations of the formatting traits can only produce valid Unicode.

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0526-fmt-text-writer.md

One of the primary improvements of this patch is the performance of the
`.to_string()` method by avoiding an almost-always redundant UTF-8 check. This
is a breaking change due to the renaming of the trait as well as the loss of the
`write` method, but migration paths should be relatively easy:

* All usage of `write` should move to `write_str`. If truly binary data was
  being written in an implementation of `Show`, then it will need to use a
  different trait or an altogether different code path.

* All usage of `write!` should continue to work as-is with no modifications.

* All usage of `Show` where implementations just delegate to another should
  continue to work as-is.

[breaking-change]

Closes #20352
Diffstat (limited to 'src/libcollections')
-rw-r--r--src/libcollections/string.rs15
-rw-r--r--src/libcollections/vec.rs6
2 files changed, 15 insertions, 6 deletions
diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs
index 37a6e690f5d..74b698361f2 100644
--- a/src/libcollections/string.rs
+++ b/src/libcollections/string.rs
@@ -995,9 +995,11 @@ pub trait ToString {
 
 impl<T: fmt::Show> ToString for T {
     fn to_string(&self) -> String {
-        let mut buf = Vec::<u8>::new();
-        let _ = fmt::write(&mut buf, format_args!("{}", *self));
-        String::from_utf8(buf).unwrap()
+        use core::fmt::Writer;
+        let mut buf = String::new();
+        let _ = buf.write_fmt(format_args!("{}", self));
+        buf.shrink_to_fit();
+        buf
     }
 }
 
@@ -1073,6 +1075,13 @@ impl<'a> Str for CowString<'a> {
     }
 }
 
+impl fmt::Writer for String {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.push_str(s);
+        Ok(())
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::*;
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index a1952352bad..a83e35a945d 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1488,9 +1488,9 @@ impl<T:fmt::Show> fmt::Show for Vec<T> {
     }
 }
 
-impl<'a> fmt::FormatWriter for Vec<u8> {
-    fn write(&mut self, buf: &[u8]) -> fmt::Result {
-        self.push_all(buf);
+impl<'a> fmt::Writer for Vec<u8> {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        self.push_all(s.as_bytes());
         Ok(())
     }
 }