Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for optional io::Read/io::Write methods #136756

Open
thaliaarchi opened this issue Feb 9, 2025 · 0 comments
Open

Tracking issue for optional io::Read/io::Write methods #136756

thaliaarchi opened this issue Feb 9, 2025 · 0 comments
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC

Comments

@thaliaarchi
Copy link
Contributor

thaliaarchi commented Feb 9, 2025

This tracks the status of specializing optional methods in implementations of io::Read and io::Write in the standard library.

Read and Write have many methods which are provided by default, and many implementors do not override them, which can be problematic in some cases. Platform abstractions for stdio are particularly lacking; most of which do not have read_buf, so the buffer is forced to be initialized, and some platforms which support it might be missing vectored read/write. Since the standard library is general, this should be consistent.

I am working on addressing these gaps and have created this issue to track progress for myself and reviewers. I am still a new contributor to Rust, so please let me know if I have missed something about the process.

This surveys of all implementations of io::Read and io::Write in rust-lang/rust, including for private types, by searching for \b(Read|Write) for in .rs files. This should have no false negatives, as opposed to viewing references, which would omit other targets.

Additionally, I include all platform implementations of File. These define read, read_buf, read_vectored, is_read_vectored, write, write_vectored, is_write_vectored, and flush as inherent methods. Since the other methods are not currently supported with this scheme, I have marked them with N/A.

Implementation history

PRs created for this effort and some relevant PRs from earlier:

Read

