Repository: tokio-rs/tokio
File: tokio/src/fs/read_uring.rs (Rust)

Code before:

        // doesn't matter if we have a valid size_hint or not, if we do more
        // than 2 consecutive_short_reads, gradually increase the buffer
        // capacity to read more data at a time

        // prepare the spare capacity to be read into
        let spare = buf.capacity() - buf.len();
        let buf_len = cmp::min(spare, MAX_READ_SIZE);

        let mut read_len = {
            // SAFETY:
            // 1. buf_len cannot be greater than u32::MAX because max_read_size
            // is u32::MAX
            // 2. This is faster than a cast
            unsafe { TryInto::<u32>::try_into(buf_len).unwrap_unchecked() }
        };

        loop {
            // read into spare capacity
            let (res, r_fd, mut r_buf) = Op::read(fd, buf, read_len, offset).await;

            match res {
                Ok(size_read) => {
                    if size_read == 0 {
                        return Ok(r_buf);
                    }

                    let size_read_usize = size_read as usize;

                    let new_len = size_read_usize + r_buf.len();
                    // SAFETY: We didn't read more than what as reserved
                    // as capacity, the _size_read was initialized by the kernel
                    // via a mutable pointer
                    unsafe { r_buf.set_len(new_len) }

                    fd = r_fd;
                    buf = r_buf;
                    offset += size_read as u64;
                    read_len -= size_read;

                    // 1. In case of no size_hint and a large file, if we keep reading
                    // PROBE_SIZE, we want to increment number of short reads in order to gradually
                    // increase read size per Op submission
                    // 2. In case of small reads by the kernel, also gradually increase
                    // read size per Op submission to read files in lesser cycles
                    if size_read_usize <= buf.len() {
                        consecutive_short_reads += 1;
                    } else {
                        consecutive_short_reads = 0;
                    }


Review comment (suggestion):
```suggestion
                Ok(0) => return Ok(r_buf),
                Ok(size_read) => {
```

Code after:
    offset: &mut u64,
) -> io::Result<(OwnedFd, Vec<u8>, bool)> {
    let read_len = PROBE_SIZE_U32;

    let mut temp_arr = [0; PROBE_SIZE];
    // we don't call this function if buffer's length < PROBE_SIZE
    let back_bytes_len = buf.len() - PROBE_SIZE;

    temp_arr.copy_from_slice(&buf[back_bytes_len..]);

    // We're decreasing the length of the buffer and len is greater
    // than PROBE_SIZE. So we can read into the discarded length
    buf.truncate(back_bytes_len);

    let (r_fd, mut r_buf, is_eof) = op_read(fd, buf, offset, read_len).await?;
    // If `size_read` returns zero due to reasons such as buffer's exact fit,
    // then this `try_reserve` does not perform allocation.
    r_buf.try_reserve(PROBE_SIZE)?;
    r_buf.splice(back_bytes_len..back_bytes_len, temp_arr);

    Ok((r_fd, r_buf, is_eof))
}

// Takes a amount of length to read and returns a singluar read in the buffer
//
// Returns the file descriptor, buffer and EOF reached or not
async fn op_read(
    mut fd: OwnedFd,
    mut buf: Vec<u8>,
    offset: &mut u64,
    read_len: u32,
) -> io::Result<(OwnedFd, Vec<u8>, bool)> {
    loop {
        let (res, r_fd, r_buf) = Op::read(fd, buf, read_len, *offset).await;

        match res {
            Err(e) if e.kind() == ErrorKind::Interrupted => {
                buf = r_buf;
                fd = r_fd;
            }
            Err(e) => return Err(e),
            Ok(size_read) => {
                *offset += size_read as u64;

                return Ok((r_fd, r_buf, size_read == 0));
            }
        }
    }
}