diff --git a/src/fs/file.rs b/src/fs/file.rs index 9cd47f21..bf3f561f 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -444,6 +444,35 @@ impl File { (Ok(()), buf.into_inner()) } + /// Fills a vector with the contents of the file + /// from the given position to the end + /// + /// If this function encounters any form of I/O or other error, an error + /// variant will be returned. + /// On error the buffer will contain the partial data that was + /// read up until this point. + pub async fn read_at_to_end( + &self, + mut pos: u64, + mut result: Vec, + ) -> crate::BufResult<(), Vec> { + let mut buffer = vec![0u8; 4096]; + + loop { + let (res, buf) = self.read_at(buffer, pos).await; + + match res { + Ok(0) => return (Ok(()), result), + Ok(n) => { + buffer = buf; + result.extend_from_slice(&buffer[..n]); + pos += n as u64; + } + Err(err) => return (Err(err), result), + } + } + } + /// Like [`read_at`], but using a pre-mapped buffer /// registered with [`FixedBufRegistry`]. /// diff --git a/tests/fs_file.rs b/tests/fs_file.rs index 096565e6..ec9d15e0 100644 --- a/tests/fs_file.rs +++ b/tests/fs_file.rs @@ -35,6 +35,23 @@ fn basic_read() { }); } +#[test] +fn read_exact_buf_too_long() { + tokio_uring::start(async { + let data = HELLO.repeat(1); + let buf = Vec::with_capacity(data.len() * 2); + + let mut tempfile = tempfile(); + tempfile.write_all(&data).unwrap(); + + let file = File::open(tempfile.path()).await.unwrap(); + let (res, _buf) = file.read_exact_at(buf, 0).await; + + assert!(res.is_err()); + assert_eq!(res.unwrap_err().kind(), std::io::ErrorKind::UnexpectedEof); + }); +} + #[test] fn basic_read_exact() { tokio_uring::start(async { @@ -51,6 +68,23 @@ fn basic_read_exact() { }); } +#[test] +fn basic_read_to_end() { + tokio_uring::start(async { + let data = HELLO.repeat(1); + + let mut tempfile = tempfile(); + tempfile.write_all(&data).unwrap(); + + let file = File::open(tempfile.path()).await.unwrap(); + + let buf = vec![]; + let (res, buf) = file.read_at_to_end(0, buf).await; + res.unwrap(); + assert_eq!(buf, data); + }); +} + #[test] fn basic_write() { tokio_uring::start(async {