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