Use standard Read/Write traits in sys::stdio
This commit is contained in:
@@ -9,8 +9,10 @@ impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> {
|
||||
Ok(Stdin(()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
@@ -19,15 +21,17 @@ impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> {
|
||||
Ok(Stdout(()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::BrokenPipe,
|
||||
"Stdout is not connected to any output in this environment",
|
||||
))
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -36,15 +40,17 @@ impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> {
|
||||
Ok(Stderr(()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::BrokenPipe,
|
||||
"Stderr is not connected to any output in this environment",
|
||||
))
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ pub struct Stderr(());
|
||||
|
||||
impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(0);
|
||||
let ret = fd.read(data);
|
||||
let ret = fd.read(buf);
|
||||
fd.into_raw();
|
||||
ret
|
||||
}
|
||||
@@ -19,30 +21,34 @@ impl Stdin {
|
||||
|
||||
impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(1);
|
||||
let ret = fd.write(data);
|
||||
let ret = fd.write(buf);
|
||||
fd.into_raw();
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
cvt(syscall::fsync(1)).and(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(2);
|
||||
let ret = fd.write(data);
|
||||
let ret = fd.write(buf);
|
||||
fd.into_raw();
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
cvt(syscall::fsync(2)).and(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,32 +16,38 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
|
||||
|
||||
impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDIN, |fd| fd.read(data))
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDIN, |fd| fd.read(buf))
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDOUT, |fd| fd.write(data))
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDOUT, |fd| fd.write(buf))
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
with_std_fd(abi::FD_STDOUT, |fd| fd.flush())
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDERR, |fd| fd.write(data))
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
with_std_fd(abi::FD_STDERR, |fd| fd.write(buf))
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
with_std_fd(abi::FD_STDERR, |fd| fd.flush())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ pub struct Stderr(());
|
||||
|
||||
impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(libc::STDIN_FILENO);
|
||||
let ret = fd.read(data);
|
||||
let ret = fd.read(buf);
|
||||
fd.into_raw(); // do not close this FD
|
||||
ret
|
||||
}
|
||||
@@ -19,30 +21,34 @@ impl Stdin {
|
||||
|
||||
impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(libc::STDOUT_FILENO);
|
||||
let ret = fd.write(data);
|
||||
let ret = fd.write(buf);
|
||||
fd.into_raw(); // do not close this FD
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let fd = FileDesc::new(libc::STDERR_FILENO);
|
||||
let ret = fd.write(data);
|
||||
let ret = fd.write(buf);
|
||||
fd.into_raw(); // do not close this FD
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,11 @@ impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> {
|
||||
Ok(Stdin)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(ReadSysCall::perform(0, data))
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(ReadSysCall::perform(0, buf))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +21,15 @@ impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> {
|
||||
Ok(Stdout)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
WriteSysCall::perform(1, data);
|
||||
Ok(data.len())
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
WriteSysCall::perform(1, buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -34,13 +38,15 @@ impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> {
|
||||
Ok(Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
WriteSysCall::perform(2, data);
|
||||
Ok(data.len())
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
WriteSysCall::perform(2, buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#![unstable(issue = "0", feature = "windows_stdio")]
|
||||
|
||||
use cell::Cell;
|
||||
use char::decode_utf16;
|
||||
use cmp;
|
||||
use io;
|
||||
@@ -13,7 +12,7 @@ use sys::handle::Handle;
|
||||
// Don't cache handles but get them fresh for every read/write. This allows us to track changes to
|
||||
// the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
|
||||
pub struct Stdin {
|
||||
high_surrogate: Cell<u16>,
|
||||
surrogate: u16,
|
||||
}
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
@@ -128,10 +127,12 @@ fn write_u16s(handle: c::HANDLE, data: &[u16]) -> io::Result<usize> {
|
||||
|
||||
impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> {
|
||||
Ok(Stdin { high_surrogate: Cell::new(0) })
|
||||
Ok(Stdin { surrogate: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let handle = get_handle(c::STD_INPUT_HANDLE)?;
|
||||
if !is_console(handle) {
|
||||
let handle = Handle::new(handle);
|
||||
@@ -153,21 +154,26 @@ impl Stdin {
|
||||
// we can read at most a third of `buf.len()` chars and uphold the guarantee no data gets
|
||||
// lost.
|
||||
let amount = cmp::min(buf.len() / 3, utf16_buf.len());
|
||||
let read = self.read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount)?;
|
||||
let read = read_u16s_fixup_surrogates(handle, &mut utf16_buf, amount, &mut self.surrogate)?;
|
||||
|
||||
utf16_to_utf8(&utf16_buf[..read], buf)
|
||||
}
|
||||
}
|
||||
|
||||
// We assume that if the last `u16` is an unpaired surrogate they got sliced apart by our
|
||||
// buffer size, and keep it around for the next read hoping to put them together.
|
||||
// This is a best effort, and may not work if we are not the only reader on Stdin.
|
||||
fn read_u16s_fixup_surrogates(&self, handle: c::HANDLE, buf: &mut [u16], mut amount: usize)
|
||||
-> io::Result<usize>
|
||||
{
|
||||
|
||||
// We assume that if the last `u16` is an unpaired surrogate they got sliced apart by our
|
||||
// buffer size, and keep it around for the next read hoping to put them together.
|
||||
// This is a best effort, and may not work if we are not the only reader on Stdin.
|
||||
fn read_u16s_fixup_surrogates(handle: c::HANDLE,
|
||||
buf: &mut [u16],
|
||||
mut amount: usize,
|
||||
surrogate: &mut u16) -> io::Result<usize>
|
||||
{
|
||||
// Insert possibly remaining unpaired surrogate from last read.
|
||||
let mut start = 0;
|
||||
if self.high_surrogate.get() != 0 {
|
||||
buf[0] = self.high_surrogate.replace(0);
|
||||
if *surrogate != 0 {
|
||||
buf[0] = *surrogate;
|
||||
*surrogate = 0;
|
||||
start = 1;
|
||||
if amount == 1 {
|
||||
// Special case: `Stdin::read` guarantees we can always read at least one new `u16`
|
||||
@@ -181,12 +187,11 @@ impl Stdin {
|
||||
if amount > 0 {
|
||||
let last_char = buf[amount - 1];
|
||||
if last_char >= 0xD800 && last_char <= 0xDBFF { // high surrogate
|
||||
self.high_surrogate.set(last_char);
|
||||
*surrogate = last_char;
|
||||
amount -= 1;
|
||||
}
|
||||
}
|
||||
Ok(amount)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_u16s(handle: c::HANDLE, buf: &mut [u16]) -> io::Result<usize> {
|
||||
@@ -241,12 +246,14 @@ impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> {
|
||||
Ok(Stdout)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
write(c::STD_OUTPUT_HANDLE, data)
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
write(c::STD_OUTPUT_HANDLE, buf)
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -255,12 +262,14 @@ impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> {
|
||||
Ok(Stderr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
write(c::STD_ERROR_HANDLE, data)
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
write(c::STD_ERROR_HANDLE, buf)
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user