Skip to content

Commit

Permalink
io: extend via Vec::set_len only after having read into it
Browse files Browse the repository at this point in the history
  • Loading branch information
paolobarbolini committed Jan 2, 2025
1 parent b3ff911 commit 8ec1726
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 14 deletions.
2 changes: 1 addition & 1 deletion tokio/src/fs/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ impl AsyncRead for File {
let std = me.std.clone();

inner.state = State::Busy(spawn_blocking(move || {
let res = buf.read_from(&mut &*std);
let res = unsafe { buf.read_from(&mut &*std) };
(Operation::Read(res), buf)
}));
}
Expand Down
27 changes: 14 additions & 13 deletions tokio/src/io/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::cmp;
use std::future::Future;
use std::io;
use std::io::prelude::*;
use std::mem::MaybeUninit;
use std::pin::Pin;
use std::task::{ready, Context, Poll};

Expand All @@ -21,6 +22,7 @@ pub(crate) struct Blocking<T> {
pub(crate) struct Buf {
buf: Vec<u8>,
pos: usize,
capacity: usize,
}

pub(crate) const DEFAULT_MAX_BUF_SIZE: usize = 2 * 1024 * 1024;
Expand Down Expand Up @@ -68,7 +70,7 @@ where
let mut inner = self.inner.take().unwrap();

self.state = State::Busy(sys::run(move || {
let res = buf.read_from(&mut inner);
let res = unsafe { buf.read_from(&mut inner) };
(res, buf, inner)
}));
}
Expand Down Expand Up @@ -190,6 +192,7 @@ impl Buf {
Buf {
buf: Vec::with_capacity(n),
pos: 0,
capacity: 0,
}
}

Expand Down Expand Up @@ -230,22 +233,20 @@ impl Buf {
pub(crate) fn ensure_capacity_for(&mut self, bytes: &ReadBuf<'_>, max_buf_size: usize) {
assert!(self.is_empty());

let len = cmp::min(bytes.remaining(), max_buf_size);

if self.buf.len() < len {
self.buf.reserve(len - self.buf.len());
}

unsafe {
self.buf.set_len(len);
}
let capacity = cmp::min(bytes.remaining(), max_buf_size);
self.buf.reserve(capacity);
self.capacity = capacity;
}

pub(crate) fn read_from<T: Read>(&mut self, rd: &mut T) -> io::Result<usize> {
let res = uninterruptibly!(rd.read(&mut self.buf));
/// Safety: `rd` must not read from the buffer passed to `read` and
/// must correctly report the length of the written portion of the buffer.
pub(crate) unsafe fn read_from<T: Read>(&mut self, rd: &mut T) -> io::Result<usize> {
let buf = &mut self.buf.spare_capacity_mut()[..self.capacity - self.pos];
let buf = unsafe { &mut *(buf as *mut [MaybeUninit<u8>] as *mut [u8]) };
let res = uninterruptibly!(rd.read(buf));

if let Ok(n) = res {
self.buf.truncate(n);
unsafe { self.buf.set_len(n) }
} else {
self.buf.clear();
}
Expand Down

0 comments on commit 8ec1726

Please sign in to comment.