diff --git a/Cargo.lock b/Cargo.lock index e1b6f81..cc19448 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -447,7 +447,7 @@ dependencies = [ [[package]] name = "nod" -version = "1.3.0" +version = "1.4.0" dependencies = [ "adler", "aes", @@ -470,7 +470,7 @@ dependencies = [ [[package]] name = "nodtool" -version = "1.3.0" +version = "1.4.0" dependencies = [ "argp", "base16ct", diff --git a/Cargo.toml b/Cargo.toml index f7c7e2c..5a16ea8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ strip = "debuginfo" codegen-units = 1 [workspace.package] -version = "1.3.0" +version = "1.4.0" edition = "2021" rust-version = "1.74" authors = ["Luke Street "] diff --git a/nod/src/disc/fst.rs b/nod/src/disc/fst.rs index b08e69d..716602b 100644 --- a/nod/src/disc/fst.rs +++ b/nod/src/disc/fst.rs @@ -19,7 +19,7 @@ pub enum NodeKind { } /// An individual file system node. -#[derive(Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] +#[derive(Copy, Clone, Debug, PartialEq, FromBytes, FromZeroes, AsBytes)] #[repr(C, align(4))] pub struct Node { kind: u8, @@ -108,7 +108,7 @@ impl<'a> Fst<'a> { /// Get the name of a node. #[allow(clippy::missing_inline_in_public_items)] - pub fn get_name(&self, node: &Node) -> Result, String> { + pub fn get_name(&self, node: Node) -> Result, String> { let name_buf = self.string_table.get(node.name_offset() as usize..).ok_or_else(|| { format!( "FST: name offset {} out of bounds (string table size: {})", @@ -128,12 +128,12 @@ impl<'a> Fst<'a> { /// Finds a particular file or directory by path. #[allow(clippy::missing_inline_in_public_items)] - pub fn find(&self, path: &str) -> Option<(usize, &'a Node)> { + pub fn find(&self, path: &str) -> Option<(usize, Node)> { let mut split = path.trim_matches('/').split('/'); let mut current = split.next()?; let mut idx = 1; let mut stop_at = None; - while let Some(node) = self.nodes.get(idx) { + while let Some(node) = self.nodes.get(idx).copied() { if self.get_name(node).as_ref().map_or(false, |name| name.eq_ignore_ascii_case(current)) { if let Some(next) = split.next() { @@ -168,11 +168,11 @@ pub struct FstIter<'a> { } impl<'a> Iterator for FstIter<'a> { - type Item = (usize, &'a Node, Result, String>); + type Item = (usize, Node, Result, String>); fn next(&mut self) -> Option { let idx = self.idx; - let node = self.fst.nodes.get(idx)?; + let node = self.fst.nodes.get(idx).copied()?; let name = self.fst.get_name(node); self.idx += 1; Some((idx, node, name)) diff --git a/nod/src/disc/gcn.rs b/nod/src/disc/gcn.rs index a52b7b7..b51518a 100644 --- a/nod/src/disc/gcn.rs +++ b/nod/src/disc/gcn.rs @@ -124,7 +124,7 @@ impl PartitionBase for PartitionGC { read_part_meta(self, false) } - fn open_file(&mut self, node: &Node) -> io::Result { + fn open_file(&mut self, node: Node) -> io::Result { if !node.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidInput, @@ -134,7 +134,7 @@ impl PartitionBase for PartitionGC { FileStream::new(self, node.offset(false), node.length()) } - fn into_open_file(self: Box, node: &Node) -> io::Result { + fn into_open_file(self: Box, node: Node) -> io::Result { if !node.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidInput, diff --git a/nod/src/disc/mod.rs b/nod/src/disc/mod.rs index 3bd1102..d5178cf 100644 --- a/nod/src/disc/mod.rs +++ b/nod/src/disc/mod.rs @@ -313,7 +313,7 @@ pub trait PartitionBase: DynClone + BufRead + Seek + Send + Sync { /// Ok(()) /// } /// ``` - fn open_file(&mut self, node: &Node) -> io::Result; + fn open_file(&mut self, node: Node) -> io::Result; /// Consumes the partition instance and returns a windowed stream. /// @@ -342,7 +342,7 @@ pub trait PartitionBase: DynClone + BufRead + Seek + Send + Sync { /// Ok(()) /// } /// ``` - fn into_open_file(self: Box, node: &Node) -> io::Result; + fn into_open_file(self: Box, node: Node) -> io::Result; } dyn_clone::clone_trait_object!(PartitionBase); diff --git a/nod/src/disc/streams.rs b/nod/src/disc/streams.rs index cbee2fb..fbb8277 100644 --- a/nod/src/disc/streams.rs +++ b/nod/src/disc/streams.rs @@ -35,6 +35,11 @@ where T: BufRead + Seek base.seek(SeekFrom::Start(offset))?; Ok(Self { base, pos: offset, begin: offset, end: offset + size }) } + + /// Returns the length of the window. + #[inline] + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> u64 { self.end - self.begin } } impl Read for WindowedStream diff --git a/nod/src/disc/wii.rs b/nod/src/disc/wii.rs index 586fd4e..df3aac7 100644 --- a/nod/src/disc/wii.rs +++ b/nod/src/disc/wii.rs @@ -489,7 +489,7 @@ impl PartitionBase for PartitionWii { Ok(meta) } - fn open_file(&mut self, node: &Node) -> io::Result { + fn open_file(&mut self, node: Node) -> io::Result { if !node.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidInput, @@ -499,7 +499,7 @@ impl PartitionBase for PartitionWii { FileStream::new(self, node.offset(true), node.length()) } - fn into_open_file(self: Box, node: &Node) -> io::Result { + fn into_open_file(self: Box, node: Node) -> io::Result { if !node.is_file() { return Err(io::Error::new( io::ErrorKind::InvalidInput, diff --git a/nod/src/io/block.rs b/nod/src/io/block.rs index d53b759..b98d115 100644 --- a/nod/src/io/block.rs +++ b/nod/src/io/block.rs @@ -94,7 +94,7 @@ dyn_clone::clone_trait_object!(BlockIO); /// Creates a new [`BlockIO`] instance from a stream. pub fn new(mut stream: Box) -> Result> { - let io: Box = match detect(stream.as_mut())? { + let io: Box = match detect(stream.as_mut()).context("Detecting file type")? { Some(Format::Iso) => crate::io::iso::DiscIOISO::new(stream)?, Some(Format::Ciso) => crate::io::ciso::DiscIOCISO::new(stream)?, Some(Format::Gcz) => { @@ -103,9 +103,7 @@ pub fn new(mut stream: Box) -> Result> { crate::io::gcz::DiscIOGCZ::new(stream)? } #[cfg(not(feature = "compress-zlib"))] - { - return Err(Error::DiscFormat("GCZ support is disabled".to_string())); - } + return Err(Error::DiscFormat("GCZ support is disabled".to_string())); } Some(Format::Nfs) => { return Err(Error::DiscFormat("NFS requires a filesystem path".to_string())) @@ -134,7 +132,7 @@ pub fn open(filename: &Path) -> Result> { return Err(Error::DiscFormat(format!("Input is not a file: {}", filename.display()))); } let mut stream = Box::new(SplitFileReader::new(filename)?); - let io: Box = match detect(stream.as_mut())? { + let io: Box = match detect(stream.as_mut()).context("Detecting file type")? { Some(Format::Iso) => crate::io::iso::DiscIOISO::new(stream)?, Some(Format::Ciso) => crate::io::ciso::DiscIOCISO::new(stream)?, Some(Format::Gcz) => { @@ -143,9 +141,7 @@ pub fn open(filename: &Path) -> Result> { crate::io::gcz::DiscIOGCZ::new(stream)? } #[cfg(not(feature = "compress-zlib"))] - { - return Err(Error::DiscFormat("GCZ support is disabled".to_string())); - } + return Err(Error::DiscFormat("GCZ support is disabled".to_string())); } Some(Format::Nfs) => match path.parent() { Some(parent) if parent.is_dir() => { @@ -172,11 +168,11 @@ pub const WBFS_MAGIC: MagicBytes = *b"WBFS"; pub const WIA_MAGIC: MagicBytes = *b"WIA\x01"; pub const RVZ_MAGIC: MagicBytes = *b"RVZ\x01"; -pub fn detect(stream: &mut R) -> Result> { +pub fn detect(stream: &mut R) -> io::Result> { let data: [u8; 0x20] = match read_from(stream) { Ok(magic) => magic, Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => return Ok(None), - Err(e) => return Err(e).context("Reading magic bytes"), + Err(e) => return Err(e), }; let out = match *array_ref!(data, 0, 4) { CISO_MAGIC => Some(Format::Ciso), diff --git a/nod/src/lib.rs b/nod/src/lib.rs index a3460f4..b726ee4 100644 --- a/nod/src/lib.rs +++ b/nod/src/lib.rs @@ -192,7 +192,7 @@ impl Disc { /// Detects the format of a disc image from a read stream. #[inline] - pub fn detect(stream: &mut R) -> Result> + pub fn detect(stream: &mut R) -> std::io::Result> where R: Read + ?Sized { io::block::detect(stream) } diff --git a/nodtool/src/cmd/extract.rs b/nodtool/src/cmd/extract.rs index bb4b048..bcd8886 100644 --- a/nodtool/src/cmd/extract.rs +++ b/nodtool/src/cmd/extract.rs @@ -181,7 +181,7 @@ fn extract_file(bytes: &[u8], out_path: &Path, quiet: bool) -> nod::Result<()> { } fn extract_node( - node: &Node, + node: Node, partition: &mut dyn PartitionBase, base_path: &Path, name: &str, diff --git a/nodtool/src/lib.rs b/nodtool/src/lib.rs index c20d907..ac42d14 100644 --- a/nodtool/src/lib.rs +++ b/nodtool/src/lib.rs @@ -3,6 +3,9 @@ use argp::FromArgs; pub mod cmd; pub(crate) mod util; +// Re-export nod +pub use nod; + #[derive(FromArgs, Debug)] #[argp(subcommand)] pub enum SubCommand {