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)
|
||||
.ok_or(Error::DiscFormat("Failed to locate data partition".to_string()))?;
|
||||
let data_off = part.part_header.data_off;
|
||||
let has_crypto = disc_io.has_wii_crypto();
|
||||
let result = Box::new(WiiPartReadStream {
|
||||
stream: wrap_windowed(
|
||||
disc_io.begin_read_stream(data_off)?,
|
||||
data_off,
|
||||
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()
|
||||
} else {
|
||||
Option::None
|
||||
|
|
|
@ -5,7 +5,11 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use crate::{io::DiscIO, streams::ReadStream, Result};
|
||||
use crate::{
|
||||
io::DiscIO,
|
||||
streams::{ByteReadStream, ReadStream},
|
||||
Result,
|
||||
};
|
||||
|
||||
pub(crate) struct DiscIOISO {
|
||||
pub(crate) filename: PathBuf,
|
||||
|
@ -18,9 +22,28 @@ impl 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)?;
|
||||
file.seek(SeekFrom::Start(offset))?;
|
||||
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 crate::{
|
||||
io::{iso::DiscIOISO, nfs::DiscIONFS},
|
||||
streams::ReadStream,
|
||||
io::{
|
||||
iso::{DiscIOISO, DiscIOISOStream},
|
||||
nfs::DiscIONFS,
|
||||
},
|
||||
streams::{ByteReadStream, ReadStream},
|
||||
Error, Result,
|
||||
};
|
||||
|
||||
|
@ -15,7 +18,7 @@ pub(crate) mod nfs;
|
|||
pub trait DiscIO {
|
||||
/// Opens a new read stream for the disc file(s).
|
||||
/// 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)
|
||||
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.
|
||||
#[inline(always)]
|
||||
pub fn has_extension(filename: &Path, extension: &str) -> bool {
|
||||
|
|
|
@ -228,7 +228,7 @@ impl<'a> ReadStream for NFSReadStream<'a> {
|
|||
}
|
||||
|
||||
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 {
|
||||
disc_io: self,
|
||||
file: Option::None,
|
||||
|
|
|
@ -173,3 +173,55 @@ impl<'a> WindowedReadStream for SharedWindowedReadStream<'a> {
|
|||
|
||||
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