From 91aa36c1209c4d877d98aedbac626c7996d25b5e Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 7 Nov 2024 09:00:52 -0700 Subject: [PATCH] Clean up VFS error handling --- src/vfs/disc.rs | 18 ++++++++++-------- src/vfs/std_fs.rs | 24 +++++++++++++----------- src/vfs/wad.rs | 45 ++++++++++++++++++++++++++------------------- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/vfs/disc.rs b/src/vfs/disc.rs index da2c4fb..fec18c1 100644 --- a/src/vfs/disc.rs +++ b/src/vfs/disc.rs @@ -10,7 +10,7 @@ use nodtool::{ nod::{Disc, DiscStream, Fst, NodeKind, OwnedFileStream, PartitionBase, PartitionMeta}, }; use typed_path::Utf8UnixPath; -use zerocopy::IntoBytes; +use zerocopy::{FromZeros, IntoBytes}; use super::{ next_non_empty, StaticFile, Vfs, VfsError, VfsFile, VfsFileType, VfsMetadata, VfsResult, @@ -252,19 +252,21 @@ impl DiscFile { Self { inner: DiscFileInner::Stream(file), mtime } } - fn convert_to_mapped(&mut self) { + fn convert_to_mapped(&mut self) -> io::Result<()> { match &mut self.inner { DiscFileInner::Stream(stream) => { - let pos = stream.stream_position().unwrap(); - stream.seek(SeekFrom::Start(0)).unwrap(); - let mut data = vec![0u8; stream.len() as usize]; - stream.read_exact(&mut data).unwrap(); - let mut cursor = Cursor::new(Arc::from(data.as_slice())); + let pos = stream.stream_position()?; + stream.seek(SeekFrom::Start(0))?; + let mut data = <[u8]>::new_box_zeroed_with_elems(stream.len() as usize) + .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + stream.read_exact(&mut data)?; + let mut cursor = Cursor::new(Arc::from(data)); cursor.set_position(pos); self.inner = DiscFileInner::Mapped(cursor); } DiscFileInner::Mapped(_) => {} }; + Ok(()) } } @@ -304,7 +306,7 @@ impl Seek for DiscFile { impl VfsFile for DiscFile { fn map(&mut self) -> io::Result<&[u8]> { - self.convert_to_mapped(); + self.convert_to_mapped()?; match &mut self.inner { DiscFileInner::Stream(_) => unreachable!(), DiscFileInner::Mapped(data) => Ok(data.get_ref()), diff --git a/src/vfs/std_fs.rs b/src/vfs/std_fs.rs index 9d0c40d..3a75b64 100644 --- a/src/vfs/std_fs.rs +++ b/src/vfs/std_fs.rs @@ -55,10 +55,10 @@ impl StdFile { pub fn new(path: Utf8NativePathBuf) -> Self { StdFile { path, file: None, mmap: None } } pub fn file(&mut self) -> io::Result<&mut BufReader> { - if self.file.is_none() { - self.file = Some(BufReader::new(fs::File::open(&self.path)?)); - } - Ok(self.file.as_mut().unwrap()) + Ok(match self.file { + Some(ref mut file) => file, + None => self.file.insert(BufReader::new(fs::File::open(&self.path)?)), + }) } } @@ -86,13 +86,15 @@ impl Seek for StdFile { impl VfsFile for StdFile { fn map(&mut self) -> io::Result<&[u8]> { - if self.file.is_none() { - self.file = Some(BufReader::new(fs::File::open(&self.path)?)); - } - if self.mmap.is_none() { - self.mmap = Some(unsafe { memmap2::Mmap::map(self.file.as_ref().unwrap().get_ref())? }); - } - Ok(self.mmap.as_ref().unwrap()) + let file = match self.file { + Some(ref mut file) => file, + None => self.file.insert(BufReader::new(fs::File::open(&self.path)?)), + }; + let mmap = match self.mmap { + Some(ref mmap) => mmap, + None => self.mmap.insert(unsafe { memmap2::Mmap::map(file.get_ref())? }), + }; + Ok(mmap) } fn metadata(&mut self) -> io::Result { diff --git a/src/vfs/wad.rs b/src/vfs/wad.rs index 0bed0ec..e106874 100644 --- a/src/vfs/wad.rs +++ b/src/vfs/wad.rs @@ -23,6 +23,7 @@ use crate::{ pub struct WadFs { file: Box, wad: WadFile, + mtime: Option, } enum WadFindResult<'a> { @@ -34,9 +35,10 @@ enum WadFindResult<'a> { impl WadFs { pub fn new(mut file: Box) -> io::Result { + let mtime = file.metadata()?.mtime; let wad = process_wad(file.as_mut()) .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; - Ok(Self { file, wad }) + Ok(Self { file, wad, mtime }) } fn find(&self, path: &str) -> Option { @@ -81,7 +83,7 @@ impl Vfs for WadFs { match result { WadFindResult::Root => Err(VfsError::IsADirectory), WadFindResult::Static(data) => { - Ok(Box::new(StaticFile::new(Arc::from(data), self.file.metadata()?.mtime))) + Ok(Box::new(StaticFile::new(Arc::from(data), self.mtime))) } WadFindResult::Content(content_index, content) => { let offset = self.wad.content_offset(content_index); @@ -93,7 +95,7 @@ impl Vfs for WadFs { &self.wad.title_key, &content.iv(), ), - self.file.metadata()?.mtime, + self.mtime, ))) } WadFindResult::Window(offset, len) => { @@ -129,20 +131,23 @@ impl Vfs for WadFs { } fn metadata(&mut self, path: &Utf8UnixPath) -> VfsResult { - let mtime = self.file.metadata()?.mtime; if let Some(result) = self.find(path.as_str()) { match result { WadFindResult::Root => { - Ok(VfsMetadata { file_type: VfsFileType::Directory, len: 0, mtime }) - } - WadFindResult::Static(data) => { - Ok(VfsMetadata { file_type: VfsFileType::File, len: data.len() as u64, mtime }) - } - WadFindResult::Content(_, content) => { - Ok(VfsMetadata { file_type: VfsFileType::File, len: content.size.get(), mtime }) + Ok(VfsMetadata { file_type: VfsFileType::Directory, len: 0, mtime: self.mtime }) } + WadFindResult::Static(data) => Ok(VfsMetadata { + file_type: VfsFileType::File, + len: data.len() as u64, + mtime: self.mtime, + }), + WadFindResult::Content(_, content) => Ok(VfsMetadata { + file_type: VfsFileType::File, + len: content.size.get(), + mtime: self.mtime, + }), WadFindResult::Window(_, len) => { - Ok(VfsMetadata { file_type: VfsFileType::File, len, mtime }) + Ok(VfsMetadata { file_type: VfsFileType::File, len, mtime: self.mtime }) } } } else { @@ -168,19 +173,21 @@ impl WadContent { Self { inner: WadContentInner::Stream(inner), mtime } } - fn convert_to_mapped(&mut self) { + fn convert_to_mapped(&mut self) -> io::Result<()> { match &mut self.inner { WadContentInner::Stream(stream) => { - let pos = stream.stream_position().unwrap(); - stream.seek(SeekFrom::Start(0)).unwrap(); - let mut data = vec![0u8; stream.len() as usize]; - stream.read_exact(&mut data).unwrap(); - let mut cursor = Cursor::new(Arc::from(data.as_slice())); + let pos = stream.stream_position()?; + stream.seek(SeekFrom::Start(0))?; + let mut data = <[u8]>::new_box_zeroed_with_elems(stream.len() as usize) + .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?; + stream.read_exact(&mut data)?; + let mut cursor = Cursor::new(Arc::from(data)); cursor.set_position(pos); self.inner = WadContentInner::Mapped(cursor); } WadContentInner::Mapped(_) => {} }; + Ok(()) } } @@ -220,7 +227,7 @@ impl Seek for WadContent { impl VfsFile for WadContent { fn map(&mut self) -> io::Result<&[u8]> { - self.convert_to_mapped(); + self.convert_to_mapped()?; match &mut self.inner { WadContentInner::Stream(_) => unreachable!(), WadContentInner::Mapped(data) => Ok(data.get_ref()),