WASI previously used `u32` as its `RawFd` type, since its "file descriptors" are unsigned table indices, and there's no fundamental reason why WASI can't have more than 2^31 handles. However, this creates myriad little incompability problems with code that also supports Unix platforms, where `RawFd` is `c_int`. While WASI isn't a Unix, it often shares code with Unix, and this difference made such shared code inconvenient. #87329 is the most recent example of such code. So, switch WASI to use `c_int`, which is `i32`. This will mean that code intending to support WASI should ideally avoid assuming that negative file descriptors are invalid, even though POSIX itself says that file descriptors are never negative. This is a breaking change, but `RawFd` is considerd an experimental feature in [the documentation]. [the documentation]: https://doc.rust-lang.org/stable/std/os/wasi/io/type.RawFd.html
106 lines
2.2 KiB
Rust
106 lines
2.2 KiB
Rust
#![deny(unsafe_op_in_unsafe_fn)]
|
|
|
|
use super::fd::WasiFd;
|
|
use crate::io::{self, IoSlice, IoSliceMut};
|
|
use crate::mem::ManuallyDrop;
|
|
use crate::os::raw;
|
|
|
|
pub struct Stdin;
|
|
pub struct Stdout;
|
|
pub struct Stderr;
|
|
|
|
impl Stdin {
|
|
pub const fn new() -> Stdin {
|
|
Stdin
|
|
}
|
|
|
|
#[inline]
|
|
pub fn as_raw_fd(&self) -> raw::c_int {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl io::Read for Stdin {
|
|
fn read(&mut self, data: &mut [u8]) -> io::Result<usize> {
|
|
self.read_vectored(&mut [IoSliceMut::new(data)])
|
|
}
|
|
|
|
fn read_vectored(&mut self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
|
|
}
|
|
|
|
#[inline]
|
|
fn is_read_vectored(&self) -> bool {
|
|
true
|
|
}
|
|
}
|
|
|
|
impl Stdout {
|
|
pub const fn new() -> Stdout {
|
|
Stdout
|
|
}
|
|
|
|
#[inline]
|
|
pub fn as_raw_fd(&self) -> raw::c_int {
|
|
1
|
|
}
|
|
}
|
|
|
|
impl io::Write for Stdout {
|
|
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
|
self.write_vectored(&[IoSlice::new(data)])
|
|
}
|
|
|
|
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
|
}
|
|
|
|
#[inline]
|
|
fn is_write_vectored(&self) -> bool {
|
|
true
|
|
}
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Stderr {
|
|
pub const fn new() -> Stderr {
|
|
Stderr
|
|
}
|
|
|
|
#[inline]
|
|
pub fn as_raw_fd(&self) -> raw::c_int {
|
|
2
|
|
}
|
|
}
|
|
|
|
impl io::Write for Stderr {
|
|
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
|
self.write_vectored(&[IoSlice::new(data)])
|
|
}
|
|
|
|
fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
|
|
}
|
|
|
|
#[inline]
|
|
fn is_write_vectored(&self) -> bool {
|
|
true
|
|
}
|
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
|
|
|
|
pub fn is_ebadf(err: &io::Error) -> bool {
|
|
err.raw_os_error() == Some(wasi::ERRNO_BADF.into())
|
|
}
|
|
|
|
pub fn panic_output() -> Option<impl io::Write> {
|
|
Some(Stderr::new())
|
|
}
|