Migrate to Rust edition 2024

This commit is contained in:
Luke Street 2025-03-04 22:59:28 -07:00
parent fb3542f445
commit d6969045be
38 changed files with 116 additions and 125 deletions

View File

@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
toolchain: [ stable, 1.81.0, nightly ] toolchain: [ stable, 1.85.0, nightly ]
fail-fast: false fail-fast: false
env: env:
RUSTFLAGS: -D warnings RUSTFLAGS: -D warnings

View File

@ -1,6 +1,6 @@
[workspace] [workspace]
members = ["nod", "nodtool"] members = ["nod", "nodtool"]
resolver = "2" resolver = "3"
[profile.release] [profile.release]
debug = 1 debug = 1
@ -13,8 +13,8 @@ codegen-units = 1
[workspace.package] [workspace.package]
version = "2.0.0-alpha.1" version = "2.0.0-alpha.1"
edition = "2021" edition = "2024"
rust-version = "1.81" rust-version = "1.85"
authors = ["Luke Street <luke@street.dev>"] authors = ["Luke Street <luke@street.dev>"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/encounter/nod" repository = "https://github.com/encounter/nod"

View File

@ -6,7 +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.81+-blue.svg?maxAge=3600 [Rust Version]: https://img.shields.io/badge/rust-1.85+-blue.svg?maxAge=3600
Library for reading and writing Nintendo Optical Disc (GameCube and Wii) images. Library for reading and writing Nintendo Optical Disc (GameCube and Wii) images.

View File

@ -9,14 +9,14 @@ use tracing::debug;
use zerocopy::{FromZeros, IntoBytes}; use zerocopy::{FromZeros, IntoBytes};
use crate::{ use crate::{
Error, Result, ResultContext,
disc::{ disc::{
fst::{Fst, FstBuilder}, BI2_SIZE, BOOT_SIZE, BootHeader, DiscHeader, GCN_MAGIC, MINI_DVD_SIZE, SECTOR_SIZE,
BootHeader, DiscHeader, BI2_SIZE, BOOT_SIZE, GCN_MAGIC, MINI_DVD_SIZE, SECTOR_SIZE,
WII_MAGIC, WII_MAGIC,
fst::{Fst, FstBuilder},
}, },
read::DiscStream, read::DiscStream,
util::{array_ref, array_ref_mut, lfg::LaggedFibonacci, Align}, util::{Align, array_ref, array_ref_mut, lfg::LaggedFibonacci},
Error, Result, ResultContext,
}; };
pub trait FileCallback: Clone + Send + Sync { pub trait FileCallback: Clone + Send + Sync {

View File

@ -5,12 +5,12 @@ use std::{borrow::Cow, fmt, str::FromStr, sync::Arc};
use zerocopy::FromBytes; use zerocopy::FromBytes;
use crate::{ use crate::{
Error, Result,
disc::{ disc::{
fst::Fst, wii::WiiPartitionHeader, BootHeader, DebugHeader, DiscHeader, BB2_OFFSET, BB2_OFFSET, BOOT_SIZE, BootHeader, DebugHeader, DiscHeader, SECTOR_SIZE, fst::Fst,
BOOT_SIZE, SECTOR_SIZE, wii::WiiPartitionHeader,
}, },
util::array_ref, util::array_ref,
Error, Result,
}; };
/// SHA-1 hash bytes /// SHA-1 hash bytes

View File

@ -7,11 +7,11 @@ use std::{
use zerocopy::FromZeros; use zerocopy::FromZeros;
use crate::{ use crate::{
Result,
common::KeyBytes, common::KeyBytes,
disc::{wii::SECTOR_DATA_SIZE, DiscHeader, SECTOR_SIZE}, disc::{DiscHeader, SECTOR_SIZE, wii::SECTOR_DATA_SIZE},
io::block::{Block, BlockReader}, io::block::{Block, BlockReader},
util::impl_read_for_bufread, util::impl_read_for_bufread,
Result,
}; };
#[derive(Clone)] #[derive(Clone)]

View File

@ -4,11 +4,11 @@ use std::{borrow::Cow, ffi::CStr, mem::size_of};
use encoding_rs::SHIFT_JIS; use encoding_rs::SHIFT_JIS;
use itertools::Itertools; use itertools::Itertools;
use zerocopy::{big_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, big_endian::*};
use crate::{ use crate::{
util::{array_ref, static_assert},
Error, Result, Error, Result,
util::{array_ref, static_assert},
}; };
/// File system node kind. /// File system node kind.
@ -39,13 +39,14 @@ impl Node {
/// Create a new node. /// Create a new node.
#[inline] #[inline]
pub fn new(kind: NodeKind, name_offset: u32, offset: u64, length: u32, is_wii: bool) -> Self { pub fn new(kind: NodeKind, name_offset: u32, offset: u64, length: u32, is_wii: bool) -> Self {
let name_offset_bytes = name_offset.to_be_bytes();
Self { Self {
kind: match kind { kind: match kind {
NodeKind::File => 0, NodeKind::File => 0,
NodeKind::Directory => 1, NodeKind::Directory => 1,
NodeKind::Invalid => u8::MAX, NodeKind::Invalid => u8::MAX,
}, },
name_offset: *array_ref![name_offset.to_be_bytes(), 1, 3], name_offset: *array_ref![name_offset_bytes, 1, 3],
offset: U32::new(match kind { offset: U32::new(match kind {
NodeKind::File if is_wii => (offset / 4) as u32, NodeKind::File if is_wii => (offset / 4) as u32,
_ => offset as u32, _ => offset as u32,
@ -91,7 +92,8 @@ impl Node {
/// Set the name offset of the node. /// Set the name offset of the node.
#[inline] #[inline]
pub fn set_name_offset(&mut self, name_offset: u32) { pub fn set_name_offset(&mut self, name_offset: u32) {
self.name_offset = *array_ref![name_offset.to_be_bytes(), 1, 3]; let name_offset_bytes = name_offset.to_be_bytes();
self.name_offset = *array_ref![name_offset_bytes, 1, 3];
} }
/// For files, this is the partition offset of the file data. (Wii: >> 2) /// For files, this is the partition offset of the file data. (Wii: >> 2)

View File

@ -8,10 +8,11 @@ use std::{
use zerocopy::{FromBytes, FromZeros, IntoBytes}; use zerocopy::{FromBytes, FromZeros, IntoBytes};
use crate::{ use crate::{
Result, ResultContext,
disc::{ disc::{
preloader::{fetch_sector_group, Preloader, SectorGroup, SectorGroupRequest}, ApploaderHeader, BB2_OFFSET, BI2_SIZE, BOOT_SIZE, BootHeader, DolHeader, SECTOR_GROUP_SIZE,
ApploaderHeader, BootHeader, DolHeader, BB2_OFFSET, BI2_SIZE, BOOT_SIZE, SECTOR_GROUP_SIZE,
SECTOR_SIZE, SECTOR_SIZE,
preloader::{Preloader, SectorGroup, SectorGroupRequest, fetch_sector_group},
}, },
io::block::BlockReader, io::block::BlockReader,
read::{DiscStream, PartitionEncryption, PartitionMeta, PartitionReader}, read::{DiscStream, PartitionEncryption, PartitionMeta, PartitionReader},
@ -19,7 +20,6 @@ use crate::{
impl_read_for_bufread, impl_read_for_bufread,
read::{read_arc, read_arc_slice, read_from}, read::{read_arc, read_arc_slice, read_from},
}, },
Result, ResultContext,
}; };
pub struct PartitionReaderGC { pub struct PartitionReaderGC {

View File

@ -4,8 +4,8 @@ use zerocopy::{FromZeros, IntoBytes};
use crate::{ use crate::{
common::HashBytes, common::HashBytes,
disc::{ disc::{
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
SECTOR_GROUP_SIZE, SECTOR_SIZE, SECTOR_GROUP_SIZE, SECTOR_SIZE,
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
}, },
util::{array_ref, array_ref_mut, digest::sha1_hash}, util::{array_ref, array_ref_mut, digest::sha1_hash},
}; };

View File

@ -2,7 +2,7 @@
use std::{ffi::CStr, str::from_utf8}; use std::{ffi::CStr, str::from_utf8};
use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, big_endian::*};
use crate::{common::MagicBytes, util::static_assert}; use crate::{common::MagicBytes, util::static_assert};
@ -166,11 +166,7 @@ impl BootHeader {
/// Offset within the partition to the main DOL. /// Offset within the partition to the main DOL.
#[inline] #[inline]
pub fn dol_offset(&self, is_wii: bool) -> u64 { pub fn dol_offset(&self, is_wii: bool) -> u64 {
if is_wii { if is_wii { self.dol_offset.get() as u64 * 4 } else { self.dol_offset.get() as u64 }
self.dol_offset.get() as u64 * 4
} else {
self.dol_offset.get() as u64
}
} }
/// Set the offset within the partition to the main DOL. /// Set the offset within the partition to the main DOL.
@ -186,11 +182,7 @@ impl BootHeader {
/// Offset within the partition to the file system table (FST). /// Offset within the partition to the file system table (FST).
#[inline] #[inline]
pub fn fst_offset(&self, is_wii: bool) -> u64 { pub fn fst_offset(&self, is_wii: bool) -> u64 {
if is_wii { if is_wii { self.fst_offset.get() as u64 * 4 } else { self.fst_offset.get() as u64 }
self.fst_offset.get() as u64 * 4
} else {
self.fst_offset.get() as u64
}
} }
/// Set the offset within the partition to the file system table (FST). /// Set the offset within the partition to the file system table (FST).
@ -206,11 +198,7 @@ impl BootHeader {
/// Size of the file system table (FST). /// Size of the file system table (FST).
#[inline] #[inline]
pub fn fst_size(&self, is_wii: bool) -> u64 { pub fn fst_size(&self, is_wii: bool) -> u64 {
if is_wii { if is_wii { self.fst_size.get() as u64 * 4 } else { self.fst_size.get() as u64 }
self.fst_size.get() as u64 * 4
} else {
self.fst_size.get() as u64
}
} }
/// Set the size of the file system table (FST). /// Set the size of the file system table (FST).
@ -226,11 +214,7 @@ impl BootHeader {
/// Maximum size of the file system table (FST) across multi-disc games. /// Maximum size of the file system table (FST) across multi-disc games.
#[inline] #[inline]
pub fn fst_max_size(&self, is_wii: bool) -> u64 { pub fn fst_max_size(&self, is_wii: bool) -> u64 {
if is_wii { if is_wii { self.fst_max_size.get() as u64 * 4 } else { self.fst_max_size.get() as u64 }
self.fst_max_size.get() as u64 * 4
} else {
self.fst_max_size.get() as u64
}
} }
/// Set the maximum size of the file system table (FST) across multi-disc games. /// Set the maximum size of the file system table (FST) across multi-disc games.

View File

@ -13,16 +13,17 @@ use crossbeam_channel::{Receiver, Sender};
use crossbeam_utils::sync::WaitGroup; use crossbeam_utils::sync::WaitGroup;
use lru::LruCache; use lru::LruCache;
use polonius_the_crab::{polonius, polonius_return}; use polonius_the_crab::{polonius, polonius_return};
use simple_moving_average::{SingleSumSMA, SMA}; use simple_moving_average::{SMA, SingleSumSMA};
use tracing::{debug, error, instrument, span, Level}; use tracing::{Level, debug, error, instrument, span};
use zerocopy::FromZeros; use zerocopy::FromZeros;
use crate::{ use crate::{
IoResultContext,
common::PartitionInfo, common::PartitionInfo,
disc::{ disc::{
hashes::{hash_sector_group, GroupHashes},
wii::HASHES_SIZE,
DiscHeader, SECTOR_GROUP_SIZE, SECTOR_SIZE, DiscHeader, SECTOR_GROUP_SIZE, SECTOR_SIZE,
hashes::{GroupHashes, hash_sector_group},
wii::HASHES_SIZE,
}, },
io::{ io::{
block::{Block, BlockKind, BlockReader}, block::{Block, BlockKind, BlockReader},
@ -33,7 +34,6 @@ use crate::{
aes::{decrypt_sector, encrypt_sector}, aes::{decrypt_sector, encrypt_sector},
array_ref_mut, array_ref_mut,
}, },
IoResultContext,
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View File

@ -10,20 +10,21 @@ use tracing::warn;
use zerocopy::{FromBytes, IntoBytes}; use zerocopy::{FromBytes, IntoBytes};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{PartitionInfo, PartitionKind}, common::{PartitionInfo, PartitionKind},
disc::{ disc::{
BB2_OFFSET, BOOT_SIZE, BootHeader, DL_DVD_SIZE, DiscHeader, MINI_DVD_SIZE,
SECTOR_GROUP_SIZE, SECTOR_SIZE, SL_DVD_SIZE,
direct::{DirectDiscReader, DirectDiscReaderMode}, direct::{DirectDiscReader, DirectDiscReaderMode},
fst::{Fst, NodeKind}, fst::{Fst, NodeKind},
gcn::{read_fst, PartitionReaderGC}, gcn::{PartitionReaderGC, read_fst},
preloader::{ preloader::{
fetch_sector_group, Preloader, SectorGroup, SectorGroupLoader, SectorGroupRequest, Preloader, SectorGroup, SectorGroupLoader, SectorGroupRequest, fetch_sector_group,
}, },
wii::{ wii::{
PartitionReaderWii, WiiPartEntry, WiiPartGroup, WiiPartitionHeader, REGION_OFFSET, PartitionReaderWii, REGION_OFFSET, REGION_SIZE, WII_PART_GROUP_OFF, WiiPartEntry,
REGION_SIZE, WII_PART_GROUP_OFF, WiiPartGroup, WiiPartitionHeader,
}, },
BootHeader, DiscHeader, BB2_OFFSET, BOOT_SIZE, DL_DVD_SIZE, MINI_DVD_SIZE,
SECTOR_GROUP_SIZE, SECTOR_SIZE, SL_DVD_SIZE,
}, },
io::block::BlockReader, io::block::BlockReader,
read::{DiscMeta, DiscOptions, PartitionEncryption, PartitionOptions, PartitionReader}, read::{DiscMeta, DiscOptions, PartitionEncryption, PartitionOptions, PartitionReader},
@ -31,7 +32,6 @@ use crate::{
array_ref, impl_read_for_bufread, array_ref, impl_read_for_bufread,
read::{read_arc, read_from, read_vec}, read::{read_arc, read_from, read_vec},
}, },
Error, Result, ResultContext,
}; };
pub struct DiscReader { pub struct DiscReader {

View File

@ -8,14 +8,15 @@ use std::{
sync::Arc, sync::Arc,
}; };
use zerocopy::{big_endian::*, FromBytes, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout, big_endian::*};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{HashBytes, KeyBytes, PartitionInfo}, common::{HashBytes, KeyBytes, PartitionInfo},
disc::{ disc::{
gcn::{read_part_meta, PartitionReaderGC},
preloader::{fetch_sector_group, Preloader, SectorGroup, SectorGroupRequest},
SECTOR_GROUP_SIZE, SECTOR_SIZE, SECTOR_GROUP_SIZE, SECTOR_SIZE,
gcn::{PartitionReaderGC, read_part_meta},
preloader::{Preloader, SectorGroup, SectorGroupRequest, fetch_sector_group},
}, },
io::block::BlockReader, io::block::BlockReader,
read::{PartitionEncryption, PartitionMeta, PartitionOptions, PartitionReader}, read::{PartitionEncryption, PartitionMeta, PartitionOptions, PartitionReader},
@ -27,7 +28,6 @@ use crate::{
read::{read_arc, read_arc_slice}, read::{read_arc, read_arc_slice},
static_assert, static_assert,
}, },
Error, Result, ResultContext,
}; };
/// Size in bytes of the hashes block in a Wii disc sector /// Size in bytes of the hashes block in a Wii disc sector

View File

@ -8,15 +8,15 @@ use dyn_clone::DynClone;
use rayon::prelude::*; use rayon::prelude::*;
use crate::{ use crate::{
Error, Result, ResultContext,
common::PartitionInfo, common::PartitionInfo,
disc::{ disc::{
SECTOR_SIZE,
reader::DiscReader, reader::DiscReader,
wii::{HASHES_SIZE, SECTOR_DATA_SIZE}, wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
SECTOR_SIZE,
}, },
util::{aes::decrypt_sector_b2b, array_ref, array_ref_mut, lfg::LaggedFibonacci}, util::{aes::decrypt_sector_b2b, array_ref, array_ref_mut, lfg::LaggedFibonacci},
write::{DiscFinalization, DiscWriterWeight, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, ProcessOptions},
Error, Result, ResultContext,
}; };
/// A callback for writing disc data. /// A callback for writing disc data.

View File

@ -3,10 +3,11 @@ use std::{fs, io, io::Read, path::Path};
use dyn_clone::DynClone; use dyn_clone::DynClone;
use crate::{ use crate::{
Error, Result, ResultContext,
common::{Format, KeyBytes, MagicBytes, PartitionInfo}, common::{Format, KeyBytes, MagicBytes, PartitionInfo},
disc::{ disc::{
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
DiscHeader, GCN_MAGIC, SECTOR_SIZE, WII_MAGIC, DiscHeader, GCN_MAGIC, SECTOR_SIZE, WII_MAGIC,
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
}, },
io::{ io::{
split::SplitFileReader, split::SplitFileReader,
@ -14,7 +15,6 @@ use crate::{
}, },
read::{DiscMeta, DiscStream}, read::{DiscMeta, DiscStream},
util::{aes::decrypt_sector, array_ref, array_ref_mut, lfg::LaggedFibonacci, read::read_from}, util::{aes::decrypt_sector, array_ref, array_ref_mut, lfg::LaggedFibonacci, read::read_from},
Error, Result, ResultContext,
}; };
/// Block reader trait for reading disc images. /// Block reader trait for reading disc images.
@ -45,7 +45,7 @@ pub fn new(mut stream: Box<dyn DiscStream>) -> Result<Box<dyn BlockReader>> {
return Err(Error::DiscFormat("GCZ support is disabled".to_string())); return Err(Error::DiscFormat("GCZ support is disabled".to_string()));
} }
Some(Format::Nfs) => { Some(Format::Nfs) => {
return Err(Error::DiscFormat("NFS requires a filesystem path".to_string())) return Err(Error::DiscFormat("NFS requires a filesystem path".to_string()));
} }
Some(Format::Wbfs) => crate::io::wbfs::BlockReaderWBFS::new(stream)?, Some(Format::Wbfs) => crate::io::wbfs::BlockReaderWBFS::new(stream)?,
Some(Format::Wia | Format::Rvz) => crate::io::wia::BlockReaderWIA::new(stream)?, Some(Format::Wia | Format::Rvz) => crate::io::wia::BlockReaderWIA::new(stream)?,

View File

@ -6,17 +6,18 @@ use std::{
}; };
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use zerocopy::{little_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, little_endian::*};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{Compression, Format, MagicBytes}, common::{Compression, Format, MagicBytes},
disc::{ disc::{
SECTOR_SIZE,
reader::DiscReader, reader::DiscReader,
writer::{ writer::{
check_block, par_process, read_block, BlockProcessor, BlockResult, CheckBlockResult, BlockProcessor, BlockResult, CheckBlockResult, DataCallback, DiscWriter, check_block,
DataCallback, DiscWriter, par_process, read_block,
}, },
SECTOR_SIZE,
}, },
io::{ io::{
block::{Block, BlockKind, BlockReader, CISO_MAGIC}, block::{Block, BlockKind, BlockReader, CISO_MAGIC},
@ -31,7 +32,6 @@ use crate::{
static_assert, static_assert,
}, },
write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions},
Error, Result, ResultContext,
}; };
pub const CISO_MAP_SIZE: usize = SECTOR_SIZE - 8; pub const CISO_MAP_SIZE: usize = SECTOR_SIZE - 8;

View File

@ -7,14 +7,15 @@ use std::{
use adler::adler32_slice; use adler::adler32_slice;
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use zerocopy::{little_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, little_endian::*};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{Compression, Format, MagicBytes}, common::{Compression, Format, MagicBytes},
disc::{ disc::{
reader::DiscReader,
writer::{par_process, read_block, BlockProcessor, BlockResult, DataCallback, DiscWriter},
SECTOR_SIZE, SECTOR_SIZE,
reader::DiscReader,
writer::{BlockProcessor, BlockResult, DataCallback, DiscWriter, par_process, read_block},
}, },
io::block::{Block, BlockKind, BlockReader, GCZ_MAGIC}, io::block::{Block, BlockKind, BlockReader, GCZ_MAGIC},
read::{DiscMeta, DiscStream}, read::{DiscMeta, DiscStream},
@ -25,7 +26,6 @@ use crate::{
static_assert, static_assert,
}, },
write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions},
Error, Result, ResultContext,
}; };
/// GCZ header (little endian) /// GCZ header (little endian)

View File

@ -4,17 +4,17 @@ use std::{
}; };
use crate::{ use crate::{
Result, ResultContext,
common::Format, common::Format,
disc::{ disc::{
SECTOR_SIZE,
reader::DiscReader, reader::DiscReader,
writer::{DataCallback, DiscWriter}, writer::{DataCallback, DiscWriter},
SECTOR_SIZE,
}, },
io::block::{Block, BlockKind, BlockReader}, io::block::{Block, BlockKind, BlockReader},
read::{DiscMeta, DiscStream}, read::{DiscMeta, DiscStream},
util::digest::DigestManager, util::digest::DigestManager,
write::{DiscFinalization, DiscWriterWeight, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, ProcessOptions},
Result, ResultContext,
}; };
#[derive(Clone)] #[derive(Clone)]

View File

@ -7,9 +7,10 @@ use std::{
sync::Arc, sync::Arc,
}; };
use zerocopy::{big_endian::U32, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, big_endian::U32};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{Format, KeyBytes, MagicBytes}, common::{Format, KeyBytes, MagicBytes},
disc::SECTOR_SIZE, disc::SECTOR_SIZE,
io::{ io::{
@ -18,7 +19,6 @@ use crate::{
}, },
read::DiscMeta, read::DiscMeta,
util::{aes::aes_cbc_decrypt, array_ref_mut, read::read_arc, static_assert}, util::{aes::aes_cbc_decrypt, array_ref_mut, read::read_arc, static_assert},
Error, Result, ResultContext,
}; };
pub const NFS_END_MAGIC: MagicBytes = *b"SGGE"; pub const NFS_END_MAGIC: MagicBytes = *b"SGGE";

View File

@ -5,27 +5,27 @@ use std::{
}; };
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use zerocopy::{big_endian::U32, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, big_endian::U32};
use crate::{ use crate::{
build::gc::{insert_junk_data, FileCallback, GCPartitionStream, WriteInfo, WriteKind}, Error, Result, ResultContext,
build::gc::{FileCallback, GCPartitionStream, WriteInfo, WriteKind, insert_junk_data},
common::{Compression, Format, MagicBytes, PartitionKind}, common::{Compression, Format, MagicBytes, PartitionKind},
disc::{ disc::{
BB2_OFFSET, BootHeader, DiscHeader, SECTOR_SIZE,
fst::Fst, fst::Fst,
gcn::{read_dol, read_fst}, gcn::{read_dol, read_fst},
reader::DiscReader, reader::DiscReader,
writer::{DataCallback, DiscWriter}, writer::{DataCallback, DiscWriter},
BootHeader, DiscHeader, BB2_OFFSET, SECTOR_SIZE,
}, },
io::block::{Block, BlockKind, BlockReader, TGC_MAGIC}, io::block::{Block, BlockKind, BlockReader, TGC_MAGIC},
read::{DiscMeta, DiscStream, PartitionOptions, PartitionReader}, read::{DiscMeta, DiscStream, PartitionOptions, PartitionReader},
util::{ util::{
array_ref, Align, array_ref,
read::{read_arc, read_arc_slice, read_from, read_with_zero_fill}, read::{read_arc, read_arc_slice, read_from, read_with_zero_fill},
static_assert, Align, static_assert,
}, },
write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions},
Error, Result, ResultContext,
}; };
/// TGC header (big endian) /// TGC header (big endian)

View File

@ -6,17 +6,18 @@ use std::{
}; };
use bytes::{BufMut, Bytes, BytesMut}; use bytes::{BufMut, Bytes, BytesMut};
use zerocopy::{big_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, big_endian::*};
use crate::{ use crate::{
Error, Result, ResultContext,
common::{Compression, Format, MagicBytes}, common::{Compression, Format, MagicBytes},
disc::{ disc::{
SECTOR_SIZE,
reader::DiscReader, reader::DiscReader,
writer::{ writer::{
check_block, par_process, read_block, BlockProcessor, BlockResult, CheckBlockResult, BlockProcessor, BlockResult, CheckBlockResult, DataCallback, DiscWriter, check_block,
DataCallback, DiscWriter, par_process, read_block,
}, },
SECTOR_SIZE,
}, },
io::{ io::{
block::{Block, BlockKind, BlockReader, WBFS_MAGIC}, block::{Block, BlockKind, BlockReader, WBFS_MAGIC},
@ -30,7 +31,6 @@ use crate::{
read::{read_arc_slice, read_box_slice, read_from}, read::{read_arc_slice, read_box_slice, read_from},
}, },
write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions},
Error, Result, ResultContext,
}; };
#[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)] #[derive(Debug, Clone, PartialEq, FromBytes, IntoBytes, Immutable, KnownLayout)]

View File

@ -1,6 +1,6 @@
use std::{ use std::{
borrow::Cow, borrow::Cow,
collections::{hash_map::Entry, BTreeSet, HashMap}, collections::{BTreeSet, HashMap, hash_map::Entry},
io, io,
io::{Read, Seek, SeekFrom}, io::{Read, Seek, SeekFrom},
mem::size_of, mem::size_of,
@ -10,16 +10,17 @@ use std::{
use bytes::{Buf, BufMut, Bytes, BytesMut}; use bytes::{Buf, BufMut, Bytes, BytesMut};
use tracing::{debug, instrument, warn}; use tracing::{debug, instrument, warn};
use zerocopy::{big_endian::*, FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout, big_endian::*};
use crate::{ use crate::{
Error, IoResultContext, Result, ResultContext,
common::{Compression, Format, HashBytes, KeyBytes, MagicBytes}, common::{Compression, Format, HashBytes, KeyBytes, MagicBytes},
disc::{ disc::{
BootHeader, DiscHeader, SECTOR_SIZE,
fst::Fst, fst::Fst,
reader::DiscReader, reader::DiscReader,
wii::{HASHES_SIZE, SECTOR_DATA_SIZE}, wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
writer::{par_process, read_block, BlockProcessor, BlockResult, DataCallback, DiscWriter}, writer::{BlockProcessor, BlockResult, DataCallback, DiscWriter, par_process, read_block},
BootHeader, DiscHeader, SECTOR_SIZE,
}, },
io::{ io::{
block::{Block, BlockKind, BlockReader, RVZ_MAGIC, WIA_MAGIC}, block::{Block, BlockKind, BlockReader, RVZ_MAGIC, WIA_MAGIC},
@ -27,16 +28,16 @@ use crate::{
}, },
read::{DiscMeta, DiscStream}, read::{DiscMeta, DiscStream},
util::{ util::{
Align,
aes::decrypt_sector_data_b2b, aes::decrypt_sector_data_b2b,
array_ref, array_ref_mut, array_ref, array_ref_mut,
compress::{Compressor, DecompressionKind, Decompressor}, compress::{Compressor, DecompressionKind, Decompressor},
digest::{sha1_hash, xxh64_hash, DigestManager}, digest::{DigestManager, sha1_hash, xxh64_hash},
lfg::{LaggedFibonacci, SEED_SIZE, SEED_SIZE_BYTES}, lfg::{LaggedFibonacci, SEED_SIZE, SEED_SIZE_BYTES},
read::{read_arc_slice, read_from, read_vec}, read::{read_arc_slice, read_from, read_vec},
static_assert, Align, static_assert,
}, },
write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscFinalization, DiscWriterWeight, FormatOptions, ProcessOptions},
Error, IoResultContext, Result, ResultContext,
}; };
const WIA_VERSION: u32 = 0x01000000; const WIA_VERSION: u32 = 0x01000000;
@ -1492,7 +1493,7 @@ impl DiscWriterWIA {
return Err(Error::Other(format!( return Err(Error::Other(format!(
"Unsupported compression for WIA/RVZ: {}", "Unsupported compression for WIA/RVZ: {}",
options.compression options.compression
))) )));
} }
}; };
let compr_data = compr_data(options.compression).context("Building compression data")?; let compr_data = compr_data(options.compression).context("Building compression data")?;

View File

@ -9,17 +9,17 @@ use dyn_clone::DynClone;
use zerocopy::FromBytes; use zerocopy::FromBytes;
use crate::{ use crate::{
Result,
common::{Compression, Format, PartitionInfo, PartitionKind}, common::{Compression, Format, PartitionInfo, PartitionKind},
disc, disc,
disc::{ disc::{
ApploaderHeader, BB2_OFFSET, BI2_SIZE, BOOT_SIZE, BootHeader, DebugHeader, DiscHeader,
DolHeader,
fst::{Fst, Node}, fst::{Fst, Node},
wii::{ContentMetadata, Ticket, TmdHeader, H3_TABLE_SIZE, REGION_SIZE}, wii::{ContentMetadata, H3_TABLE_SIZE, REGION_SIZE, Ticket, TmdHeader},
ApploaderHeader, BootHeader, DebugHeader, DiscHeader, DolHeader, BB2_OFFSET, BI2_SIZE,
BOOT_SIZE,
}, },
io::block, io::block,
util::{array_ref, WindowedReader}, util::{WindowedReader, array_ref},
Result,
}; };
/// Wii partition encryption mode. /// Wii partition encryption mode.

View File

@ -3,8 +3,8 @@ use tracing::instrument;
use crate::{ use crate::{
common::KeyBytes, common::KeyBytes,
disc::{ disc::{
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
SECTOR_SIZE, SECTOR_SIZE,
wii::{HASHES_SIZE, SECTOR_DATA_SIZE},
}, },
util::array_ref, util::array_ref,
}; };
@ -32,7 +32,7 @@ pub fn aes_cbc_encrypt(key: &KeyBytes, iv: &KeyBytes, data: &mut [u8]) {
assert_eq!(data.len() % 16, 0); assert_eq!(data.len() % 16, 0);
#[cfg(not(feature = "openssl"))] #[cfg(not(feature = "openssl"))]
{ {
use aes::cipher::{block_padding::NoPadding, BlockModeEncrypt, KeyIvInit}; use aes::cipher::{BlockModeEncrypt, KeyIvInit, block_padding::NoPadding};
<cbc::Encryptor<aes::Aes128>>::new(key.into(), iv.into()) <cbc::Encryptor<aes::Aes128>>::new(key.into(), iv.into())
.encrypt_padded::<NoPadding>(data, data.len()) .encrypt_padded::<NoPadding>(data, data.len())
.unwrap(); .unwrap();
@ -57,7 +57,7 @@ pub fn aes_cbc_decrypt(key: &KeyBytes, iv: &KeyBytes, data: &mut [u8]) {
assert_eq!(data.len() % 16, 0); assert_eq!(data.len() % 16, 0);
#[cfg(not(feature = "openssl"))] #[cfg(not(feature = "openssl"))]
{ {
use aes::cipher::{block_padding::NoPadding, BlockModeDecrypt, KeyIvInit}; use aes::cipher::{BlockModeDecrypt, KeyIvInit, block_padding::NoPadding};
<cbc::Decryptor<aes::Aes128>>::new(key.into(), iv.into()) <cbc::Decryptor<aes::Aes128>>::new(key.into(), iv.into())
.decrypt_padded::<NoPadding>(data) .decrypt_padded::<NoPadding>(data)
.unwrap(); .unwrap();
@ -83,7 +83,7 @@ pub fn aes_cbc_decrypt_b2b(key: &KeyBytes, iv: &KeyBytes, data: &[u8], out: &mut
assert_eq!(data.len(), out.len()); assert_eq!(data.len(), out.len());
#[cfg(not(feature = "openssl"))] #[cfg(not(feature = "openssl"))]
{ {
use aes::cipher::{block_padding::NoPadding, BlockModeDecrypt, KeyIvInit}; use aes::cipher::{BlockModeDecrypt, KeyIvInit, block_padding::NoPadding};
<cbc::Decryptor<aes::Aes128>>::new(key.into(), iv.into()) <cbc::Decryptor<aes::Aes128>>::new(key.into(), iv.into())
.decrypt_padded_b2b::<NoPadding>(data, out) .decrypt_padded_b2b::<NoPadding>(data, out)
.unwrap(); .unwrap();

View File

@ -3,9 +3,9 @@ use std::{io, io::Read};
use tracing::instrument; use tracing::instrument;
use crate::{ use crate::{
Error, Result,
common::Compression, common::Compression,
io::wia::{WIACompression, WIADisc}, io::wia::{WIACompression, WIADisc},
Error, Result,
}; };
pub struct Decompressor { pub struct Decompressor {

View File

@ -7,7 +7,7 @@ use std::{
use bytes::Buf; use bytes::Buf;
use tracing::instrument; use tracing::instrument;
use zerocopy::{transmute_ref, IntoBytes}; use zerocopy::{IntoBytes, transmute_ref};
use crate::{disc::SECTOR_SIZE, util::array_ref_mut}; use crate::{disc::SECTOR_SIZE, util::array_ref_mut};

View File

@ -3,10 +3,10 @@
use bytes::Bytes; use bytes::Bytes;
use crate::{ use crate::{
Error, Result,
common::{Compression, Format}, common::{Compression, Format},
disc, disc,
read::DiscReader, read::DiscReader,
Error, Result,
}; };
/// Options for writing a disc image. /// Options for writing a disc image.

View File

@ -4,7 +4,7 @@
//! For now, this only adds a --version/-V option which causes early-exit. //! For now, this only adds a --version/-V option which causes early-exit.
use std::ffi::OsStr; use std::ffi::OsStr;
use argp::{parser::ParseGlobalOptions, EarlyExit, FromArgs, TopLevelCommand}; use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
struct ArgsOrVersion<T>(T) struct ArgsOrVersion<T>(T)
where T: FromArgs; where T: FromArgs;

View File

@ -47,7 +47,9 @@ pub fn run(args: Args) -> nod::Result<()> {
(false, true) => PartitionEncryption::ForceEncrypted, (false, true) => PartitionEncryption::ForceEncrypted,
(false, false) => PartitionEncryption::Original, (false, false) => PartitionEncryption::Original,
(true, true) => { (true, true) => {
return Err(nod::Error::Other("Both --decrypt and --encrypt specified".to_string())) return Err(nod::Error::Other(
"Both --decrypt and --encrypt specified".to_string(),
));
} }
}, },
preloader_threads: 4, preloader_threads: 4,
@ -70,7 +72,7 @@ pub fn run(args: Args) -> nod::Result<()> {
return Err(nod::Error::Other(format!( return Err(nod::Error::Other(format!(
"Unknown file extension: {}", "Unknown file extension: {}",
path_display(&args.out) path_display(&args.out)
))) )));
} }
None => Format::Iso, None => Format::Iso,
}; };

View File

@ -7,9 +7,9 @@ use std::{
use argp::FromArgs; use argp::FromArgs;
use indicatif::{ProgressBar, ProgressState, ProgressStyle}; use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use nod::{ use nod::{
Result, ResultContext,
read::{DiscOptions, DiscReader, PartitionEncryption}, read::{DiscOptions, DiscReader, PartitionEncryption},
write::{DiscWriter, FormatOptions, ProcessOptions}, write::{DiscWriter, FormatOptions, ProcessOptions},
Result, ResultContext,
}; };
use crate::util::{redump, redump::GameResult}; use crate::util::{redump, redump::GameResult};

View File

@ -7,10 +7,10 @@ use std::{
use argp::FromArgs; use argp::FromArgs;
use nod::{ use nod::{
ResultContext,
common::PartitionKind, common::PartitionKind,
disc::fst::{Fst, Node}, disc::fst::{Fst, Node},
read::{DiscOptions, DiscReader, PartitionMeta, PartitionOptions, PartitionReader}, read::{DiscOptions, DiscReader, PartitionMeta, PartitionOptions, PartitionReader},
ResultContext,
}; };
use size::{Base, Size}; use size::{Base, Size};
use zerocopy::IntoBytes; use zerocopy::IntoBytes;

View File

@ -10,11 +10,12 @@ use std::{
use argp::FromArgs; use argp::FromArgs;
use nod::{ use nod::{
ResultContext,
build::gc::{FileCallback, FileInfo, GCPartitionBuilder, PartitionOverrides}, build::gc::{FileCallback, FileInfo, GCPartitionBuilder, PartitionOverrides},
common::PartitionKind, common::PartitionKind,
disc::{ disc::{
fst::Fst, BootHeader, DiscHeader, BB2_OFFSET, BI2_SIZE, BOOT_SIZE, MINI_DVD_SIZE, BB2_OFFSET, BI2_SIZE, BOOT_SIZE, BootHeader, DiscHeader, MINI_DVD_SIZE, SECTOR_SIZE,
SECTOR_SIZE, fst::Fst,
}, },
read::{ read::{
DiscOptions, DiscReader, PartitionEncryption, PartitionMeta, PartitionOptions, DiscOptions, DiscReader, PartitionEncryption, PartitionMeta, PartitionOptions,
@ -22,7 +23,6 @@ use nod::{
}, },
util::lfg::LaggedFibonacci, util::lfg::LaggedFibonacci,
write::{DiscWriter, FormatOptions, ProcessOptions}, write::{DiscWriter, FormatOptions, ProcessOptions},
ResultContext,
}; };
use tracing::{debug, error, info, warn}; use tracing::{debug, error, info, warn};
use zerocopy::{FromBytes, FromZeros}; use zerocopy::{FromBytes, FromZeros};
@ -188,7 +188,7 @@ pub fn run(args: Args) -> nod::Result<()> {
} }
Err(e) => { Err(e) => {
return Err(e) return Err(e)
.context(format!("Failed to get metadata for {}", file_path.display())) .context(format!("Failed to get metadata for {}", file_path.display()));
} }
}; };
if metadata.is_dir() { if metadata.is_dir() {

View File

@ -1,6 +1,6 @@
pub mod convert; pub mod convert;
pub mod dat; pub mod dat;
pub mod extract; pub mod extract;
pub mod gen; pub mod r#gen;
pub mod info; pub mod info;
pub mod verify; pub mod verify;

View File

@ -41,7 +41,9 @@ pub fn run(args: Args) -> nod::Result<()> {
(false, true) => PartitionEncryption::ForceEncrypted, (false, true) => PartitionEncryption::ForceEncrypted,
(false, false) => PartitionEncryption::Original, (false, false) => PartitionEncryption::Original,
(true, true) => { (true, true) => {
return Err(nod::Error::Other("Both --decrypt and --encrypt specified".to_string())) return Err(nod::Error::Other(
"Both --decrypt and --encrypt specified".to_string(),
));
} }
}, },
preloader_threads: 4.min(cpus), preloader_threads: 4.min(cpus),

View File

@ -13,7 +13,7 @@ pub enum SubCommand {
Dat(cmd::dat::Args), Dat(cmd::dat::Args),
Extract(cmd::extract::Args), Extract(cmd::extract::Args),
// Gen(cmd::gen::Args), // Gen(cmd::gen::Args),
GenTest(cmd::gen::TestArgs), GenTest(cmd::r#gen::TestArgs),
Info(cmd::info::Args), Info(cmd::info::Args),
Verify(cmd::verify::Args), Verify(cmd::verify::Args),
} }
@ -24,7 +24,7 @@ pub fn run(command: SubCommand) -> nod::Result<()> {
SubCommand::Dat(c_args) => cmd::dat::run(c_args), SubCommand::Dat(c_args) => cmd::dat::run(c_args),
SubCommand::Extract(c_args) => cmd::extract::run(c_args), SubCommand::Extract(c_args) => cmd::extract::run(c_args),
// SubCommand::Gen(c_args) => cmd::gen::run(c_args), // SubCommand::Gen(c_args) => cmd::gen::run(c_args),
SubCommand::GenTest(c_args) => cmd::gen::run_test(c_args), SubCommand::GenTest(c_args) => cmd::r#gen::run_test(c_args),
SubCommand::Info(c_args) => cmd::info::run(c_args), SubCommand::Info(c_args) => cmd::info::run(c_args),
SubCommand::Verify(c_args) => cmd::verify::run(c_args), SubCommand::Verify(c_args) => cmd::verify::run(c_args),
} }

View File

@ -10,7 +10,7 @@ use std::{env, error::Error, ffi::OsStr, fmt, path::PathBuf, str::FromStr};
use argp::{FromArgValue, FromArgs}; use argp::{FromArgValue, FromArgs};
use enable_ansi_support::enable_ansi_support; use enable_ansi_support::enable_ansi_support;
use nodtool::{run, SubCommand}; use nodtool::{SubCommand, run};
use supports_color::Stream; use supports_color::Stream;
#[derive(FromArgs, Debug)] #[derive(FromArgs, Debug)]
@ -93,7 +93,7 @@ fn main() {
// Try to enable ANSI support on Windows. // Try to enable ANSI support on Windows.
let _ = enable_ansi_support(); let _ = enable_ansi_support();
// Disable isatty check for supports-color. (e.g. when used with ninja) // Disable isatty check for supports-color. (e.g. when used with ninja)
env::set_var("IGNORE_IS_TERMINAL", "1"); unsafe { env::set_var("IGNORE_IS_TERMINAL", "1") };
supports_color::on(Stream::Stdout).is_some_and(|c| c.has_basic) supports_color::on(Stream::Stdout).is_some_and(|c| c.has_basic)
}; };

View File

@ -5,7 +5,7 @@ pub mod shared;
use std::{ use std::{
fmt, fmt,
fmt::Write, fmt::Write,
path::{Path, MAIN_SEPARATOR}, path::{MAIN_SEPARATOR, Path},
}; };
pub fn path_display(path: &Path) -> PathDisplay { PathDisplay { path } } pub fn path_display(path: &Path) -> PathDisplay { PathDisplay { path } }

View File

@ -7,11 +7,11 @@ use std::{
use indicatif::{ProgressBar, ProgressState, ProgressStyle}; use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use nod::{ use nod::{
Result, ResultContext,
common::Compression, common::Compression,
disc::DiscHeader, disc::DiscHeader,
read::{DiscMeta, DiscOptions, DiscReader, PartitionEncryption}, read::{DiscMeta, DiscOptions, DiscReader, PartitionEncryption},
write::{DiscWriter, DiscWriterWeight, FormatOptions, ProcessOptions}, write::{DiscWriter, DiscWriterWeight, FormatOptions, ProcessOptions},
Result, ResultContext,
}; };
use size::Size; use size::Size;