pub trait Read {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
    fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {}
    fn read_buf_exact(&mut self, buf: BorrowedCursor<'_>) -> Result<()> {}
    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize> {}
    fn is_read_vectored(&self) -> bool {} // considered with `read_vectored`
    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {}
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {}
    fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {}
}
impl Read for T buf buf_exact vectored exact to_end to_string
&mut Read 1 2 3 4 5 5
Box<Read> 1 2 3 4 6 6
&[u8] 1 2 3 4 7
VecDeque<u8> 8 8 7 7
std::io::Chain<Read, Read> 9 3 9 9
std::io::Take<Read> 1
std::io::Empty #137051 #137051 #137051 #137051 #137051
std::io::Repeat 1 10 3 4 10
std::io::Cursor<AsRef<[u8]>> 1 2 3 4 11 11
std::io::BufReader<Read> 1 2 3 4
std::net::TcpStream 3 4
&std::net::TcpStream 3 4
std::os::unix::net::UnixStream 12 3 4
&std::os::unix::net::UnixStream 12 3 4
&std::sys::net::windows::Socket13
std::io::PipeReader
&std::io::PipeReader
std::fs::File 1 ✅/✅4
&std::fs::File 1 ✅/✅4
Arc<std::fs::File>
std::sys::hermit::fs::File #136769 N/A N/A N/A N/A
std::sys::solid::fs::File N/A N/A N/A N/A
std::sys::unix::fs::File 1 N/A ✅/✅4 N/A N/A N/A
std::sys::unsupported::fs::File 1 N/A N/A N/A N/A
std::sys::wasi::fs::File N/A ✅/✅4 N/A N/A N/A
std::sys::windows::fs::File 1 N/A ✅/✅4 N/A N/A N/A
std::sys::unix::fd::FileDesc 1 ✅/✅4
std::sys::unix::fs::CachedFileMetadata
std::sys::windows::handle::Handle 1
&std::sys::hermit::fd::FileDesc14
std::io::Stdin 2 ✅/✅4
&std::io::Stdin 2
std::io::StdinLock<'_> 2 ✅/✅4
std::io::stdio::StdinRaw #136769 ✅/✅4 #136769
std::process::ChildStdout ✅/✅4
std::process::ChildStderr ✅/✅4 11
std::sys::hermit::stdio::Stdin #136769 ✅/✅4
std::sys::sgx::stdio::Stdin #137355 #137355
std::sys::solid::stdio::Stdin15
std::sys::teeos::stdio::Stdin15
std::sys::uefi::stdio::Stdin
std::sys::unix::stdio::Stdin ✅/✅4
std::sys::unsupported::stdio::Stdin #136769 #136769
std::sys::wasi::stdio::Stdin 16 ✅/✅4
std::sys::windows::stdio::Stdin
std::sys::xous::stdio::Stdin15
std::sys::zkvm::stdio::Stdin 17 18
cargo::util::FileLock
cargo::util::LimitErrorReader<Read>

Write

pub trait Write {
    fn write(&mut self, buf: &[u8]) -> Result<usize>;
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {}
    fn is_write_vectored(&self) -> bool {} // considered with `write_vectored`
    fn write_all(&mut self, buf: &[u8]) -> Result<()> {}
    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<()> {}
    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {}
    fn flush(&mut self) -> Result<()>;
}
impl Write for T vectored all all_vectored fmt
&mut Write 3 4 5 19 5
Box<Write> 3 4 6 19 6
&mut [u8] 3 4 5 #137107
Vec<u8> 3 4 5 #137107 #137107
VecDeque<u8> 7 #136819 / #137107 #137107
std::io::Cursor<&mut [u8]> 3 4 #137107 #137107
std::io::Cursor<&mut Vec<u8>> 3 4 #137107 #137107 #137107
std::io::Cursor<Vec<u8>> 3 4 #137107 #137107 #137107
std::io::Cursor<Box<[u8]>> 3 4 #137107 #137107
std::io::Cursor<[u8; N]> #137107 #137107
core::io::BorrowedCursor<'_> #137107 #137107 #137107
std::io::BufWriter<Write> 3 4
std::io::LineWriter<Write>
std::io::…::LineWriterShim<'_, Write>
std::io::Empty #137051 #137051
&std::io::Empty #137051 #137051
std::io::Sink 3 4 #137051 #137051
&std::io::Sink #137051 #137051
std::net::TcpStream 3 4
&std::net::TcpStream 3 4
std::os::unix::net::UnixStream 3 4
&std::os::unix::net::UnixStream 3 4
std::io::PipeWriter
&std::io::PipeWriter
std::fs::File ✅/✅4
&std::fs::File ✅/✅4
Arc<std::fs::File>
std::sys::hermit::fs::File N/A N/A N/A
std::sys::solid::fs::File N/A N/A N/A
std::sys::unix::fs::File N/A N/A N/A
std::sys::unsupported::fs::File N/A N/A N/A
std::sys::wasi::fs::File ✅/✅4 N/A N/A N/A
std::sys::windows::fs::File ✅/✅4 N/A N/A N/A
std::sys::unix::fs::CachedFileMetadata
std::io::Stdout ✅/✅4
&std::io::Stdout
&std::io::StdoutLock<'_> ✅/✅4 20
std::io::stdio::StdoutRaw ✅/✅4
std::io::Stderr ✅/✅4
&std::io::Stderr
&std::io::StderrLock<'_> ✅/✅4 20
std::io::stdio::StderrRaw ✅/✅4
std::process::ChildStdin ✅/✅4
&std::process::ChildStdin
std::sys::hermit::stdio::Stdout ✅/✅4
std::sys::hermit::stdio::Stderr ✅/✅4
std::sys::sgx::stdio::Stdout #137355
std::sys::sgx::stdio::Stderr #137355
std::sys::sgx::abi::panic::SgxPanicOutput TODO
std::sys::solid::stdio::Stdout 21
std::sys::solid::stdio::Stderr 21
std::sys::solid::stdio::PanicOutput 21
std::sys::teeos::stdio::Stdout 22
std::sys::teeos::stdio::Stderr 22
std::sys::uefi::stdio::Stdout
std::sys::uefi::stdio::Stderr
std::sys::unix::stdio::Stdout ✅/✅4
std::sys::unix::stdio::Stderr ✅/✅4
std::sys::unsupported::stdio::Stdout #136769
std::sys::unsupported::stdio::Stderr #136769
std::sys::wasi::stdio::Stdout ✅/✅4
std::sys::wasi::stdio::Stderr ✅/✅4
std::sys::windows::stdio::Stdout
std::sys::windows::stdio::Stderr
std::sys::xous::stdio::Stdout #136769
std::sys::xous::stdio::Stderr #136769
std::sys::xous::stdio::PanicWriter
std::sys::zkvm::stdio::Stdout 18
std::sys::zkvm::stdio::Stderr 18
test::console::OutputLocation<Write> WIP
test::term::WinConsole<Write> WIP
test::term::TerminfoTerminal<Write> WIP
cargo::util::FileLock
proc_macro::bridge::buffer::Buffer
rust-installer::compression::CombinedEncoder
rustc_errors::emitter::Buffy
rustc_errors::json::…::BufWriter WIP

FileExt

Type read_at seek_read read_vectored_at read_exact_at write_at seek_write write_vectored_at write_all_at
std::fs::unix::fs::File N/A 23 default N/A 23 default
std::sys::wasi::fs::File default N/A default default N/A default
std::sys::windows::fs::File N/A N/A N/A N/A N/A N/A

Socket

Type read read_buf read_vectored recv_from peek peek_from write write_vectored
std::sys::net::hermit::Socket ✅/✅4 ✅/✅4
std::sys::net::solid::Socket
std::sys::net::unix::Socket 3 4 3 4
std::sys::net::wasip2::Socket default private default
std::sys::net::windows::Socket 3 4 3 4
std::sys::net::sgx::{TcpStream, UdpSocket} 3 4 unsupported unsupported (ok) unsupported 3 4
std::sys::net::wasip1::{TcpStream, UdpSocket} 3 4 unsupported unsupported unsupported 3 4

Footnotes

