about summary refs log tree commit diff
path: root/src/libstd/rt/util.rs
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/libstd/rt/util.rs
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/libstd/rt/util.rs')
-rw-r--r--src/libstd/rt/util.rs18
1 files changed, 12 insertions, 6 deletions
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index fee86e33455..fa7c305d69e 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -96,8 +96,8 @@ pub const Stdout: Stdio = Stdio(libc::STDOUT_FILENO);
 #[allow(non_upper_case_globals)]
 pub const Stderr: Stdio = Stdio(libc::STDERR_FILENO);
 
-impl fmt::FormatWriter for Stdio {
-    fn write(&mut self, data: &[u8]) -> fmt::Result {
+impl Stdio {
+    pub fn write_bytes(&mut self, data: &[u8]) {
         #[cfg(unix)]
         type WriteLen = libc::size_t;
         #[cfg(windows)]
@@ -108,6 +108,12 @@ impl fmt::FormatWriter for Stdio {
                         data.as_ptr() as *const libc::c_void,
                         data.len() as WriteLen);
         }
+    }
+}
+
+impl fmt::Writer for Stdio {
+    fn write_str(&mut self, data: &str) -> fmt::Result {
+        self.write_bytes(data.as_bytes());
         Ok(()) // yes, we're lying
     }
 }
@@ -117,16 +123,16 @@ pub fn dumb_print(args: fmt::Arguments) {
 }
 
 pub fn abort(args: fmt::Arguments) -> ! {
-    use fmt::FormatWriter;
+    use fmt::Writer;
 
     struct BufWriter<'a> {
         buf: &'a mut [u8],
         pos: uint,
     }
-    impl<'a> FormatWriter for BufWriter<'a> {
-        fn write(&mut self, bytes: &[u8]) -> fmt::Result {
+    impl<'a> fmt::Writer for BufWriter<'a> {
+        fn write_str(&mut self, bytes: &str) -> fmt::Result {
             let left = self.buf.slice_from_mut(self.pos);
-            let to_write = bytes[..cmp::min(bytes.len(), left.len())];
+            let to_write = bytes.as_bytes()[..cmp::min(bytes.len(), left.len())];
             slice::bytes::copy_memory(left, to_write);
             self.pos += to_write.len();
             Ok(())