Skip to content

Commit 3c478cb

Browse files
committed
std::io::Take: Clarify & optimize BorrowedBuf::set_init usage.
Don't initialize `buf` if it was already initialized. Move the `buf.advance()` call to make the initialization more like calling `buf.ensure_init()`, then clarify how the code here is an optimized variant of `ensure_init`.
1 parent 12f35ad commit 3c478cb

1 file changed

Lines changed: 10 additions & 7 deletions

File tree

library/std/src/io/mod.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3095,14 +3095,22 @@ impl<T: Read> Read for Take<T> {
30953095
let mut cursor = sliced_buf.unfilled();
30963096
let result = self.inner.read_buf(cursor.reborrow());
30973097

3098-
let should_init = cursor.is_init();
3098+
let is_init_up_to_limit = cursor.is_init();
30993099
let filled = sliced_buf.len();
31003100

31013101
// cursor / sliced_buf / ibuf must drop here
31023102

3103+
unsafe {
3104+
// SAFETY: filled bytes have been filled
3105+
buf.advance(filled);
3106+
}
3107+
31033108
// Avoid accidentally quadratic behaviour by initializing the whole
31043109
// cursor if only part of it was initialized.
3105-
if should_init {
3110+
if is_init_up_to_limit && !is_init {
3111+
// `buf.ensure_init()` would work, but it would additionally
3112+
// re-initialize `buf.as_mut()[buf.len()..limit]`.
3113+
31063114
// SAFETY: no uninit data is written
31073115
let uninit = unsafe { &mut buf.as_mut()[limit..] };
31083116
uninit.write_filled(0);
@@ -3111,11 +3119,6 @@ impl<T: Read> Read for Take<T> {
31113119
unsafe { buf.set_init() };
31123120
}
31133121

3114-
unsafe {
3115-
// SAFETY: filled bytes have been filled
3116-
buf.advance(filled);
3117-
}
3118-
31193122
self.limit -= filled as u64;
31203123

31213124
result

0 commit comments

Comments
 (0)