  1. Added in Implement most of RFC 2930, providing the ReadBuf abstraction #81156. 2 3 4 5 6 7 8 9 10 11 12 13 14

  2. Added in Specialize many implementations of Read::read_buf_exact #122393. 2 3 4 5 6 7 8

  3. Added in Add vectored read and write support #58357. 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

  4. Added in Add Read/Write::can_read/write_vectored #67841. 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

  5. Added in std: Update the std::io adaptors to proxy all methods #22428. 2 3 4 5 6

  6. Added in std: Stabilize portions of the io module #23010. 2 3 4

  7. Added in Specialize some io::Read and io::Write methods for VecDeque<u8> and &[u8] #110608. 2 3 4

  8. Added in Specialize read_exact and read_buf_exact for VecDeque #132039. 2

  9. Added in Specialize some methods of io::Chain #105917. 2 3

  10. Added in Implement read*_exact for std:io::repeat #136818. 2

  11. Added in Improve several Read implementations #122441. 2 3

  12. Added in UnixStream: override read_buf #123084. 2

  13. This Read implementation is unused. I plan to remove it.

  14. This Read implementation is unused. I plan to remove it.

  15. This platform doesn't have stdin. I replace it with std::sys::unsupported::stdio::Stdin in #136769. 2 3

  16. Added in Implement read_buf for WASI stdin #137353.

  17. Added in Implement read_buf for zkVM stdin #137349.

  18. zkVM has no vectored read/write syscalls. 2 3

  19. Added in Forward all default methods for I/O impls #137062. 2

