Skip to content

Commit 31043a5

Browse files
committed
Use try_reserve in Vec's io::Write
1 parent 2b91cbe commit 31043a5

File tree

1 file changed

+27
-2
lines changed

1 file changed

+27
-2
lines changed

library/std/src/io/impls.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,18 +377,28 @@ impl Write for &mut [u8] {
377377

378378
/// Write is implemented for `Vec<u8>` by appending to the vector.
379379
/// The vector will grow as needed.
380+
///
381+
/// # Panics
382+
///
383+
/// In case of allocation error or capacity overflow, write operations will panic.
384+
/// The panicking behavior is not guaranteed. In the future, it may become
385+
/// a regular `io::Error`.
380386
#[stable(feature = "rust1", since = "1.0.0")]
381387
impl<A: Allocator> Write for Vec<u8, A> {
382388
#[inline]
383389
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
390+
fallible_reserve(self, buf.len());
384391
self.extend_from_slice(buf);
385392
Ok(buf.len())
386393
}
387394

388395
#[inline]
389396
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
390-
let len = bufs.iter().map(|b| b.len()).sum();
391-
self.reserve(len);
397+
let len = bufs
398+
.iter()
399+
.try_fold(0usize, |len, b| len.checked_add(b.len()))
400+
.expect("capacity overflow");
401+
fallible_reserve(self, len);
392402
for buf in bufs {
393403
self.extend_from_slice(buf);
394404
}
@@ -402,6 +412,7 @@ impl<A: Allocator> Write for Vec<u8, A> {
402412

403413
#[inline]
404414
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
415+
fallible_reserve(self, buf.len());
405416
self.extend_from_slice(buf);
406417
Ok(())
407418
}
@@ -412,6 +423,20 @@ impl<A: Allocator> Write for Vec<u8, A> {
412423
}
413424
}
414425

426+
#[inline]
427+
fn fallible_reserve<T, A: Allocator>(vec: &mut Vec<T, A>, len: usize) {
428+
if len > vec.capacity().wrapping_sub(vec.len()) {
429+
do_reserve_and_handle(vec, len);
430+
}
431+
}
432+
433+
#[cold]
434+
fn do_reserve_and_handle<T, A: Allocator>(vec: &mut Vec<T, A>, len: usize) {
435+
if let Err(_) = vec.try_reserve(len) {
436+
panic!("out of memory");
437+
}
438+
}
439+
415440
/// Read is implemented for `VecDeque<u8>` by consuming bytes from the front of the `VecDeque`.
416441
#[stable(feature = "vecdeque_read_write", since = "1.63.0")]
417442
impl<A: Allocator> Read for VecDeque<u8, A> {

0 commit comments

Comments
 (0)