From 8b3f655dc2abd75997c1791d557a2d5262c468ea Mon Sep 17 00:00:00 2001 From: Luke Street Date: Wed, 2 Feb 2022 17:42:34 -0500 Subject: [PATCH] Various updates - Use thiserror for nod::Error - Use anyhow for error context chaining - Stream logic fixes --- Cargo.toml | 4 +++- src/disc/mod.rs | 4 ++-- src/io/iso.rs | 2 +- src/io/mod.rs | 4 ++-- src/lib.rs | 24 +++++++++++------------- src/streams.rs | 16 ++++++++++++++-- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2744fec..3dc3a1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nod" -version = "0.1.1" +version = "0.1.2" edition = "2018" authors = ["Luke Street "] license = "MIT OR Apache-2.0" @@ -19,9 +19,11 @@ path = "src/bin.rs" [dependencies] aes = "0.7.4" +anyhow = "1.0.53" binread = "2.1.1" block-modes = "0.8.1" clap = "2.33.3" encoding_rs = "0.8.28" file-size = "1.0.3" sha-1 = "0.9.7" +thiserror = "1.0.30" diff --git a/src/disc/mod.rs b/src/disc/mod.rs index 287d768..a21c13b 100644 --- a/src/disc/mod.rs +++ b/src/disc/mod.rs @@ -73,7 +73,7 @@ pub(crate) struct BI2Header { pub(crate) const BUFFER_SIZE: usize = 0x8000; /// Contains a disc's header & partition information. -pub trait DiscBase { +pub trait DiscBase: Send + Sync { /// Retrieves the disc's header. fn get_header(&self) -> &Header; @@ -157,7 +157,7 @@ pub trait PartReadStream: ReadStream { } /// Disc partition header with file system table. -pub trait PartHeader: Debug { +pub trait PartHeader: Debug + Send + Sync { /// The root node for the filesystem. fn root_node(&self) -> &NodeType; diff --git a/src/io/iso.rs b/src/io/iso.rs index 6a4a21a..a8b163a 100644 --- a/src/io/iso.rs +++ b/src/io/iso.rs @@ -39,7 +39,7 @@ impl DiscIOISOStream { } } -impl DiscIO for DiscIOISOStream { +impl DiscIO for DiscIOISOStream { fn begin_read_stream<'a>(&'a mut self, offset: u64) -> io::Result> { let size = self.stream.stable_stream_len()?; let mut stream = self.stream.new_window(0, size)?; diff --git a/src/io/mod.rs b/src/io/mod.rs index d534590..c92f1c4 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -15,7 +15,7 @@ pub(crate) mod iso; pub(crate) mod nfs; /// Abstraction over supported disc file types. -pub trait DiscIO { +pub trait DiscIO: Send + Sync { /// Opens a new read stream for the disc file(s). /// Generally does _not_ need to be used directly. fn begin_read_stream(&mut self, offset: u64) -> io::Result>; @@ -73,7 +73,7 @@ pub fn new_disc_io_from_buf(buf: &[u8]) -> Result> { Ok(Box::from(DiscIOISOStream::new(ByteReadStream { bytes: buf, position: 0 })?)) } -pub fn new_disc_io_from_stream<'a, T: 'a + ReadStream + Sized>( +pub fn new_disc_io_from_stream<'a, T: 'a + ReadStream + Sized + Send + Sync>( stream: T, ) -> Result> { Ok(Box::from(DiscIOISOStream::new(stream)?)) diff --git a/src/lib.rs b/src/lib.rs index c8e3eb8..97a41d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -26,33 +26,31 @@ //! println!(s); //! } //! ``` +use thiserror::Error; + pub mod disc; pub mod fst; pub mod io; pub mod streams; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum Error { - BinaryFormat(binread::Error), - Encryption(block_modes::BlockModeError), - Io(String, std::io::Error), + #[error("binary format")] + BinaryFormat(#[from] binread::Error), + #[error("encryption")] + Encryption(#[from] block_modes::BlockModeError), + #[error("io error: `{0}`")] + Io(String, #[source] std::io::Error), + #[error("disc format error: `{0}`")] DiscFormat(String), } -pub type Result = std::result::Result; +pub type Result = anyhow::Result; impl From for Error { fn from(v: std::io::Error) -> Self { Error::Io("I/O error".to_string(), v) } } -impl From for Error { - fn from(v: binread::Error) -> Self { Error::BinaryFormat(v) } -} - -impl From for Error { - fn from(v: block_modes::BlockModeError) -> Self { Error::Encryption(v) } -} - #[inline(always)] pub(crate) fn div_rem + std::ops::Rem + Copy>( x: T, diff --git a/src/streams.rs b/src/streams.rs index 1f6871e..c5b873c 100644 --- a/src/streams.rs +++ b/src/streams.rs @@ -57,7 +57,14 @@ impl ReadStream for File { let before = self.stream_position()?; let result = self.seek(SeekFrom::End(0)); // Try to restore position even if the above failed - self.seek(SeekFrom::Start(before))?; + let seek_result = self.seek(SeekFrom::Start(before)); + if seek_result.is_err() { + return if result.is_err() { + result + } else { + seek_result + } + } result } @@ -104,6 +111,9 @@ impl<'a> SharedWindowedReadStream<'a> { fn windowed_read(stream: &mut dyn WindowedReadStream, buf: &mut [u8]) -> io::Result { let pos = stream.stream_position()?; let size = stream.stable_stream_len()?; + if pos == size { + return Ok(0); + } stream.base_stream().read(if pos + buf.len() as u64 > size { &mut buf[..(size - pos) as usize] } else { @@ -185,8 +195,10 @@ impl Read for ByteReadStream<'_> { let total = self.bytes.len(); let pos = self.position as usize; if len + pos > total { - if pos >= total { + if pos > total { return Err(io::Error::from(io::ErrorKind::UnexpectedEof)); + } else if pos == total { + return Ok(0); } len = total - pos; }