Prevously the `read_to_end` implementation for `std::io::Take` used its
own `limit` as a cap on the `reservation_size`. However, that could
still result in an over-allocation like this:
1. Call `reader.take(5).read_to_end(&mut vec)`.
2. `read_to_end_with_reservation` reserves 5 bytes and calls `read`.
3. `read` writes 5 bytes.
4. `read_to_end_with_reservation` reserves 5 bytes and calls `read`.
5. `read` writes 0 bytes.
6. The read loop ends with `vec` having length 5 and capacity 10.
The reservation of 5 bytes was correct for the read at step 2 but
unnecessary for the read at step 4. By that second read, `Take::limit`
is 0, but the `read_to_end_with_reservation` loop is still using the
same `reservation_size` it started with.
Solve this by having `read_to_end_with_reservation` take a closure,
which lets it get a fresh `reservation_size` for each read. This is an
implementation detail which doesn't affect any public API.
simplify std::io::Write::write rustdoc
The std::io::Write::write method currensly suggests consumers guaranteed
that `0 <= n <= buf.len()`, for `Ok(n)`, however `n` is of type `usize`
causing the compiler to emit a warning:
```
warning: comparison is useless due to type limits
--> lib.rs:6:18
|
6 | Ok(n) => 0 <= n && n <= output.len(),
| ^^^^^^
|
= note: #[warn(unused_comparisons)] on by default
```
This PR removes the suggestion to check `0 <= n` since it is moot.
r? @steveklabnik
The std::io::Write::write method currensly suggests consumers guaranteed
that `0 <= n <= buf.len()`, for `Ok(n)`, however `n` is of type `usize`
causing the compiler to emit a warning:
```
warning: comparison is useless due to type limits
--> lib.rs:6:18
|
6 | Ok(n) => 0 <= n && n <= output.len(),
| ^^^^^^
|
= note: #[warn(unused_comparisons)] on by default
```
This PR removes the suggestion to check `0 <= n` since it is moot.
r? @steveklabnik
This renames `std::io::IoVec` to `std::io::IoSlice` and
`std::io::IoVecMut` to `std::io::IoSliceMut`, and stabilizes
`std::io::IoSlice`, `std::io::IoSliceMut`,
`std::io::Read::read_vectored`, and `std::io::Write::write_vectored`.
Closes#58452
Calling `Read::read` or `Write::write` without checking the returned
`usize` value is almost always an error. Example code in the
documentation should demonstrate how to use the return value correctly.
Otherwise, people might copy the example code thinking that it is okay
to "fire and forget" these methods.
Add provided methods `Seek::{stream_len, stream_position}`
This adds two new, provided methods to the `io::Seek` trait:
- `fn stream_len(&mut self) -> Result<u64>`
- `fn stream_position(&mut self) -> Result<u64>`
Both are added for convenience and to improve readability in user code. Reading `file.stream_len()` is much better than to manually seek two or three times. Similarly, `file.stream_position()` is much more clear than `file.seek(SeekFrom::Current(0))`.
You can find prior discussions [in this internals thread](https://internals.rust-lang.org/t/pre-rfc-idea-extend-io-seek-with-convenience-methods-with-e-g-stream-len/9262). I think I addressed all concerns in that thread.
I already wrote three RFCs to add a small new API to libstd but I noticed that many public changes to libstd happen without an RFC. So I figured I can try opening a PR directly without going through RFCs first. After all, we do have rfcbot here too. If you think this change is too big to merge without an RFC, I can still close this PR and write an RFC.
Add vectored read and write support
This functionality has lived for a while in the tokio ecosystem, where
it can improve performance by minimizing copies.
r? @alexcrichton
There are two big categories of changes in here
- Removing lifetimes from common traits that can essentially never user a lifetime from an input (particularly `Drop` & `Debug`)
- Forwarding impls that are only possible because the lifetime doesn't matter (like `impl<R: Read + ?Sized> Read for &mut R`)
I omitted things that seemed like they could be more controversial, like the handful of iterators that have a `Item: 'static` despite the iterator having a lifetime or the `PartialEq` implementations where the flipped one cannot elide the lifetime.
Fixed the link to the ? operator
I'm working on updating all broken links, but figured I'd break up the pull requests so they are easier to review, versus just one big pull request.
Defactored Bytes::read
Removed unneeded refactoring of read_one_byte, which removed the unneeded dynamic dispatch (`dyn Read`) used by that function.
This function is only used in one place in the entire Rust codebase; there doesn't seem to be a reason for it to exist (and there especially doesn't seem to be a reason for it to use dynamic dispatch)
The std::io::read main documentation can lead to error because the
buffer is prefilled with 10 zeros that will pad the response.
Using an empty vector is better.
The `read_to_end` documentation is already correct though.
This is my first rust PR, don't hesitate to tell me if I did something
wrong.