Release 0.1.1: Improvements to windowed stream API, minor fixes

This commit is contained in:
Luke Street 2021-08-23 16:51:05 -04:00
parent 1e60c551e1
commit 9df1aa4149
7 changed files with 42 additions and 31 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target /target
Cargo.lock Cargo.lock
.idea

View File

@ -1,6 +1,6 @@
[package] [package]
name = "nod" name = "nod"
version = "0.1.0" version = "0.1.1"
edition = "2018" edition = "2018"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"

View File

@ -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 [Build Status]: https://github.com/encounter/nod-rs/workflows/build/badge.svg
[actions]: https://github.com/encounter/nod-rs/actions [actions]: https://github.com/encounter/nod-rs/actions
@ -6,6 +6,7 @@
[crates.io]: https://crates.io/crates/nod [crates.io]: https://crates.io/crates/nod
[Api Rustdoc]: https://img.shields.io/badge/api-rustdoc-blue.svg [Api Rustdoc]: https://img.shields.io/badge/api-rustdoc-blue.svg
[rustdoc]: https://docs.rs/nod [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. Library for traversing & reading GameCube and Wii disc images.

View File

@ -100,13 +100,7 @@ impl<'a> ReadStream for GCPartReadStream<'a> {
impl<'a> PartReadStream for GCPartReadStream<'a> { impl<'a> PartReadStream for GCPartReadStream<'a> {
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> { fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
assert_eq!(node.kind, NodeKind::File); assert_eq!(node.kind, NodeKind::File);
let offset = node.offset as u64; io::Result::Ok(self.new_window(node.offset as u64, node.length as u64)?)
self.seek(SeekFrom::Start(offset))?;
io::Result::Ok(SharedWindowedReadStream {
base: self,
begin: offset,
end: offset + node.length as u64,
})
} }
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> { fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {

View File

@ -8,7 +8,7 @@ use sha1::{digest, Digest, Sha1};
use crate::disc::{BI2Header, BUFFER_SIZE, DiscBase, DiscIO, Header, PartHeader, PartReadStream}; use crate::disc::{BI2Header, BUFFER_SIZE, DiscBase, DiscIO, Header, PartHeader, PartReadStream};
use crate::{Error, div_rem, Result, array_ref}; use crate::{Error, div_rem, Result, array_ref};
use crate::fst::{find_node, Node, NodeKind, NodeType, node_parser}; 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<Aes128, NoPadding>; type Aes128Cbc = Cbc<Aes128, NoPadding>;
@ -218,11 +218,10 @@ impl DiscBase for DiscWii {
.ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?; .ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?;
let data_off = part.part_header.data_off; let data_off = part.part_header.data_off;
let result = Box::new(WiiPartReadStream { let result = Box::new(WiiPartReadStream {
stream: OwningWindowedReadStream { stream: wrap_windowed(
base: disc_io.begin_read_stream(data_off)?, disc_io.begin_read_stream(data_off)?,
begin: data_off, data_off, part.part_header.data_size,
end: data_off + part.part_header.data_size, )?,
},
crypto: if disc_io.has_wii_crypto() { crypto: if disc_io.has_wii_crypto() {
Aes128::new(&part.part_header.ticket.enc_key.into()).into() Aes128::new(&part.part_header.ticket.enc_key.into()).into()
} else { Option::None }, } else { Option::None },
@ -247,13 +246,7 @@ struct WiiPartReadStream<'a> {
impl<'a> PartReadStream for WiiPartReadStream<'a> { impl<'a> PartReadStream for WiiPartReadStream<'a> {
fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> { fn begin_file_stream(&mut self, node: &Node) -> io::Result<SharedWindowedReadStream> {
assert_eq!(node.kind, NodeKind::File); assert_eq!(node.kind, NodeKind::File);
let offset = (node.offset as u64) << 2; io::Result::Ok(self.new_window((node.offset as u64) << 2, node.length as u64)?)
self.seek(SeekFrom::Start(offset))?;
io::Result::Ok(SharedWindowedReadStream {
base: self,
begin: offset,
end: offset + node.length as u64,
})
} }
fn read_header(&mut self) -> Result<Box<dyn PartHeader>> { fn read_header(&mut self) -> Result<Box<dyn PartHeader>> {

View File

@ -167,9 +167,9 @@ impl<'a> NFSReadStream<'a> {
let iv: [u8; 16] = [ let iv: [u8; 16] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
(phys_addr.l_block & 0xFF) as u8, (phys_addr.l_block & 0xFF) as u8,
((phys_addr.l_block >> 2) & 0xFF) as u8, ((phys_addr.l_block >> 8) & 0xFF) as u8,
((phys_addr.l_block >> 4) & 0xFF) as u8, ((phys_addr.l_block >> 16) & 0xFF) as u8,
((phys_addr.l_block >> 6) & 0xFF) as u8, ((phys_addr.l_block >> 24) & 0xFF) as u8,
]; ];
Aes128Cbc::new(self.crypto.clone(), &iv.into()) Aes128Cbc::new(self.crypto.clone(), &iv.into())
.decrypt(&mut self.buf)?; .decrypt(&mut self.buf)?;

View File

@ -20,6 +20,18 @@ pub trait ReadStream: Read + Seek {
/// ///
/// <https://github.com/rust-lang/rust/issues/59359> /// <https://github.com/rust-lang/rust/issues/59359>
fn stable_stream_len(&mut self) -> io::Result<u64>; fn stable_stream_len(&mut self) -> io::Result<u64>;
/// 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<SharedWindowedReadStream> where Self: Sized {
self.seek(SeekFrom::Start(offset))?;
io::Result::Ok(SharedWindowedReadStream {
base: self,
begin: offset,
end: offset + size,
})
}
} }
impl ReadStream for File { impl ReadStream for File {
@ -38,15 +50,25 @@ trait WindowedReadStream: ReadStream {
} }
pub struct OwningWindowedReadStream<'a> { pub struct OwningWindowedReadStream<'a> {
pub(crate) base: Box<dyn ReadStream + 'a>, pub base: Box<dyn ReadStream + 'a>,
pub(crate) begin: u64, pub begin: u64,
pub(crate) end: u64, pub end: u64,
}
/// Takes ownership of & wraps a read stream into a windowed read stream.
pub fn wrap_windowed<'a>(mut base: Box<dyn ReadStream + 'a>, offset: u64, size: u64) -> io::Result<OwningWindowedReadStream<'a>> {
base.seek(SeekFrom::Start(offset))?;
io::Result::Ok(OwningWindowedReadStream {
base,
begin: offset,
end: offset + size,
})
} }
pub struct SharedWindowedReadStream<'a> { pub struct SharedWindowedReadStream<'a> {
pub(crate) base: &'a mut dyn ReadStream, pub base: &'a mut dyn ReadStream,
pub(crate) begin: u64, pub begin: u64,
pub(crate) end: u64, pub end: u64,
} }
#[inline(always)] #[inline(always)]