Clean up VFS error handling
This commit is contained in:
parent
9fc56d847f
commit
91aa36c120
|
@ -10,7 +10,7 @@ use nodtool::{
|
||||||
nod::{Disc, DiscStream, Fst, NodeKind, OwnedFileStream, PartitionBase, PartitionMeta},
|
nod::{Disc, DiscStream, Fst, NodeKind, OwnedFileStream, PartitionBase, PartitionMeta},
|
||||||
};
|
};
|
||||||
use typed_path::Utf8UnixPath;
|
use typed_path::Utf8UnixPath;
|
||||||
use zerocopy::IntoBytes;
|
use zerocopy::{FromZeros, IntoBytes};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
next_non_empty, StaticFile, Vfs, VfsError, VfsFile, VfsFileType, VfsMetadata, VfsResult,
|
next_non_empty, StaticFile, Vfs, VfsError, VfsFile, VfsFileType, VfsMetadata, VfsResult,
|
||||||
|
@ -252,19 +252,21 @@ impl DiscFile {
|
||||||
Self { inner: DiscFileInner::Stream(file), mtime }
|
Self { inner: DiscFileInner::Stream(file), mtime }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_to_mapped(&mut self) {
|
fn convert_to_mapped(&mut self) -> io::Result<()> {
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
DiscFileInner::Stream(stream) => {
|
DiscFileInner::Stream(stream) => {
|
||||||
let pos = stream.stream_position().unwrap();
|
let pos = stream.stream_position()?;
|
||||||
stream.seek(SeekFrom::Start(0)).unwrap();
|
stream.seek(SeekFrom::Start(0))?;
|
||||||
let mut data = vec![0u8; stream.len() as usize];
|
let mut data = <[u8]>::new_box_zeroed_with_elems(stream.len() as usize)
|
||||||
stream.read_exact(&mut data).unwrap();
|
.map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
|
||||||
let mut cursor = Cursor::new(Arc::from(data.as_slice()));
|
stream.read_exact(&mut data)?;
|
||||||
|
let mut cursor = Cursor::new(Arc::from(data));
|
||||||
cursor.set_position(pos);
|
cursor.set_position(pos);
|
||||||
self.inner = DiscFileInner::Mapped(cursor);
|
self.inner = DiscFileInner::Mapped(cursor);
|
||||||
}
|
}
|
||||||
DiscFileInner::Mapped(_) => {}
|
DiscFileInner::Mapped(_) => {}
|
||||||
};
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +306,7 @@ impl Seek for DiscFile {
|
||||||
|
|
||||||
impl VfsFile for DiscFile {
|
impl VfsFile for DiscFile {
|
||||||
fn map(&mut self) -> io::Result<&[u8]> {
|
fn map(&mut self) -> io::Result<&[u8]> {
|
||||||
self.convert_to_mapped();
|
self.convert_to_mapped()?;
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
DiscFileInner::Stream(_) => unreachable!(),
|
DiscFileInner::Stream(_) => unreachable!(),
|
||||||
DiscFileInner::Mapped(data) => Ok(data.get_ref()),
|
DiscFileInner::Mapped(data) => Ok(data.get_ref()),
|
||||||
|
|
|
@ -55,10 +55,10 @@ impl StdFile {
|
||||||
pub fn new(path: Utf8NativePathBuf) -> Self { StdFile { path, file: None, mmap: None } }
|
pub fn new(path: Utf8NativePathBuf) -> Self { StdFile { path, file: None, mmap: None } }
|
||||||
|
|
||||||
pub fn file(&mut self) -> io::Result<&mut BufReader<fs::File>> {
|
pub fn file(&mut self) -> io::Result<&mut BufReader<fs::File>> {
|
||||||
if self.file.is_none() {
|
Ok(match self.file {
|
||||||
self.file = Some(BufReader::new(fs::File::open(&self.path)?));
|
Some(ref mut file) => file,
|
||||||
}
|
None => self.file.insert(BufReader::new(fs::File::open(&self.path)?)),
|
||||||
Ok(self.file.as_mut().unwrap())
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,13 +86,15 @@ impl Seek for StdFile {
|
||||||
|
|
||||||
impl VfsFile for StdFile {
|
impl VfsFile for StdFile {
|
||||||
fn map(&mut self) -> io::Result<&[u8]> {
|
fn map(&mut self) -> io::Result<&[u8]> {
|
||||||
if self.file.is_none() {
|
let file = match self.file {
|
||||||
self.file = Some(BufReader::new(fs::File::open(&self.path)?));
|
Some(ref mut file) => file,
|
||||||
}
|
None => self.file.insert(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())? });
|
let mmap = match self.mmap {
|
||||||
}
|
Some(ref mmap) => mmap,
|
||||||
Ok(self.mmap.as_ref().unwrap())
|
None => self.mmap.insert(unsafe { memmap2::Mmap::map(file.get_ref())? }),
|
||||||
|
};
|
||||||
|
Ok(mmap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&mut self) -> io::Result<VfsMetadata> {
|
fn metadata(&mut self) -> io::Result<VfsMetadata> {
|
||||||
|
|
|
@ -23,6 +23,7 @@ use crate::{
|
||||||
pub struct WadFs {
|
pub struct WadFs {
|
||||||
file: Box<dyn VfsFile>,
|
file: Box<dyn VfsFile>,
|
||||||
wad: WadFile,
|
wad: WadFile,
|
||||||
|
mtime: Option<FileTime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum WadFindResult<'a> {
|
enum WadFindResult<'a> {
|
||||||
|
@ -34,9 +35,10 @@ enum WadFindResult<'a> {
|
||||||
|
|
||||||
impl WadFs {
|
impl WadFs {
|
||||||
pub fn new(mut file: Box<dyn VfsFile>) -> io::Result<Self> {
|
pub fn new(mut file: Box<dyn VfsFile>) -> io::Result<Self> {
|
||||||
|
let mtime = file.metadata()?.mtime;
|
||||||
let wad = process_wad(file.as_mut())
|
let wad = process_wad(file.as_mut())
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
.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<WadFindResult> {
|
fn find(&self, path: &str) -> Option<WadFindResult> {
|
||||||
|
@ -81,7 +83,7 @@ impl Vfs for WadFs {
|
||||||
match result {
|
match result {
|
||||||
WadFindResult::Root => Err(VfsError::IsADirectory),
|
WadFindResult::Root => Err(VfsError::IsADirectory),
|
||||||
WadFindResult::Static(data) => {
|
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) => {
|
WadFindResult::Content(content_index, content) => {
|
||||||
let offset = self.wad.content_offset(content_index);
|
let offset = self.wad.content_offset(content_index);
|
||||||
|
@ -93,7 +95,7 @@ impl Vfs for WadFs {
|
||||||
&self.wad.title_key,
|
&self.wad.title_key,
|
||||||
&content.iv(),
|
&content.iv(),
|
||||||
),
|
),
|
||||||
self.file.metadata()?.mtime,
|
self.mtime,
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
WadFindResult::Window(offset, len) => {
|
WadFindResult::Window(offset, len) => {
|
||||||
|
@ -129,20 +131,23 @@ impl Vfs for WadFs {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata(&mut self, path: &Utf8UnixPath) -> VfsResult<VfsMetadata> {
|
fn metadata(&mut self, path: &Utf8UnixPath) -> VfsResult<VfsMetadata> {
|
||||||
let mtime = self.file.metadata()?.mtime;
|
|
||||||
if let Some(result) = self.find(path.as_str()) {
|
if let Some(result) = self.find(path.as_str()) {
|
||||||
match result {
|
match result {
|
||||||
WadFindResult::Root => {
|
WadFindResult::Root => {
|
||||||
Ok(VfsMetadata { file_type: VfsFileType::Directory, len: 0, 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 })
|
|
||||||
}
|
|
||||||
WadFindResult::Content(_, content) => {
|
|
||||||
Ok(VfsMetadata { file_type: VfsFileType::File, len: content.size.get(), 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) => {
|
WadFindResult::Window(_, len) => {
|
||||||
Ok(VfsMetadata { file_type: VfsFileType::File, len, mtime })
|
Ok(VfsMetadata { file_type: VfsFileType::File, len, mtime: self.mtime })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,19 +173,21 @@ impl WadContent {
|
||||||
Self { inner: WadContentInner::Stream(inner), mtime }
|
Self { inner: WadContentInner::Stream(inner), mtime }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_to_mapped(&mut self) {
|
fn convert_to_mapped(&mut self) -> io::Result<()> {
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
WadContentInner::Stream(stream) => {
|
WadContentInner::Stream(stream) => {
|
||||||
let pos = stream.stream_position().unwrap();
|
let pos = stream.stream_position()?;
|
||||||
stream.seek(SeekFrom::Start(0)).unwrap();
|
stream.seek(SeekFrom::Start(0))?;
|
||||||
let mut data = vec![0u8; stream.len() as usize];
|
let mut data = <[u8]>::new_box_zeroed_with_elems(stream.len() as usize)
|
||||||
stream.read_exact(&mut data).unwrap();
|
.map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
|
||||||
let mut cursor = Cursor::new(Arc::from(data.as_slice()));
|
stream.read_exact(&mut data)?;
|
||||||
|
let mut cursor = Cursor::new(Arc::from(data));
|
||||||
cursor.set_position(pos);
|
cursor.set_position(pos);
|
||||||
self.inner = WadContentInner::Mapped(cursor);
|
self.inner = WadContentInner::Mapped(cursor);
|
||||||
}
|
}
|
||||||
WadContentInner::Mapped(_) => {}
|
WadContentInner::Mapped(_) => {}
|
||||||
};
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +227,7 @@ impl Seek for WadContent {
|
||||||
|
|
||||||
impl VfsFile for WadContent {
|
impl VfsFile for WadContent {
|
||||||
fn map(&mut self) -> io::Result<&[u8]> {
|
fn map(&mut self) -> io::Result<&[u8]> {
|
||||||
self.convert_to_mapped();
|
self.convert_to_mapped()?;
|
||||||
match &mut self.inner {
|
match &mut self.inner {
|
||||||
WadContentInner::Stream(_) => unreachable!(),
|
WadContentInner::Stream(_) => unreachable!(),
|
||||||
WadContentInner::Mapped(data) => Ok(data.get_ref()),
|
WadContentInner::Mapped(data) => Ok(data.get_ref()),
|
||||||
|
|
Loading…
Reference in New Issue