  20. StdoutLock<'_> and StderrLock<'_> cannot provide write_fmt, because the user could supply a formatting implementation which uses Stdout or Stderr, leading to panicking. (See joboet's comment) 2

  21. SOLID has no vectored version of SOLID_LOG_write. 2 3

  22. TEEOS has no vectored version of KCALL_DEBUG_CMD_PUT_BYTES. 2

  23. Added in Add vectored positioned I/O on Unix #89518. 2

@thaliaarchi thaliaarchi added the C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC label Feb 9, 2025
a1phyr added a commit to a1phyr/rust that referenced this issue Feb 10, 2025
a1phyr added a commit to a1phyr/rust that referenced this issue Feb 10, 2025
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Feb 12, 2025
jhpratt added a commit to jhpratt/rust that referenced this issue Feb 13, 2025
jhpratt added a commit to jhpratt/rust that referenced this issue Feb 13, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 13, 2025
Rollup merge of rust-lang#136818 - a1phyr:io_repeat_exact, r=jhpratt

Implement `read*_exact` for `std:io::repeat`

cc rust-lang#136756
thaliaarchi added a commit to thaliaarchi/hermit-kernel that referenced this issue Feb 19, 2025
Currently, when using an uninitialized buffer for `read`, as would be
typical in C or required for `Read::read_buf`, it is casted from `*mut
u8` at the FFI boundary in `sys_read`/`sys_readv` to a `&[u8]`. I think
this is unsound. Instead, use `&[MaybeUninit<u8>]` internally.

This enables implementing `std::io::Read::read_buf` for `std::fs::File`
and `std::io::Stdin` on Hermit. That effort is tracked in
rust-lang/rust#136756.
thaliaarchi added a commit to thaliaarchi/hermit-kernel that referenced this issue Feb 19, 2025
Currently, when using an uninitialized buffer for `read`, as would be
typical in C or required for `Read::read_buf`, it is casted from `*mut
u8` at the FFI boundary in `sys_read`/`sys_readv` to a `&[u8]`. I think
this is unsound.

Instead, use `&[MaybeUninit<u8>]` internally. I use this instead of
`core::io::BorrowedCursor<'_>`, because there are currently no cases
where the initialized portion needs to be separately tracked.

This enables implementing `std::io::Read::read_buf` for `std::fs::File`
and `std::io::Stdin` on Hermit. That effort is tracked in
rust-lang/rust#136756.
thaliaarchi added a commit to thaliaarchi/hermit-kernel that referenced this issue Feb 19, 2025
Currently, when using an uninitialized buffer for `read`, as would be
typical in C or required for `Read::read_buf`, it is casted from `*mut
u8` at the FFI boundary in `sys_read`/`sys_readv` to a `&[u8]`. I think
this is unsound.

Instead, use `&[MaybeUninit<u8>]` internally. I use this instead of
`core::io::BorrowedCursor<'_>`, because there are currently no cases
where the initialized portion needs to be separately tracked.

This enables implementing `std::io::Read::read_buf` for `std::fs::File`
and `std::io::Stdin` on Hermit. That effort is tracked in
rust-lang/rust#136756.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 21, 2025
…si-stdin, r=alexcrichton

Implement `read_buf` for WASI stdin

`WasiFd::read_buf` already exists. Simply use it in `Stdin`.

cc `@alexcrichton`

Tracked in rust-lang#136756
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 21, 2025
Rollup merge of rust-lang#137353 - thaliaarchi:io-optional-methods/wasi-stdin, r=alexcrichton

Implement `read_buf` for WASI stdin

`WasiFd::read_buf` already exists. Simply use it in `Stdin`.

cc `@alexcrichton`

Tracked in rust-lang#136756
github-actions bot pushed a commit to model-checking/verify-rust-std that referenced this issue Feb 22, 2025
github-actions bot pushed a commit to carolynzech/rust that referenced this issue Feb 22, 2025
github-actions bot pushed a commit to tautschnig/verify-rust-std that referenced this issue Feb 22, 2025
github-actions bot pushed a commit to thanhnguyen-aws/verify-rust-std that referenced this issue Feb 22, 2025
tgross35 added a commit to tgross35/rust that referenced this issue Feb 24, 2025
…vm, r=Noratrieb

Implement `read_buf` for zkVM stdin

For the zkVM, even when a guest buffer is uninitialized, from the host's perspective it is just a normal piece of memory which was initialized before letting the guest write into it. This makes `sys_read` safe to use with an uninitialized buffer. See risc0/risc0#2853.

cc `@bobbobbio,` `@flaub`

r? `@Noratrieb`

Tracked in rust-lang#136756
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Feb 25, 2025
Rollup merge of rust-lang#137349 - thaliaarchi:io-optional-methods/zkvm, r=Noratrieb

Implement `read_buf` for zkVM stdin

For the zkVM, even when a guest buffer is uninitialized, from the host's perspective it is just a normal piece of memory which was initialized before letting the guest write into it. This makes `sys_read` safe to use with an uninitialized buffer. See risc0/risc0#2853.

cc `@bobbobbio,` `@flaub`

r? `@Noratrieb`

Tracked in rust-lang#136756
github-actions bot pushed a commit to rust-lang/miri that referenced this issue Feb 26, 2025
…atrieb

Implement `read_buf` for zkVM stdin

For the zkVM, even when a guest buffer is uninitialized, from the host's perspective it is just a normal piece of memory which was initialized before letting the guest write into it. This makes `sys_read` safe to use with an uninitialized buffer. See risc0/risc0#2853.

cc `@bobbobbio,` `@flaub`

r? `@Noratrieb`

Tracked in rust-lang/rust#136756
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC
Projects
None yet
Development

No branches or pull requests

1 participant