mirror of https://github.com/encounter/nod-rs.git
Add new_disc_io_from_{buf,stream}
This commit is contained in:
parent
50f171dcf5
commit
4b32388fa5
|
@ -230,13 +230,14 @@ impl DiscBase for DiscWii {
|
||||||
.find(|v| v.part_type == WiiPartType::Data)
|
.find(|v| v.part_type == WiiPartType::Data)
|
||||||
.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 has_crypto = disc_io.has_wii_crypto();
|
||||||
let result = Box::new(WiiPartReadStream {
|
let result = Box::new(WiiPartReadStream {
|
||||||
stream: wrap_windowed(
|
stream: wrap_windowed(
|
||||||
disc_io.begin_read_stream(data_off)?,
|
disc_io.begin_read_stream(data_off)?,
|
||||||
data_off,
|
data_off,
|
||||||
part.part_header.data_size,
|
part.part_header.data_size,
|
||||||
)?,
|
)?,
|
||||||
crypto: if disc_io.has_wii_crypto() {
|
crypto: if has_crypto {
|
||||||
Aes128::new(&part.part_header.ticket.enc_key.into()).into()
|
Aes128::new(&part.part_header.ticket.enc_key.into()).into()
|
||||||
} else {
|
} else {
|
||||||
Option::None
|
Option::None
|
||||||
|
|
|
@ -5,7 +5,11 @@ use std::{
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{io::DiscIO, streams::ReadStream, Result};
|
use crate::{
|
||||||
|
io::DiscIO,
|
||||||
|
streams::{ByteReadStream, ReadStream},
|
||||||
|
Result,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) struct DiscIOISO {
|
pub(crate) struct DiscIOISO {
|
||||||
pub(crate) filename: PathBuf,
|
pub(crate) filename: PathBuf,
|
||||||
|
@ -18,9 +22,28 @@ impl DiscIOISO {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiscIO for DiscIOISO {
|
impl DiscIO for DiscIOISO {
|
||||||
fn begin_read_stream(&self, offset: u64) -> io::Result<Box<dyn ReadStream>> {
|
fn begin_read_stream(&mut self, offset: u64) -> io::Result<Box<dyn ReadStream>> {
|
||||||
let mut file = File::open(&*self.filename)?;
|
let mut file = File::open(&*self.filename)?;
|
||||||
file.seek(SeekFrom::Start(offset))?;
|
file.seek(SeekFrom::Start(offset))?;
|
||||||
io::Result::Ok(Box::from(file))
|
io::Result::Ok(Box::from(file))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct DiscIOISOStream<T: ReadStream + Sized> {
|
||||||
|
pub(crate) stream: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ReadStream + Sized> DiscIOISOStream<T> {
|
||||||
|
pub(crate) fn new(stream: T) -> Result<DiscIOISOStream<T>> {
|
||||||
|
Result::Ok(DiscIOISOStream { stream })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ReadStream + Sized> DiscIO for DiscIOISOStream<T> {
|
||||||
|
fn begin_read_stream<'a>(&'a mut self, offset: u64) -> io::Result<Box<dyn ReadStream + 'a>> {
|
||||||
|
let size = self.stream.stable_stream_len()?;
|
||||||
|
let mut stream = self.stream.new_window(0, size)?;
|
||||||
|
stream.seek(SeekFrom::Start(offset))?;
|
||||||
|
Ok(Box::from(stream))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
use std::{fs, io, path::Path};
|
use std::{fs, io, path::Path};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
io::{iso::DiscIOISO, nfs::DiscIONFS},
|
io::{
|
||||||
streams::ReadStream,
|
iso::{DiscIOISO, DiscIOISOStream},
|
||||||
|
nfs::DiscIONFS,
|
||||||
|
},
|
||||||
|
streams::{ByteReadStream, ReadStream},
|
||||||
Error, Result,
|
Error, Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +18,7 @@ pub(crate) mod nfs;
|
||||||
pub trait DiscIO {
|
pub trait DiscIO {
|
||||||
/// Opens a new read stream for the disc file(s).
|
/// Opens a new read stream for the disc file(s).
|
||||||
/// Generally does _not_ need to be used directly.
|
/// Generally does _not_ need to be used directly.
|
||||||
fn begin_read_stream(&self, offset: u64) -> io::Result<Box<dyn ReadStream + '_>>;
|
fn begin_read_stream(&mut self, offset: u64) -> io::Result<Box<dyn ReadStream + '_>>;
|
||||||
|
|
||||||
/// If false, the file format does not use standard Wii partition encryption. (e.g. NFS)
|
/// If false, the file format does not use standard Wii partition encryption. (e.g. NFS)
|
||||||
fn has_wii_crypto(&self) -> bool { true }
|
fn has_wii_crypto(&self) -> bool { true }
|
||||||
|
@ -66,6 +69,16 @@ pub fn new_disc_io(filename: &Path) -> Result<Box<dyn DiscIO>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_disc_io_from_buf(buf: &[u8]) -> Result<Box<dyn DiscIO + '_>> {
|
||||||
|
Ok(Box::from(DiscIOISOStream::new(ByteReadStream { bytes: buf, position: 0 })?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_disc_io_from_stream<'a, T: 'a + ReadStream + Sized>(
|
||||||
|
stream: T,
|
||||||
|
) -> Result<Box<dyn DiscIO + 'a>> {
|
||||||
|
Ok(Box::from(DiscIOISOStream::new(stream)?))
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper function for checking a file extension.
|
/// Helper function for checking a file extension.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn has_extension(filename: &Path, extension: &str) -> bool {
|
pub fn has_extension(filename: &Path, extension: &str) -> bool {
|
||||||
|
|
|
@ -228,7 +228,7 @@ impl<'a> ReadStream for NFSReadStream<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiscIO for DiscIONFS {
|
impl DiscIO for DiscIONFS {
|
||||||
fn begin_read_stream(&self, offset: u64) -> io::Result<Box<dyn ReadStream + '_>> {
|
fn begin_read_stream(&mut self, offset: u64) -> io::Result<Box<dyn ReadStream + '_>> {
|
||||||
io::Result::Ok(Box::from(NFSReadStream {
|
io::Result::Ok(Box::from(NFSReadStream {
|
||||||
disc_io: self,
|
disc_io: self,
|
||||||
file: Option::None,
|
file: Option::None,
|
||||||
|
|
|
@ -173,3 +173,55 @@ impl<'a> WindowedReadStream for SharedWindowedReadStream<'a> {
|
||||||
|
|
||||||
fn window(&self) -> (u64, u64) { (self.begin, self.end) }
|
fn window(&self) -> (u64, u64) { (self.begin, self.end) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct ByteReadStream<'a> {
|
||||||
|
pub bytes: &'a [u8],
|
||||||
|
pub position: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for ByteReadStream<'_> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
let mut len = buf.len();
|
||||||
|
let total = self.bytes.len();
|
||||||
|
let pos = self.position as usize;
|
||||||
|
if len + pos > total {
|
||||||
|
if pos >= total {
|
||||||
|
return Err(io::Error::from(io::ErrorKind::UnexpectedEof));
|
||||||
|
}
|
||||||
|
len = total - pos;
|
||||||
|
}
|
||||||
|
buf.copy_from_slice(&self.bytes[pos..pos + len]);
|
||||||
|
self.position += len as u64;
|
||||||
|
Ok(len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Seek for ByteReadStream<'_> {
|
||||||
|
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
|
let new_pos = match pos {
|
||||||
|
SeekFrom::Start(v) => v,
|
||||||
|
SeekFrom::End(v) => (self.bytes.len() as i64 + v) as u64,
|
||||||
|
SeekFrom::Current(v) => (self.position as i64 + v) as u64,
|
||||||
|
};
|
||||||
|
if new_pos > self.bytes.len() as u64 {
|
||||||
|
Err(io::Error::from(io::ErrorKind::UnexpectedEof))
|
||||||
|
} else {
|
||||||
|
self.position = new_pos;
|
||||||
|
Ok(new_pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn stream_len(&mut self) -> io::Result<u64> { Ok(self.bytes.len() as u64) }
|
||||||
|
|
||||||
|
fn stream_position(&mut self) -> io::Result<u64> { Ok(self.position) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadStream for ByteReadStream<'_> {
|
||||||
|
fn stable_stream_len(&mut self) -> io::Result<u64> { Ok(self.bytes.len() as u64) }
|
||||||
|
|
||||||
|
fn as_dyn(&mut self) -> &mut dyn ReadStream { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AsMut<dyn ReadStream + 'a> for ByteReadStream<'a> {
|
||||||
|
fn as_mut(&mut self) -> &mut (dyn ReadStream + 'a) { self as &mut (dyn ReadStream + 'a) }
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue