Skip to content

Commit 5bea81c

Browse files
authored
Rollup merge of rust-lang#122441 - a1phyr:improve_read_impls, r=ChrisDenton
Improve several `Read` implementations - `read_to_end` and `read_to_string` for `Cursor` - Error on OOM in `read_to_string` of `&[u8]` and `VecDeque<u8>` - Avoid making the slices contiguous in `VecDeque::read_to_string` - ~`read_exact` and (unstable) `read_buf_exact` for `Take`~ - ~`read_buf` for `UnixStream` and `&UnixStream`~ (moved to rust-lang#123084) - `read_to_end` for `ChildStdErr`
2 parents 22d5776 + f804284 commit 5bea81c

File tree

4 files changed

+33
-10
lines changed

4 files changed

+33
-10
lines changed

Diff for: std/src/io/cursor.rs

+21
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,27 @@ where
364364
self.pos += n as u64;
365365
Ok(())
366366
}
367+
368+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
369+
let content = self.remaining_slice();
370+
let len = content.len();
371+
buf.try_reserve(len)?;
372+
buf.extend_from_slice(content);
373+
self.pos += len as u64;
374+
375+
Ok(len)
376+
}
377+
378+
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
379+
let content =
380+
crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
381+
let len = content.len();
382+
buf.try_reserve(len)?;
383+
buf.push_str(content);
384+
self.pos += len as u64;
385+
386+
Ok(len)
387+
}
367388
}
368389

369390
#[stable(feature = "rust1", since = "1.0.0")]

Diff for: std/src/io/impls.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,9 @@ impl Read for &[u8] {
329329
#[inline]
330330
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
331331
let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?;
332-
buf.push_str(content);
333332
let len = self.len();
333+
buf.try_reserve(len)?;
334+
buf.push_str(content);
334335
*self = &self[len..];
335336
Ok(len)
336337
}
@@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {
473474

474475
#[inline]
475476
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
476-
// We have to use a single contiguous slice because the `VecDequeue` might be split in the
477-
// middle of an UTF-8 character.
478-
let len = self.len();
479-
let content = self.make_contiguous();
480-
let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?;
481-
buf.push_str(string);
482-
self.clear();
483-
Ok(len)
477+
// SAFETY: We only append to the buffer
478+
unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) }
484479
}
485480
}
486481

Diff for: std/src/io/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,10 @@ where
384384
{
385385
let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
386386
let ret = f(g.buf);
387-
if str::from_utf8(&g.buf[g.len..]).is_err() {
387+
388+
// SAFETY: the caller promises to only append data to `buf`
389+
let appended = g.buf.get_unchecked(g.len..);
390+
if str::from_utf8(appended).is_err() {
388391
ret.and_then(|_| Err(Error::INVALID_UTF8))
389392
} else {
390393
g.len = g.buf.len();

Diff for: std/src/process.rs

+4
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,10 @@ impl Read for ChildStderr {
486486
fn is_read_vectored(&self) -> bool {
487487
self.inner.is_read_vectored()
488488
}
489+
490+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
491+
self.inner.read_to_end(buf)
492+
}
489493
}
490494

491495
impl AsInner<AnonPipe> for ChildStderr {

0 commit comments

Comments
 (0)