diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 25309a785c45a..e1a388c38c453 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -12,7 +12,6 @@ use prelude::v1::*; use io::prelude::*; use cell::{RefCell, BorrowState}; -use cmp; use fmt; use io::lazy::Lazy; use io::{self, BufReader, LineWriter}; @@ -312,22 +311,6 @@ impl<'a> BufRead for StdinLock<'a> { fn consume(&mut self, n: usize) { self.inner.consume(n) } } -// As with stdin on windows, stdout often can't handle writes of large -// sizes. For an example, see #14940. For this reason, don't try to -// write the entire output buffer on windows. On unix we can just -// write the whole buffer all at once. -// -// For some other references, it appears that this problem has been -// encountered by others [1] [2]. We choose the number 8KB just because -// libuv does the same. -// -// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232 -// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html -#[cfg(windows)] -const OUT_MAX: usize = 8192; -#[cfg(unix)] -const OUT_MAX: usize = ::usize::MAX; - /// A handle to the global standard output stream of the current process. /// /// Each handle shares a global buffer of data to be written to the standard @@ -440,7 +423,7 @@ impl Write for Stdout { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for StdoutLock<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.borrow_mut().write(&buf[..cmp::min(buf.len(), OUT_MAX)]) + self.inner.borrow_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.borrow_mut().flush() @@ -546,7 +529,7 @@ impl Write for Stderr { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> Write for StderrLock<'a> { fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.borrow_mut().write(&buf[..cmp::min(buf.len(), OUT_MAX)]) + self.inner.borrow_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.borrow_mut().flush() diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index 5883904c21d72..0a0851ffac37a 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -13,6 +13,7 @@ use prelude::v1::*; use io::prelude::*; +use cmp; use io::{self, Cursor}; use ptr; use str; @@ -58,10 +59,24 @@ fn write(out: &Output, data: &[u8]) -> io::Result { Output::Console(ref c) => c.get().raw(), Output::Pipe(ref p) => return p.get().write(data), }; - let utf16 = match str::from_utf8(data).ok() { - Some(utf8) => utf8.encode_utf16().collect::>(), - None => return Err(invalid_encoding()), + // As with stdin on windows, stdout often can't handle writes of large + // sizes. For an example, see #14940. For this reason, don't try to + // write the entire output buffer on windows. + // + // For some other references, it appears that this problem has been + // encountered by others [1] [2]. We choose the number 8K just because + // libuv does the same. + // + // [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232 + // [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html + const OUT_MAX: usize = 8192; + let len = cmp::min(data.len(), OUT_MAX); + let utf8 = match str::from_utf8(&data[..len]) { + Ok(s) => s, + Err(ref e) if e.valid_up_to() == 0 => return Err(invalid_encoding()), + Err(e) => str::from_utf8(&data[..e.valid_up_to()]).unwrap(), }; + let utf16 = utf8.encode_utf16().collect::>(); let mut written = 0; try!(cvt(unsafe { c::WriteConsoleW(handle, @@ -74,7 +89,7 @@ fn write(out: &Output, data: &[u8]) -> io::Result { // FIXME if this only partially writes the utf16 buffer then we need to // figure out how many bytes of `data` were actually written assert_eq!(written as usize, utf16.len()); - Ok(data.len()) + Ok(utf8.len()) } impl Stdin {