mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #136769 - thaliaarchi:io-optional-methods/stdio, r=joboet
Provide optional `Read`/`Write` methods for stdio Override more of the default methods for `io::Read` and `io::Write` for stdio types, when efficient to do so, and deduplicate unsupported types. Tracked in https://github.com/rust-lang/rust/issues/136756. try-job: x86_64-msvc-1
This commit is contained in:
commit
60a3084f64
@ -97,15 +97,15 @@ const fn stderr_raw() -> StderrRaw {
|
||||
|
||||
impl Read for StdinRaw {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.read(buf), 0)
|
||||
handle_ebadf(self.0.read(buf), || Ok(0))
|
||||
}
|
||||
|
||||
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
handle_ebadf(self.0.read_buf(buf), ())
|
||||
handle_ebadf(self.0.read_buf(buf), || Ok(()))
|
||||
}
|
||||
|
||||
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.read_vectored(bufs), 0)
|
||||
handle_ebadf(self.0.read_vectored(bufs), || Ok(0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -113,23 +113,37 @@ impl Read for StdinRaw {
|
||||
self.0.is_read_vectored()
|
||||
}
|
||||
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
if buf.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
handle_ebadf(self.0.read_exact(buf), || Err(io::Error::READ_EXACT_EOF))
|
||||
}
|
||||
|
||||
fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
if buf.capacity() == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
handle_ebadf(self.0.read_buf_exact(buf), || Err(io::Error::READ_EXACT_EOF))
|
||||
}
|
||||
|
||||
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.read_to_end(buf), 0)
|
||||
handle_ebadf(self.0.read_to_end(buf), || Ok(0))
|
||||
}
|
||||
|
||||
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.read_to_string(buf), 0)
|
||||
handle_ebadf(self.0.read_to_string(buf), || Ok(0))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for StdoutRaw {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.write(buf), buf.len())
|
||||
handle_ebadf(self.0.write(buf), || Ok(buf.len()))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let total = || bufs.iter().map(|b| b.len()).sum();
|
||||
handle_ebadf_lazy(self.0.write_vectored(bufs), total)
|
||||
let total = || Ok(bufs.iter().map(|b| b.len()).sum());
|
||||
handle_ebadf(self.0.write_vectored(bufs), total)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -138,30 +152,30 @@ impl Write for StdoutRaw {
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
handle_ebadf(self.0.flush(), ())
|
||||
handle_ebadf(self.0.flush(), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_all(buf), ())
|
||||
handle_ebadf(self.0.write_all(buf), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_all_vectored(bufs), ())
|
||||
handle_ebadf(self.0.write_all_vectored(bufs), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_fmt(fmt), ())
|
||||
handle_ebadf(self.0.write_fmt(fmt), || Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for StderrRaw {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
handle_ebadf(self.0.write(buf), buf.len())
|
||||
handle_ebadf(self.0.write(buf), || Ok(buf.len()))
|
||||
}
|
||||
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let total = || bufs.iter().map(|b| b.len()).sum();
|
||||
handle_ebadf_lazy(self.0.write_vectored(bufs), total)
|
||||
let total = || Ok(bufs.iter().map(|b| b.len()).sum());
|
||||
handle_ebadf(self.0.write_vectored(bufs), total)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -170,32 +184,25 @@ impl Write for StderrRaw {
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
handle_ebadf(self.0.flush(), ())
|
||||
handle_ebadf(self.0.flush(), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_all(buf), ())
|
||||
handle_ebadf(self.0.write_all(buf), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_all_vectored(bufs), ())
|
||||
handle_ebadf(self.0.write_all_vectored(bufs), || Ok(()))
|
||||
}
|
||||
|
||||
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
|
||||
handle_ebadf(self.0.write_fmt(fmt), ())
|
||||
handle_ebadf(self.0.write_fmt(fmt), || Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
|
||||
fn handle_ebadf<T>(r: io::Result<T>, default: impl FnOnce() -> io::Result<T>) -> io::Result<T> {
|
||||
match r {
|
||||
Err(ref e) if stdio::is_ebadf(e) => Ok(default),
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ebadf_lazy<T>(r: io::Result<T>, default: impl FnOnce() -> T) -> io::Result<T> {
|
||||
match r {
|
||||
Err(ref e) if stdio::is_ebadf(e) => Ok(default()),
|
||||
Err(ref e) if stdio::is_ebadf(e) => default(),
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ use fortanix_sgx_abi as abi;
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
use crate::sys::fd::FileDesc;
|
||||
|
||||
pub struct Stdin(());
|
||||
pub struct Stdout(());
|
||||
pub struct Stderr(());
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
|
||||
fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
|
||||
let fd = FileDesc::new(fd);
|
||||
@ -16,7 +16,7 @@ fn with_std_fd<F: FnOnce(&FileDesc) -> R, R>(fd: abi::Fd, f: F) -> R {
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin(())
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ impl io::Read for Stdin {
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
Stdout(())
|
||||
Stdout
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ impl io::Write for Stdout {
|
||||
|
||||
impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr(())
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,13 @@
|
||||
#[expect(dead_code)]
|
||||
#[path = "unsupported.rs"]
|
||||
mod unsupported_stdio;
|
||||
|
||||
use crate::io;
|
||||
use crate::sys::pal::abi;
|
||||
|
||||
pub struct Stdin;
|
||||
pub type Stdin = unsupported_stdio::Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
struct PanicOutput;
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
pub type Stderr = Stdout;
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
@ -35,46 +26,12 @@ impl io::Write for Stdout {
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) };
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PanicOutput {
|
||||
pub const fn new() -> PanicOutput {
|
||||
PanicOutput
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for PanicOutput {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
unsafe { abi::SOLID_LOG_write(buf.as_ptr(), buf.len()) };
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub const STDIN_BUF_SIZE: usize = 0;
|
||||
pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
|
||||
|
||||
pub fn is_ebadf(_err: &io::Error) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn panic_output() -> Option<impl io::Write> {
|
||||
Some(PanicOutput::new())
|
||||
Some(Stderr::new())
|
||||
}
|
||||
|
@ -1,12 +1,16 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[expect(dead_code)]
|
||||
#[path = "unsupported.rs"]
|
||||
mod unsupported_stdio;
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
use crate::io;
|
||||
|
||||
pub struct Stdin;
|
||||
pub type Stdin = unsupported_stdio::Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
pub type Stderr = Stdout;
|
||||
|
||||
const KCALL_DEBUG_CMD_PUT_BYTES: i64 = 2;
|
||||
|
||||
@ -25,27 +29,6 @@ unsafe fn debug_call(cap_ref: u64, call_no: i64, arg1: u64, arg2: u64) -> i32 {
|
||||
ret as i32
|
||||
}
|
||||
|
||||
fn print_buf(s: &[u8]) -> io::Result<usize> {
|
||||
// Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`.
|
||||
const MAX_LEN: usize = 512;
|
||||
let len = if s.len() > MAX_LEN { MAX_LEN } else { s.len() };
|
||||
let result = unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, s.as_ptr() as u64, len as u64) };
|
||||
|
||||
if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) }
|
||||
}
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
Stdout
|
||||
@ -54,7 +37,13 @@ impl Stdout {
|
||||
|
||||
impl io::Write for Stdout {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
print_buf(buf)
|
||||
// Corresponds to `HM_DEBUG_PUT_BYTES_LIMIT`.
|
||||
const MAX_LEN: usize = 512;
|
||||
let len = buf.len().min(MAX_LEN);
|
||||
let result =
|
||||
unsafe { debug_call(0, KCALL_DEBUG_CMD_PUT_BYTES, buf.as_ptr() as u64, len as u64) };
|
||||
|
||||
if result == 0 { Ok(len) } else { Err(io::Error::from(io::ErrorKind::InvalidInput)) }
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
@ -62,23 +51,7 @@ impl io::Write for Stdout {
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
print_buf(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub const STDIN_BUF_SIZE: usize = 0;
|
||||
pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
|
||||
|
||||
pub fn is_ebadf(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(libc::EBADF as i32)
|
||||
|
@ -11,13 +11,13 @@ use crate::os::hermit::io::FromRawFd;
|
||||
use crate::os::unix::io::FromRawFd;
|
||||
use crate::sys::fd::FileDesc;
|
||||
|
||||
pub struct Stdin(());
|
||||
pub struct Stdout(());
|
||||
pub struct Stderr(());
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin(())
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ impl io::Read for Stdin {
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
Stdout(())
|
||||
Stdout
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ impl io::Write for Stdout {
|
||||
|
||||
impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr(())
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::io;
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
pub type Stderr = Stdout;
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
@ -11,9 +11,47 @@ impl Stdin {
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
#[inline]
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_buf(&mut self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_vectored(&mut self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_read_vectored(&self) -> bool {
|
||||
// Do not force `Chain<Empty, T>` or `Chain<T, Empty>` to use vectored
|
||||
// reads, unless the other reader is vectored.
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
|
||||
if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
if cursor.capacity() != 0 { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_to_end(&mut self, _buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_to_string(&mut self, _buf: &mut String) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
@ -23,26 +61,35 @@ impl Stdout {
|
||||
}
|
||||
|
||||
impl io::Write for Stdout {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
#[inline]
|
||||
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let total_len = bufs.iter().map(|b| b.len()).sum();
|
||||
Ok(total_len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_all(&mut self, _buf: &[u8]) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub const fn new() -> Stderr {
|
||||
Stderr
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
Ok(buf.len())
|
||||
#[inline]
|
||||
fn write_all_vectored(&mut self, _bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Keep the default write_fmt so the `fmt::Arguments` are still evaluated.
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,27 +1,18 @@
|
||||
#[expect(dead_code)]
|
||||
#[path = "unsupported.rs"]
|
||||
mod unsupported_stdio;
|
||||
|
||||
use crate::io;
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout {}
|
||||
pub struct Stderr;
|
||||
|
||||
use crate::os::xous::ffi::{Connection, lend, try_lend, try_scalar};
|
||||
use crate::os::xous::services::{LogLend, LogScalar, log_server, try_connect};
|
||||
|
||||
impl Stdin {
|
||||
pub const fn new() -> Stdin {
|
||||
Stdin
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Read for Stdin {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Ok(0)
|
||||
}
|
||||
}
|
||||
pub type Stdin = unsupported_stdio::Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
|
||||
impl Stdout {
|
||||
pub const fn new() -> Stdout {
|
||||
Stdout {}
|
||||
Stdout
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,7 +64,7 @@ impl io::Write for Stderr {
|
||||
}
|
||||
}
|
||||
|
||||
pub const STDIN_BUF_SIZE: usize = 0;
|
||||
pub const STDIN_BUF_SIZE: usize = unsupported_stdio::STDIN_BUF_SIZE;
|
||||
|
||||
pub fn is_ebadf(_err: &io::Error) -> bool {
|
||||
true
|
||||
|
Loading…
Reference in New Issue
Block a user