From 9df1aa4149eca31505c6b7285384d9a7ccb366a4 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Mon, 23 Aug 2021 16:51:05 -0400 Subject: [PATCH] Release 0.1.1: Improvements to windowed stream API, minor fixes --- .gitignore | 1 + Cargo.toml | 2 +- README.md | 3 ++- src/disc/gcn.rs | 8 +------- src/disc/wii.rs | 19 ++++++------------- src/io/nfs.rs | 6 +++--- src/streams.rs | 34 ++++++++++++++++++++++++++++------ 7 files changed, 42 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 96ef6c0..b471067 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +.idea diff --git a/Cargo.toml b/Cargo.toml index d69d558..2744fec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nod" -version = "0.1.0" +version = "0.1.1" edition = "2018" authors = ["Luke Street "] license = "MIT OR Apache-2.0" diff --git a/README.md b/README.md index 835513b..0a8fd30 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# nod-rs [![Build Status]][actions] [![Latest Version]][crates.io] [![Api Rustdoc]][rustdoc] [![Rust](https://img.shields.io/badge/rust-1.51%2B-blue.svg?maxAge=3600)](https://github.com/encounter/nod-rs) +# nod-rs [![Build Status]][actions] [![Latest Version]][crates.io] [![Api Rustdoc]][rustdoc] ![Rust Version] [Build Status]: https://github.com/encounter/nod-rs/workflows/build/badge.svg [actions]: https://github.com/encounter/nod-rs/actions @@ -6,6 +6,7 @@ [crates.io]: https://crates.io/crates/nod [Api Rustdoc]: https://img.shields.io/badge/api-rustdoc-blue.svg [rustdoc]: https://docs.rs/nod +[Rust Version]: https://img.shields.io/badge/rust-1.51+-blue.svg?maxAge=3600 Library for traversing & reading GameCube and Wii disc images. diff --git a/src/disc/gcn.rs b/src/disc/gcn.rs index cd889da..309f823 100644 --- a/src/disc/gcn.rs +++ b/src/disc/gcn.rs @@ -100,13 +100,7 @@ impl<'a> ReadStream for GCPartReadStream<'a> { impl<'a> PartReadStream for GCPartReadStream<'a> { fn begin_file_stream(&mut self, node: &Node) -> io::Result { assert_eq!(node.kind, NodeKind::File); - let offset = node.offset as u64; - self.seek(SeekFrom::Start(offset))?; - io::Result::Ok(SharedWindowedReadStream { - base: self, - begin: offset, - end: offset + node.length as u64, - }) + io::Result::Ok(self.new_window(node.offset as u64, node.length as u64)?) } fn read_header(&mut self) -> Result> { diff --git a/src/disc/wii.rs b/src/disc/wii.rs index 5254422..b72b423 100644 --- a/src/disc/wii.rs +++ b/src/disc/wii.rs @@ -8,7 +8,7 @@ use sha1::{digest, Digest, Sha1}; use crate::disc::{BI2Header, BUFFER_SIZE, DiscBase, DiscIO, Header, PartHeader, PartReadStream}; use crate::{Error, div_rem, Result, array_ref}; use crate::fst::{find_node, Node, NodeKind, NodeType, node_parser}; -use crate::streams::{OwningWindowedReadStream, ReadStream, SharedWindowedReadStream}; +use crate::streams::{OwningWindowedReadStream, ReadStream, SharedWindowedReadStream, wrap_windowed}; type Aes128Cbc = Cbc; @@ -218,11 +218,10 @@ impl DiscBase for DiscWii { .ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?; let data_off = part.part_header.data_off; let result = Box::new(WiiPartReadStream { - stream: OwningWindowedReadStream { - base: disc_io.begin_read_stream(data_off)?, - begin: data_off, - end: data_off + part.part_header.data_size, - }, + stream: wrap_windowed( + disc_io.begin_read_stream(data_off)?, + data_off, part.part_header.data_size, + )?, crypto: if disc_io.has_wii_crypto() { Aes128::new(&part.part_header.ticket.enc_key.into()).into() } else { Option::None }, @@ -247,13 +246,7 @@ struct WiiPartReadStream<'a> { impl<'a> PartReadStream for WiiPartReadStream<'a> { fn begin_file_stream(&mut self, node: &Node) -> io::Result { assert_eq!(node.kind, NodeKind::File); - let offset = (node.offset as u64) << 2; - self.seek(SeekFrom::Start(offset))?; - io::Result::Ok(SharedWindowedReadStream { - base: self, - begin: offset, - end: offset + node.length as u64, - }) + io::Result::Ok(self.new_window((node.offset as u64) << 2, node.length as u64)?) } fn read_header(&mut self) -> Result> { diff --git a/src/io/nfs.rs b/src/io/nfs.rs index cb7ce5f..b6401f1 100644 --- a/src/io/nfs.rs +++ b/src/io/nfs.rs @@ -167,9 +167,9 @@ impl<'a> NFSReadStream<'a> { let iv: [u8; 16] = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (phys_addr.l_block & 0xFF) as u8, - ((phys_addr.l_block >> 2) & 0xFF) as u8, - ((phys_addr.l_block >> 4) & 0xFF) as u8, - ((phys_addr.l_block >> 6) & 0xFF) as u8, + ((phys_addr.l_block >> 8) & 0xFF) as u8, + ((phys_addr.l_block >> 16) & 0xFF) as u8, + ((phys_addr.l_block >> 24) & 0xFF) as u8, ]; Aes128Cbc::new(self.crypto.clone(), &iv.into()) .decrypt(&mut self.buf)?; diff --git a/src/streams.rs b/src/streams.rs index 161d8e5..b46a7ef 100644 --- a/src/streams.rs +++ b/src/streams.rs @@ -20,6 +20,18 @@ pub trait ReadStream: Read + Seek { /// /// fn stable_stream_len(&mut self) -> io::Result; + + /// Creates a windowed read sub-stream with offset and size. + /// + /// Seeks underlying stream immediately. + fn new_window(&mut self, offset: u64, size: u64) -> io::Result where Self: Sized { + self.seek(SeekFrom::Start(offset))?; + io::Result::Ok(SharedWindowedReadStream { + base: self, + begin: offset, + end: offset + size, + }) + } } impl ReadStream for File { @@ -38,15 +50,25 @@ trait WindowedReadStream: ReadStream { } pub struct OwningWindowedReadStream<'a> { - pub(crate) base: Box, - pub(crate) begin: u64, - pub(crate) end: u64, + pub base: Box, + pub begin: u64, + pub end: u64, +} + +/// Takes ownership of & wraps a read stream into a windowed read stream. +pub fn wrap_windowed<'a>(mut base: Box, offset: u64, size: u64) -> io::Result> { + base.seek(SeekFrom::Start(offset))?; + io::Result::Ok(OwningWindowedReadStream { + base, + begin: offset, + end: offset + size, + }) } pub struct SharedWindowedReadStream<'a> { - pub(crate) base: &'a mut dyn ReadStream, - pub(crate) begin: u64, - pub(crate) end: u64, + pub base: &'a mut dyn ReadStream, + pub begin: u64, + pub end: u64, } #[inline(always)]