From d32ae0eef98c5bfda404b1daba9b3525e50d528c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Harabie=C5=84?= Date: Sat, 7 Oct 2017 16:07:33 +0200 Subject: [PATCH] Allow seeking beyond end of file as documented in Seek trait. Also fix possible panic when seeking in file without clusters. --- src/file.rs | 22 +++++++++++++++------- tests/integration-test.rs | 8 ++++++-- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/file.rs b/src/file.rs index f893541..24dd077 100644 --- a/src/file.rs +++ b/src/file.rs @@ -29,15 +29,18 @@ impl <'a, 'b> Read for File<'a, 'b> { let mut buf_offset: usize = 0; let cluster_size = self.fs.get_cluster_size(); loop { + let current_cluster = match self.current_cluster { + Some(n) => n, + None => break, + }; let offset_in_cluster = self.offset % cluster_size; let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize; let bytes_left_in_file = self.size.map(|size| (size - self.offset) as usize).unwrap_or(bytes_left_in_cluster); let bytes_left_in_buf = buf.len() - buf_offset; let read_size = cmp::min(cmp::min(bytes_left_in_buf, bytes_left_in_cluster), bytes_left_in_file); - if read_size == 0 || self.current_cluster.is_none() { + if read_size == 0 { break; } - let current_cluster = self.current_cluster.unwrap(); let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64); let read_bytes = { let mut rdr = self.fs.rdr.borrow_mut(); @@ -67,17 +70,22 @@ impl <'a, 'b> Seek for File<'a, 'b> { let new_offset = match pos { SeekFrom::Current(x) => self.offset as i64 + x, SeekFrom::Start(x) => x as i64, - SeekFrom::End(x) => self.size.unwrap() as i64 + x, + SeekFrom::End(x) => self.size.expect("cannot seek from end if size is unknown") as i64 + x, }; - if new_offset < 0 || (self.size.is_some() && new_offset as u64 > self.size.unwrap() as u64) { + if new_offset < 0 { return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek")); } let cluster_size = self.fs.get_cluster_size(); let cluster_count = (new_offset / cluster_size as i64) as usize; let new_cluster = if cluster_count > 0 { - match self.fs.cluster_iter(self.first_cluster.unwrap()).skip(cluster_count).next() { - Some(Err(err)) => return Err(err), - Some(Ok(n)) => Some(n), + match self.first_cluster { + Some(n) => { + match self.fs.cluster_iter(n).skip(cluster_count).next() { + Some(Err(err)) => return Err(err), + Some(Ok(n)) => Some(n), + None => None, + } + }, None => None, } } else { diff --git a/tests/integration-test.rs b/tests/integration-test.rs index d83465a..135e7fb 100644 --- a/tests/integration-test.rs +++ b/tests/integration-test.rs @@ -53,10 +53,14 @@ fn test_read_seek_short_file(fs: FileSystem) { short_file.read_to_end(&mut buf).unwrap(); assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT); - short_file.seek(SeekFrom::Start(5)).unwrap(); + assert_eq!(short_file.seek(SeekFrom::Start(5)).unwrap(), 5); let mut buf2 = [0; 5]; short_file.read_exact(&mut buf2).unwrap(); assert_eq!(str::from_utf8(&buf2).unwrap(), &TEST_TEXT[5..10]); + + assert_eq!(short_file.seek(SeekFrom::Start(1000)).unwrap(), 1000); + let mut buf2 = [0; 5]; + assert_eq!(short_file.read(&mut buf2).unwrap(), 0); } #[test] @@ -81,7 +85,7 @@ fn test_read_long_file(fs: FileSystem) { long_file.read_to_end(&mut buf).unwrap(); assert_eq!(str::from_utf8(&buf).unwrap(), TEST_TEXT.repeat(1000)); - long_file.seek(SeekFrom::Start(2017)).unwrap(); + assert_eq!(long_file.seek(SeekFrom::Start(2017)).unwrap(), 2017); buf.clear(); let mut buf2 = [0; 10]; long_file.read_exact(&mut buf2).unwrap();