mirror of https://github.com/encounter/nod-rs.git
Various minor API adjustments
This commit is contained in:
parent
8abe674cb9
commit
5f537f0e7b
|
@ -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",
|
||||
|
|
|
@ -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 <luke@street.dev>"]
|
||||
|
|
|
@ -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<Cow<'a, str>, String> {
|
||||
pub fn get_name(&self, node: Node) -> Result<Cow<'a, str>, 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<Cow<'a, str>, String>);
|
||||
type Item = (usize, Node, Result<Cow<'a, str>, String>);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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))
|
||||
|
|
|
@ -124,7 +124,7 @@ impl PartitionBase for PartitionGC {
|
|||
read_part_meta(self, false)
|
||||
}
|
||||
|
||||
fn open_file(&mut self, node: &Node) -> io::Result<FileStream> {
|
||||
fn open_file(&mut self, node: Node) -> io::Result<FileStream> {
|
||||
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<Self>, node: &Node) -> io::Result<OwnedFileStream> {
|
||||
fn into_open_file(self: Box<Self>, node: Node) -> io::Result<OwnedFileStream> {
|
||||
if !node.is_file() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
|
|
|
@ -313,7 +313,7 @@ pub trait PartitionBase: DynClone + BufRead + Seek + Send + Sync {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
fn open_file(&mut self, node: &Node) -> io::Result<FileStream>;
|
||||
fn open_file(&mut self, node: Node) -> io::Result<FileStream>;
|
||||
|
||||
/// 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<Self>, node: &Node) -> io::Result<OwnedFileStream>;
|
||||
fn into_open_file(self: Box<Self>, node: Node) -> io::Result<OwnedFileStream>;
|
||||
}
|
||||
|
||||
dyn_clone::clone_trait_object!(PartitionBase);
|
||||
|
|
|
@ -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<T> Read for WindowedStream<T>
|
||||
|
|
|
@ -489,7 +489,7 @@ impl PartitionBase for PartitionWii {
|
|||
Ok(meta)
|
||||
}
|
||||
|
||||
fn open_file(&mut self, node: &Node) -> io::Result<FileStream> {
|
||||
fn open_file(&mut self, node: Node) -> io::Result<FileStream> {
|
||||
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<Self>, node: &Node) -> io::Result<OwnedFileStream> {
|
||||
fn into_open_file(self: Box<Self>, node: Node) -> io::Result<OwnedFileStream> {
|
||||
if !node.is_file() {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
|
|
|
@ -94,7 +94,7 @@ dyn_clone::clone_trait_object!(BlockIO);
|
|||
|
||||
/// Creates a new [`BlockIO`] instance from a stream.
|
||||
pub fn new(mut stream: Box<dyn DiscStream>) -> Result<Box<dyn BlockIO>> {
|
||||
let io: Box<dyn BlockIO> = match detect(stream.as_mut())? {
|
||||
let io: Box<dyn BlockIO> = 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<dyn DiscStream>) -> Result<Box<dyn BlockIO>> {
|
|||
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<Box<dyn BlockIO>> {
|
|||
return Err(Error::DiscFormat(format!("Input is not a file: {}", filename.display())));
|
||||
}
|
||||
let mut stream = Box::new(SplitFileReader::new(filename)?);
|
||||
let io: Box<dyn BlockIO> = match detect(stream.as_mut())? {
|
||||
let io: Box<dyn BlockIO> = 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<Box<dyn BlockIO>> {
|
|||
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<R: Read + ?Sized>(stream: &mut R) -> Result<Option<Format>> {
|
||||
pub fn detect<R: Read + ?Sized>(stream: &mut R) -> io::Result<Option<Format>> {
|
||||
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),
|
||||
|
|
|
@ -192,7 +192,7 @@ impl Disc {
|
|||
|
||||
/// Detects the format of a disc image from a read stream.
|
||||
#[inline]
|
||||
pub fn detect<R>(stream: &mut R) -> Result<Option<Format>>
|
||||
pub fn detect<R>(stream: &mut R) -> std::io::Result<Option<Format>>
|
||||
where R: Read + ?Sized {
|
||||
io::block::detect(stream)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue