std: Funnel read_to_end through to one location

This pushes the implementation detail of proxying `read_to_end` through to
`read_to_end_uninitialized` all the way down to the `FileDesc` and `Handle`
implementations on Unix/Windows. This way intermediate layers will also be able
to take advantage of this optimized implementation.

This commit also adds the optimized implementation for `ChildStdout` and
`ChildStderr`.
This commit is contained in:
Alex Crichton 2016-02-12 00:17:24 -08:00
parent eabfc160f8
commit d46c99abe8
15 changed files with 136 additions and 11 deletions

View file

@ -22,7 +22,6 @@ use ffi::OsString;
use io::{self, SeekFrom, Seek, Read, Write}; use io::{self, SeekFrom, Seek, Read, Write};
use path::{Path, PathBuf}; use path::{Path, PathBuf};
use sys::fs as fs_imp; use sys::fs as fs_imp;
use sys_common::io::read_to_end_uninitialized;
use sys_common::{AsInnerMut, FromInner, AsInner, IntoInner}; use sys_common::{AsInnerMut, FromInner, AsInner, IntoInner};
use vec::Vec; use vec::Vec;
use time::SystemTime; use time::SystemTime;
@ -351,7 +350,7 @@ impl Read for File {
self.inner.read(buf) self.inner.read(buf)
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) } self.inner.read_to_end(buf)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -372,6 +371,9 @@ impl<'a> Read for &'a File {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf) self.inner.read(buf)
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for &'a File { impl<'a> Write for &'a File {

View file

@ -18,7 +18,6 @@ use io::lazy::Lazy;
use io::{self, BufReader, LineWriter}; use io::{self, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard}; use sync::{Arc, Mutex, MutexGuard};
use sys::stdio; use sys::stdio;
use sys_common::io::{read_to_end_uninitialized};
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard}; use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
use thread::LocalKeyState; use thread::LocalKeyState;
@ -78,6 +77,9 @@ fn stderr_raw() -> io::Result<StderrRaw> { stdio::Stderr::new().map(StderrRaw) }
impl Read for StdinRaw { impl Read for StdinRaw {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}
} }
impl Write for StdoutRaw { impl Write for StdoutRaw {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) } fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
@ -116,6 +118,12 @@ impl<R: io::Read> io::Read for Maybe<R> {
Maybe::Fake => Ok(0) Maybe::Fake => Ok(0)
} }
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
match *self {
Maybe::Real(ref mut r) => handle_ebadf(r.read_to_end(buf), 0),
Maybe::Fake => Ok(0)
}
}
} }
fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> { fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
@ -294,7 +302,7 @@ impl<'a> Read for StdinLock<'a> {
self.inner.read(buf) self.inner.read(buf)
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) } self.inner.read_to_end(buf)
} }
} }

View file

@ -14,7 +14,6 @@ use io::prelude::*;
use fmt; use fmt;
use io; use io;
use net::{ToSocketAddrs, SocketAddr, Shutdown}; use net::{ToSocketAddrs, SocketAddr, Shutdown};
use sys_common::io::read_to_end_uninitialized;
use sys_common::net as net_imp; use sys_common::net as net_imp;
use sys_common::{AsInner, FromInner, IntoInner}; use sys_common::{AsInner, FromInner, IntoInner};
use time::Duration; use time::Duration;
@ -269,7 +268,7 @@ impl TcpStream {
impl Read for TcpStream { impl Read for TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) } self.0.read_to_end(buf)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -281,7 +280,7 @@ impl Write for TcpStream {
impl<'a> Read for &'a TcpStream { impl<'a> Read for &'a TcpStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> { fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) } self.0.read_to_end(buf)
} }
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View file

@ -134,6 +134,9 @@ impl Read for ChildStdout {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf) self.inner.read(buf)
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
} }
impl AsInner<AnonPipe> for ChildStdout { impl AsInner<AnonPipe> for ChildStdout {
@ -161,6 +164,9 @@ impl Read for ChildStderr {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf) self.inner.read(buf)
} }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
} }
impl AsInner<AnonPipe> for ChildStderr { impl AsInner<AnonPipe> for ChildStderr {

View file

@ -225,6 +225,10 @@ impl TcpStream {
self.inner.read(buf) self.inner.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t; let len = cmp::min(buf.len(), <wrlen_t>::max_value() as usize) as wrlen_t;
let ret = try!(cvt(unsafe { let ret = try!(cvt(unsafe {

View file

@ -8,12 +8,15 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use io; use prelude::v1::*;
use io::{self, Read};
use libc::{self, c_int, size_t, c_void}; use libc::{self, c_int, size_t, c_void};
use mem; use mem;
use sync::atomic::{AtomicBool, Ordering};
use sys::cvt; use sys::cvt;
use sys_common::AsInner; use sys_common::AsInner;
use sync::atomic::{AtomicBool, Ordering}; use sys_common::io::read_to_end_uninitialized;
pub struct FileDesc { pub struct FileDesc {
fd: c_int, fd: c_int,
@ -42,6 +45,11 @@ impl FileDesc {
Ok(ret as usize) Ok(ret as usize)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let ret = try!(cvt(unsafe { let ret = try!(cvt(unsafe {
libc::write(self.fd, libc::write(self.fd,
@ -118,6 +126,17 @@ impl FileDesc {
} }
} }
#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a FileDesc {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) }
}
}
impl AsInner<c_int> for FileDesc { impl AsInner<c_int> for FileDesc {
fn as_inner(&self) -> &c_int { &self.fd } fn as_inner(&self) -> &c_int { &self.fd }
} }

View file

@ -486,6 +486,10 @@ impl File {
self.0.read(buf) self.0.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf) self.0.write(buf)
} }

View file

@ -116,6 +116,10 @@ impl Socket {
self.0.read(buf) self.0.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}
pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> { pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
let timeout = match dur { let timeout = match dur {
Some(dur) => { Some(dur) => {

View file

@ -57,6 +57,10 @@ impl AnonPipe {
self.0.read(buf) self.0.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.0.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.0.write(buf) self.0.write(buf)
} }

View file

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::v1::*;
use io; use io;
use libc; use libc;
use sys::fd::FileDesc; use sys::fd::FileDesc;
@ -25,6 +27,13 @@ impl Stdin {
fd.into_raw(); fd.into_raw();
ret ret
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let fd = FileDesc::new(libc::STDIN_FILENO);
let ret = fd.read_to_end(buf);
fd.into_raw();
ret
}
} }
impl Stdout { impl Stdout {

View file

@ -8,6 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::v1::*;
use io::prelude::*; use io::prelude::*;
use os::windows::prelude::*; use os::windows::prelude::*;
@ -312,6 +313,10 @@ impl File {
self.handle.read(buf) self.handle.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.handle.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.handle.write(buf) self.handle.write(buf)
} }

View file

@ -8,14 +8,17 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::v1::*;
use cmp; use cmp;
use io::ErrorKind; use io::{ErrorKind, Read};
use io; use io;
use mem; use mem;
use ops::Deref; use ops::Deref;
use ptr; use ptr;
use sys::c; use sys::c;
use sys::cvt; use sys::cvt;
use sys_common::io::read_to_end_uninitialized;
use u32; use u32;
/// An owned container for `HANDLE` object, closing them on Drop. /// An owned container for `HANDLE` object, closing them on Drop.
@ -87,6 +90,11 @@ impl RawHandle {
} }
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let mut amt = 0; let mut amt = 0;
// WriteFile takes a DWORD (u32) for the length so it only supports // WriteFile takes a DWORD (u32) for the length so it only supports
@ -111,3 +119,14 @@ impl RawHandle {
Ok(Handle::new(ret)) Ok(Handle::new(ret))
} }
} }
#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a RawHandle {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) }
}
}

View file

@ -8,8 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::v1::*;
use cmp; use cmp;
use io; use io::{self, Read};
use libc::{c_int, c_void, c_ulong}; use libc::{c_int, c_void, c_ulong};
use mem; use mem;
use net::{SocketAddr, Shutdown}; use net::{SocketAddr, Shutdown};
@ -20,6 +22,7 @@ use sync::Once;
use sys::c; use sys::c;
use sys; use sys;
use sys_common::{self, AsInner, FromInner, IntoInner}; use sys_common::{self, AsInner, FromInner, IntoInner};
use sys_common::io::read_to_end_uninitialized;
use sys_common::net; use sys_common::net;
use time::Duration; use time::Duration;
@ -142,6 +145,11 @@ impl Socket {
} }
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
}
pub fn set_timeout(&self, dur: Option<Duration>, pub fn set_timeout(&self, dur: Option<Duration>,
kind: c_int) -> io::Result<()> { kind: c_int) -> io::Result<()> {
let timeout = match dur { let timeout = match dur {
@ -206,6 +214,17 @@ impl Socket {
} }
} }
#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a Socket {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) }
}
}
impl Drop for Socket { impl Drop for Socket {
fn drop(&mut self) { fn drop(&mut self) {
let _ = unsafe { c::closesocket(self.0) }; let _ = unsafe { c::closesocket(self.0) };

View file

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use prelude::v1::*;
use io; use io;
use ptr; use ptr;
use sys::cvt; use sys::cvt;
@ -41,6 +43,10 @@ impl AnonPipe {
self.inner.read(buf) self.inner.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
pub fn write(&self, buf: &[u8]) -> io::Result<usize> { pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf) self.inner.write(buf)
} }

View file

@ -18,6 +18,7 @@ use sync::Mutex;
use sys::c; use sys::c;
use sys::cvt; use sys::cvt;
use sys::handle::Handle; use sys::handle::Handle;
use sys_common::io::read_to_end_uninitialized;
pub struct NoClose(Option<Handle>); pub struct NoClose(Option<Handle>);
@ -113,6 +114,22 @@ impl Stdin {
// MemReader shouldn't error here since we just filled it // MemReader shouldn't error here since we just filled it
utf8.read(buf) utf8.read(buf)
} }
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
}
}
#[unstable(reason = "not public", issue = "0", feature = "fd_read")]
impl<'a> Read for &'a Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
unsafe { read_to_end_uninitialized(self, buf) }
}
} }
impl Stdout { impl Stdout {