diff options
Diffstat (limited to 'buffered-reader/src/file_unix.rs')
-rw-r--r-- | buffered-reader/src/file_unix.rs | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/buffered-reader/src/file_unix.rs b/buffered-reader/src/file_unix.rs index 2162f7d1..7bc8b855 100644 --- a/buffered-reader/src/file_unix.rs +++ b/buffered-reader/src/file_unix.rs @@ -10,10 +10,11 @@ use std::fs; use std::io; use std::os::unix::io::AsRawFd; use std::slice; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::ptr; use super::*; +use crate::file_error::FileError; // For small files, the overhead of manipulating the page table is not // worth the gain. This threshold has been chosen so that on my @@ -24,11 +25,11 @@ const MMAP_THRESHOLD: u64 = 16 * 4096; /// /// This implementation tries to mmap the file, falling back to /// just using a generic reader. -pub struct File<'a, C>(Imp<'a, C>); +pub struct File<'a, C>(Imp<'a, C>, PathBuf); impl<'a, C> fmt::Display for File<'a, C> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) + write!(f, "{} {:?}", self.0, self.1.display()) } } @@ -36,6 +37,7 @@ impl<'a, C> fmt::Debug for File<'a, C> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_tuple("File") .field(&self.0) + .field(&self.1) .finish() } } @@ -100,14 +102,17 @@ impl<'a> File<'a, ()> { impl<'a, C> File<'a, C> { /// Like `open()`, but sets a cookie. pub fn with_cookie<P: AsRef<Path>>(path: P, cookie: C) -> io::Result<Self> { + let path = path.as_ref(); + // As fallback, we use a generic reader. let generic = |file, cookie| { Ok(File( Imp::Generic( - Generic::with_cookie(file, None, cookie)))) + Generic::with_cookie(file, None, cookie)), + path.into())) }; - let file = fs::File::open(path)?; + let file = fs::File::open(path).map_err(|e| FileError::new(path, e))?; // For testing and benchmarking purposes, we use the variable // SEQUOIA_DONT_MMAP to turn off mmapping. @@ -115,7 +120,8 @@ impl<'a, C> File<'a, C> { return generic(file, cookie); } - let length = file.metadata()?.len(); + let length = + file.metadata().map_err(|e| FileError::new(path, e))?.len(); // For small files, the overhead of manipulating the page // table is not worth the gain. @@ -147,7 +153,8 @@ impl<'a, C> File<'a, C> { addr, length, reader: Memory::with_cookie(slice, cookie), - } + }, + path.into(), )) } } @@ -157,7 +164,7 @@ impl<'a, C> io::Read for File<'a, C> { match self.0 { Imp::Generic(ref mut reader) => reader.read(buf), Imp::MMAP { ref mut reader, .. } => reader.read(buf), - } + }.map_err(|e| FileError::new(&self.1, e)) } } @@ -170,17 +177,19 @@ impl<'a, C> BufferedReader<C> for File<'a, C> { } fn data(&mut self, amount: usize) -> io::Result<&[u8]> { + let path = &self.1; match self.0 { Imp::Generic(ref mut reader) => reader.data(amount), Imp::MMAP { ref mut reader, .. } => reader.data(amount), - } + }.map_err(|e| FileError::new(path, e)) } fn data_hard(&mut self, amount: usize) -> io::Result<&[u8]> { + let path = &self.1; match self.0 { Imp::Generic(ref mut reader) => reader.data_hard(amount), Imp::MMAP { ref mut reader, .. } => reader.data_hard(amount), - } + }.map_err(|e| FileError::new(path, e)) } fn consume(&mut self, amount: usize) -> &[u8] { @@ -191,17 +200,19 @@ impl<'a, C> BufferedReader<C> for File<'a, C> { } fn data_consume(&mut self, amount: usize) -> io::Result<&[u8]> { + let path = &self.1; match self.0 { Imp::Generic(ref mut reader) => reader.data_consume(amount), Imp::MMAP { ref mut reader, .. } => reader.data_consume(amount), - } + }.map_err(|e| FileError::new(path, e)) } fn data_consume_hard(&mut self, amount: usize) -> io::Result<&[u8]> { + let path = &self.1; match self.0 { Imp::Generic(ref mut reader) => reader.data_consume_hard(amount), Imp::MMAP { ref mut reader, .. } => reader.data_consume_hard(amount), - } + }.map_err(|e| FileError::new(path, e)) } fn get_mut(&mut self) -> Option<&mut dyn BufferedReader<C>> { @@ -238,3 +249,15 @@ impl<'a, C> BufferedReader<C> for File<'a, C> { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn error_contains_path() { + let p = "/i/do/not/exist"; + let e = File::open(p).unwrap_err(); + assert!(e.to_string().contains(p)); + } +} |