mirror of
https://github.com/encounter/nod-rs.git
synced 2025-12-10 05:57:47 +00:00
run cargo fmt
This commit is contained in:
@@ -129,7 +129,9 @@ impl GCPartitionBuilder {
|
|||||||
|
|
||||||
/// A junk file exists in the FST, but is excluded from the disc layout, so junk data will be
|
/// A junk file exists in the FST, but is excluded from the disc layout, so junk data will be
|
||||||
/// written in its place.
|
/// written in its place.
|
||||||
pub fn add_junk_file(&mut self, name: String) { self.junk_files.push(name); }
|
pub fn add_junk_file(&mut self, name: String) {
|
||||||
|
self.junk_files.push(name);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(
|
pub fn build(
|
||||||
&self,
|
&self,
|
||||||
@@ -630,7 +632,9 @@ impl GCPartitionWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_cloneable_stream<Cb>(self, file_callback: Cb) -> Result<Box<dyn DiscStream>>
|
pub fn into_cloneable_stream<Cb>(self, file_callback: Cb) -> Result<Box<dyn DiscStream>>
|
||||||
where Cb: FileCallback + Clone + 'static {
|
where
|
||||||
|
Cb: FileCallback + Clone + 'static,
|
||||||
|
{
|
||||||
Ok(Box::new(CloneableStream::new(GCPartitionStream::new(
|
Ok(Box::new(CloneableStream::new(GCPartitionStream::new(
|
||||||
file_callback,
|
file_callback,
|
||||||
Arc::from(self.write_info),
|
Arc::from(self.write_info),
|
||||||
@@ -641,7 +645,9 @@ impl GCPartitionWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_non_cloneable_stream<Cb>(self, file_callback: Cb) -> Result<Box<dyn DiscStream>>
|
pub fn into_non_cloneable_stream<Cb>(self, file_callback: Cb) -> Result<Box<dyn DiscStream>>
|
||||||
where Cb: FileCallback + 'static {
|
where
|
||||||
|
Cb: FileCallback + 'static,
|
||||||
|
{
|
||||||
Ok(Box::new(NonCloneableStream::new(GCPartitionStream::new(
|
Ok(Box::new(NonCloneableStream::new(GCPartitionStream::new(
|
||||||
file_callback,
|
file_callback,
|
||||||
Arc::from(self.write_info),
|
Arc::from(self.write_info),
|
||||||
@@ -658,7 +664,8 @@ struct WriteCursor<W> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<W> WriteCursor<W>
|
impl<W> WriteCursor<W>
|
||||||
where W: Write
|
where
|
||||||
|
W: Write,
|
||||||
{
|
{
|
||||||
fn write_zeroes_until(&mut self, until: u64) -> io::Result<()> {
|
fn write_zeroes_until(&mut self, until: u64) -> io::Result<()> {
|
||||||
static ZEROES: [u8; 0x1000] = [0u8; 0x1000];
|
static ZEROES: [u8; 0x1000] = [0u8; 0x1000];
|
||||||
@@ -673,7 +680,8 @@ where W: Write
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<W> Write for WriteCursor<W>
|
impl<W> Write for WriteCursor<W>
|
||||||
where W: Write
|
where
|
||||||
|
W: Write,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
@@ -683,7 +691,9 @@ where W: Write
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
self.inner.flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -708,14 +718,19 @@ impl<Cb> GCPartitionStream<Cb> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_position(&mut self, pos: u64) { self.pos = pos; }
|
pub fn set_position(&mut self, pos: u64) {
|
||||||
|
self.pos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> u64 { self.size }
|
pub fn len(&self) -> u64 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Cb> Read for GCPartitionStream<Cb>
|
impl<Cb> Read for GCPartitionStream<Cb>
|
||||||
where Cb: FileCallback
|
where
|
||||||
|
Cb: FileCallback,
|
||||||
{
|
{
|
||||||
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
||||||
if self.pos >= self.size {
|
if self.pos >= self.size {
|
||||||
@@ -784,7 +799,9 @@ impl<Cb> Seek for GCPartitionStream<Cb> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn gcm_align(n: u64) -> u64 { (n + 31) & !3 }
|
fn gcm_align(n: u64) -> u64 {
|
||||||
|
(n + 31) & !3
|
||||||
|
}
|
||||||
|
|
||||||
fn sort_files(files: &mut [WriteInfo]) -> Result<()> {
|
fn sort_files(files: &mut [WriteInfo]) -> Result<()> {
|
||||||
files.sort_unstable_by_key(|info| (info.offset, info.size));
|
files.sort_unstable_by_key(|info| (info.offset, info.size));
|
||||||
|
|||||||
@@ -66,7 +66,9 @@ impl DirectDiscReader {
|
|||||||
self.mode = mode;
|
self.mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_inner(self) -> Box<dyn BlockReader> { self.io }
|
pub fn into_inner(self) -> Box<dyn BlockReader> {
|
||||||
|
self.io
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufRead for DirectDiscReader {
|
impl BufRead for DirectDiscReader {
|
||||||
@@ -115,7 +117,9 @@ impl BufRead for DirectDiscReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.pos += amt as u64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_read_for_bufread!(DirectDiscReader);
|
impl_read_for_bufread!(DirectDiscReader);
|
||||||
@@ -135,11 +139,17 @@ impl Seek for DirectDiscReader {
|
|||||||
Ok(self.pos)
|
Ok(self.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_position(&mut self) -> io::Result<u64> { Ok(self.pos) }
|
fn stream_position(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartitionReader for DirectDiscReader {
|
impl PartitionReader for DirectDiscReader {
|
||||||
fn is_wii(&self) -> bool { unimplemented!() }
|
fn is_wii(&self) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&mut self) -> Result<PartitionMeta> { unimplemented!() }
|
fn meta(&mut self) -> Result<PartitionMeta> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,11 +77,15 @@ impl Node {
|
|||||||
|
|
||||||
/// Whether the node is a file.
|
/// Whether the node is a file.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_file(&self) -> bool { self.kind == 0 }
|
pub fn is_file(&self) -> bool {
|
||||||
|
self.kind == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the node is a directory.
|
/// Whether the node is a directory.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_dir(&self) -> bool { self.kind == 1 }
|
pub fn is_dir(&self) -> bool {
|
||||||
|
self.kind == 1
|
||||||
|
}
|
||||||
|
|
||||||
/// Offset in the string table to the filename.
|
/// Offset in the string table to the filename.
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -120,11 +124,15 @@ impl Node {
|
|||||||
///
|
///
|
||||||
/// Number of child files and directories recursively is `length - offset`.
|
/// Number of child files and directories recursively is `length - offset`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn length(&self) -> u32 { self.length.get() }
|
pub fn length(&self) -> u32 {
|
||||||
|
self.length.get()
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the length of the node. See [`Node::length`] for details.
|
/// Set the length of the node. See [`Node::length`] for details.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_length(&mut self, length: u32) { self.length.set(length); }
|
pub fn set_length(&mut self, length: u32) {
|
||||||
|
self.length.set(length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A view into the file system table (FST).
|
/// A view into the file system table (FST).
|
||||||
@@ -154,7 +162,9 @@ impl<'a> Fst<'a> {
|
|||||||
|
|
||||||
/// Iterate over the nodes in the FST.
|
/// Iterate over the nodes in the FST.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter(&self) -> FstIter<'_> { FstIter { fst: self.clone(), idx: 1, segments: vec![] } }
|
pub fn iter(&self) -> FstIter<'_> {
|
||||||
|
FstIter { fst: self.clone(), idx: 1, segments: vec![] }
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the name of a node.
|
/// Get the name of a node.
|
||||||
pub fn get_name(&self, node: Node) -> Result<Cow<'a, str>, String> {
|
pub fn get_name(&self, node: Node) -> Result<Cow<'a, str>, String> {
|
||||||
@@ -209,7 +219,9 @@ impl<'a> Fst<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Count the number of files in the FST.
|
/// Count the number of files in the FST.
|
||||||
pub fn num_files(&self) -> usize { self.nodes.iter().filter(|n| n.is_file()).count() }
|
pub fn num_files(&self) -> usize {
|
||||||
|
self.nodes.iter().filter(|n| n.is_file()).count()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over the nodes in an FST.
|
/// Iterator over the nodes in an FST.
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ impl BufRead for PartitionReaderGC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.pos += amt as u64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_read_for_bufread!(PartitionReaderGC);
|
impl_read_for_bufread!(PartitionReaderGC);
|
||||||
@@ -99,11 +101,15 @@ impl Seek for PartitionReaderGC {
|
|||||||
Ok(self.pos)
|
Ok(self.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_position(&mut self) -> io::Result<u64> { Ok(self.pos) }
|
fn stream_position(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartitionReader for PartitionReaderGC {
|
impl PartitionReader for PartitionReaderGC {
|
||||||
fn is_wii(&self) -> bool { false }
|
fn is_wii(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&mut self) -> Result<PartitionMeta> {
|
fn meta(&mut self) -> Result<PartitionMeta> {
|
||||||
if let Some(meta) = &self.meta {
|
if let Some(meta) = &self.meta {
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ static_assert!(size_of::<DiscHeader>() == 0x400);
|
|||||||
impl DiscHeader {
|
impl DiscHeader {
|
||||||
/// Game ID as a string.
|
/// Game ID as a string.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn game_id_str(&self) -> &str { from_utf8(&self.game_id).unwrap_or("[invalid]") }
|
pub fn game_id_str(&self) -> &str {
|
||||||
|
from_utf8(&self.game_id).unwrap_or("[invalid]")
|
||||||
|
}
|
||||||
|
|
||||||
/// Game title as a string.
|
/// Game title as a string.
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -102,19 +104,27 @@ impl DiscHeader {
|
|||||||
|
|
||||||
/// Whether this is a GameCube disc.
|
/// Whether this is a GameCube disc.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_gamecube(&self) -> bool { self.gcn_magic == GCN_MAGIC }
|
pub fn is_gamecube(&self) -> bool {
|
||||||
|
self.gcn_magic == GCN_MAGIC
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether this is a Wii disc.
|
/// Whether this is a Wii disc.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_wii(&self) -> bool { self.wii_magic == WII_MAGIC }
|
pub fn is_wii(&self) -> bool {
|
||||||
|
self.wii_magic == WII_MAGIC
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the disc has partition data hashes.
|
/// Whether the disc has partition data hashes.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_partition_hashes(&self) -> bool { self.no_partition_hashes == 0 }
|
pub fn has_partition_hashes(&self) -> bool {
|
||||||
|
self.no_partition_hashes == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether the disc has partition data encryption.
|
/// Whether the disc has partition data encryption.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn has_partition_encryption(&self) -> bool { self.no_partition_encryption == 0 }
|
pub fn has_partition_encryption(&self) -> bool {
|
||||||
|
self.no_partition_encryption == 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The debug block of a disc partition.
|
/// The debug block of a disc partition.
|
||||||
|
|||||||
@@ -172,7 +172,9 @@ impl PreloaderCache {
|
|||||||
self.inflight.remove(&request);
|
self.inflight.remove(&request);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove(&mut self, request: &SectorGroupRequest) { self.inflight.remove(request); }
|
fn remove(&mut self, request: &SectorGroupRequest) {
|
||||||
|
self.inflight.remove(request);
|
||||||
|
}
|
||||||
|
|
||||||
fn contains(&self, request: &SectorGroupRequest) -> bool {
|
fn contains(&self, request: &SectorGroupRequest) -> bool {
|
||||||
self.lru_cache.contains(request) || self.inflight.contains_key(request)
|
self.lru_cache.contains(request) || self.inflight.contains_key(request)
|
||||||
@@ -325,7 +327,9 @@ impl Preloader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn map_poisoned<T>(_: std::sync::PoisonError<T>) -> io::Error { io::Error::other("Mutex poisoned") }
|
fn map_poisoned<T>(_: std::sync::PoisonError<T>) -> io::Error {
|
||||||
|
io::Error::other("Mutex poisoned")
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SectorGroupLoader {
|
pub struct SectorGroupLoader {
|
||||||
io: Box<dyn BlockReader>,
|
io: Box<dyn BlockReader>,
|
||||||
|
|||||||
@@ -163,13 +163,19 @@ impl DiscReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reset(&mut self) { self.pos = 0; }
|
pub fn reset(&mut self) {
|
||||||
|
self.pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn position(&self) -> u64 { self.pos }
|
pub fn position(&self) -> u64 {
|
||||||
|
self.pos
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disc_size(&self) -> u64 { self.size }
|
pub fn disc_size(&self) -> u64 {
|
||||||
|
self.size
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn header(&self) -> &DiscHeader {
|
pub fn header(&self) -> &DiscHeader {
|
||||||
@@ -241,7 +247,9 @@ impl DiscReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn meta(&self) -> DiscMeta { self.io.meta() }
|
pub fn meta(&self) -> DiscMeta {
|
||||||
|
self.io.meta()
|
||||||
|
}
|
||||||
|
|
||||||
/// Opens a new, decrypted partition read stream for the specified partition index.
|
/// Opens a new, decrypted partition read stream for the specified partition index.
|
||||||
pub fn open_partition(
|
pub fn open_partition(
|
||||||
@@ -400,7 +408,9 @@ impl BufRead for DiscReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.pos += amt as u64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_read_for_bufread!(DiscReader);
|
impl_read_for_bufread!(DiscReader);
|
||||||
|
|||||||
@@ -78,7 +78,9 @@ pub(crate) struct WiiPartEntry {
|
|||||||
static_assert!(size_of::<WiiPartEntry>() == 8);
|
static_assert!(size_of::<WiiPartEntry>() == 8);
|
||||||
|
|
||||||
impl WiiPartEntry {
|
impl WiiPartEntry {
|
||||||
pub(crate) fn offset(&self) -> u64 { (self.offset.get() as u64) << 2 }
|
pub(crate) fn offset(&self) -> u64 {
|
||||||
|
(self.offset.get() as u64) << 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const WII_PART_GROUP_OFF: u64 = 0x40000;
|
pub(crate) const WII_PART_GROUP_OFF: u64 = 0x40000;
|
||||||
@@ -93,7 +95,9 @@ pub(crate) struct WiiPartGroup {
|
|||||||
static_assert!(size_of::<WiiPartGroup>() == 8);
|
static_assert!(size_of::<WiiPartGroup>() == 8);
|
||||||
|
|
||||||
impl WiiPartGroup {
|
impl WiiPartGroup {
|
||||||
pub(crate) fn part_entry_off(&self) -> u64 { (self.part_entry_off.get() as u64) << 2 }
|
pub(crate) fn part_entry_off(&self) -> u64 {
|
||||||
|
(self.part_entry_off.get() as u64) << 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signed blob header
|
/// Signed blob header
|
||||||
@@ -274,28 +278,44 @@ static_assert!(size_of::<WiiPartitionHeader>() == 0x2C0);
|
|||||||
|
|
||||||
impl WiiPartitionHeader {
|
impl WiiPartitionHeader {
|
||||||
/// TMD size in bytes
|
/// TMD size in bytes
|
||||||
pub fn tmd_size(&self) -> u64 { self.tmd_size.get() as u64 }
|
pub fn tmd_size(&self) -> u64 {
|
||||||
|
self.tmd_size.get() as u64
|
||||||
|
}
|
||||||
|
|
||||||
/// TMD offset in bytes (relative to the partition start)
|
/// TMD offset in bytes (relative to the partition start)
|
||||||
pub fn tmd_off(&self) -> u64 { (self.tmd_off.get() as u64) << 2 }
|
pub fn tmd_off(&self) -> u64 {
|
||||||
|
(self.tmd_off.get() as u64) << 2
|
||||||
|
}
|
||||||
|
|
||||||
/// Certificate chain size in bytes
|
/// Certificate chain size in bytes
|
||||||
pub fn cert_chain_size(&self) -> u64 { self.cert_chain_size.get() as u64 }
|
pub fn cert_chain_size(&self) -> u64 {
|
||||||
|
self.cert_chain_size.get() as u64
|
||||||
|
}
|
||||||
|
|
||||||
/// Certificate chain offset in bytes (relative to the partition start)
|
/// Certificate chain offset in bytes (relative to the partition start)
|
||||||
pub fn cert_chain_off(&self) -> u64 { (self.cert_chain_off.get() as u64) << 2 }
|
pub fn cert_chain_off(&self) -> u64 {
|
||||||
|
(self.cert_chain_off.get() as u64) << 2
|
||||||
|
}
|
||||||
|
|
||||||
/// H3 table offset in bytes (relative to the partition start)
|
/// H3 table offset in bytes (relative to the partition start)
|
||||||
pub fn h3_table_off(&self) -> u64 { (self.h3_table_off.get() as u64) << 2 }
|
pub fn h3_table_off(&self) -> u64 {
|
||||||
|
(self.h3_table_off.get() as u64) << 2
|
||||||
|
}
|
||||||
|
|
||||||
/// H3 table size in bytes (always H3_TABLE_SIZE)
|
/// H3 table size in bytes (always H3_TABLE_SIZE)
|
||||||
pub fn h3_table_size(&self) -> u64 { H3_TABLE_SIZE as u64 }
|
pub fn h3_table_size(&self) -> u64 {
|
||||||
|
H3_TABLE_SIZE as u64
|
||||||
|
}
|
||||||
|
|
||||||
/// Data offset in bytes (relative to the partition start)
|
/// Data offset in bytes (relative to the partition start)
|
||||||
pub fn data_off(&self) -> u64 { (self.data_off.get() as u64) << 2 }
|
pub fn data_off(&self) -> u64 {
|
||||||
|
(self.data_off.get() as u64) << 2
|
||||||
|
}
|
||||||
|
|
||||||
/// Data size in bytes
|
/// Data size in bytes
|
||||||
pub fn data_size(&self) -> u64 { (self.data_size.get() as u64) << 2 }
|
pub fn data_size(&self) -> u64 {
|
||||||
|
(self.data_size.get() as u64) << 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct PartitionReaderWii {
|
pub(crate) struct PartitionReaderWii {
|
||||||
@@ -342,7 +362,9 @@ impl PartitionReaderWii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> u64 { self.partition.data_size() }
|
pub fn len(&self) -> u64 {
|
||||||
|
self.partition.data_size()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufRead for PartitionReaderWii {
|
impl BufRead for PartitionReaderWii {
|
||||||
@@ -409,7 +431,9 @@ impl BufRead for PartitionReaderWii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.pos += amt as u64;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_read_for_bufread!(PartitionReaderWii);
|
impl_read_for_bufread!(PartitionReaderWii);
|
||||||
@@ -424,7 +448,9 @@ impl Seek for PartitionReaderWii {
|
|||||||
Ok(self.pos)
|
Ok(self.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_position(&mut self) -> io::Result<u64> { Ok(self.pos) }
|
fn stream_position(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_hashes(buf: &[u8; SECTOR_GROUP_SIZE], group_idx: u32, h3_table: &[u8]) -> io::Result<()> {
|
fn verify_hashes(buf: &[u8; SECTOR_GROUP_SIZE], group_idx: u32, h3_table: &[u8]) -> io::Result<()> {
|
||||||
@@ -487,7 +513,9 @@ fn verify_hashes(buf: &[u8; SECTOR_GROUP_SIZE], group_idx: u32, h3_table: &[u8])
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PartitionReader for PartitionReaderWii {
|
impl PartitionReader for PartitionReaderWii {
|
||||||
fn is_wii(&self) -> bool { true }
|
fn is_wii(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&mut self) -> Result<PartitionMeta> {
|
fn meta(&mut self) -> Result<PartitionMeta> {
|
||||||
if let Some(meta) = &self.meta {
|
if let Some(meta) = &self.meta {
|
||||||
|
|||||||
@@ -116,7 +116,9 @@ pub const WIA_MAGIC: MagicBytes = *b"WIA\x01";
|
|||||||
pub const RVZ_MAGIC: MagicBytes = *b"RVZ\x01";
|
pub const RVZ_MAGIC: MagicBytes = *b"RVZ\x01";
|
||||||
|
|
||||||
pub fn detect<R>(stream: &mut R) -> io::Result<Option<Format>>
|
pub fn detect<R>(stream: &mut R) -> io::Result<Option<Format>>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
match read_from(stream) {
|
match read_from(stream) {
|
||||||
Ok(ref magic) => Ok(detect_internal(magic)),
|
Ok(ref magic) => Ok(detect_internal(magic)),
|
||||||
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(None),
|
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => Ok(None),
|
||||||
|
|||||||
@@ -182,7 +182,9 @@ impl BlockReader for BlockReaderGCZ {
|
|||||||
Ok(Block::new(block_idx, block_size, BlockKind::Raw))
|
Ok(Block::new(block_idx, block_size, BlockKind::Raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { self.header.block_size.get() }
|
fn block_size(&self) -> u32 {
|
||||||
|
self.header.block_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
DiscMeta {
|
DiscMeta {
|
||||||
@@ -358,7 +360,11 @@ impl DiscWriter for DiscWriterGCZ {
|
|||||||
Ok(finalization)
|
Ok(finalization)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_bound(&self) -> u64 { self.header.disc_size.get() }
|
fn progress_bound(&self) -> u64 {
|
||||||
|
self.header.disc_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
fn weight(&self) -> DiscWriterWeight { DiscWriterWeight::Heavy }
|
fn weight(&self) -> DiscWriterWeight {
|
||||||
|
DiscWriterWeight::Heavy
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ impl BlockReader for BlockReaderISO {
|
|||||||
Ok(Block::sector(sector, BlockKind::Raw))
|
Ok(Block::sector(sector, BlockKind::Raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { SECTOR_SIZE as u32 }
|
fn block_size(&self) -> u32 {
|
||||||
|
SECTOR_SIZE as u32
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
DiscMeta {
|
DiscMeta {
|
||||||
@@ -83,7 +85,11 @@ impl DiscWriter for DiscReader {
|
|||||||
Ok(finalization)
|
Ok(finalization)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_bound(&self) -> u64 { self.disc_size() }
|
fn progress_bound(&self) -> u64 {
|
||||||
|
self.disc_size()
|
||||||
|
}
|
||||||
|
|
||||||
fn weight(&self) -> DiscWriterWeight { DiscWriterWeight::Light }
|
fn weight(&self) -> DiscWriterWeight {
|
||||||
|
DiscWriterWeight::Light
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,9 @@ impl NFSHeader {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lba_ranges(&self) -> &[LBARange] { &self.lba_ranges[..self.num_lba_ranges.get() as usize] }
|
fn lba_ranges(&self) -> &[LBARange] {
|
||||||
|
&self.lba_ranges[..self.num_lba_ranges.get() as usize]
|
||||||
|
}
|
||||||
|
|
||||||
fn calculate_num_files(&self) -> u32 {
|
fn calculate_num_files(&self) -> u32 {
|
||||||
let sector_count =
|
let sector_count =
|
||||||
@@ -126,7 +128,9 @@ impl BlockReader for BlockReaderNFS {
|
|||||||
Ok(Block::sector(sector, BlockKind::PartDecrypted { hash_block: true }))
|
Ok(Block::sector(sector, BlockKind::PartDecrypted { hash_block: true }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { SECTOR_SIZE as u32 }
|
fn block_size(&self) -> u32 {
|
||||||
|
SECTOR_SIZE as u32
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
DiscMeta { format: Format::Nfs, decrypted: true, ..Default::default() }
|
DiscMeta { format: Format::Nfs, decrypted: true, ..Default::default() }
|
||||||
@@ -134,7 +138,9 @@ impl BlockReader for BlockReaderNFS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_path<P>(directory: &Path, path: P) -> PathBuf
|
fn get_path<P>(directory: &Path, path: P) -> PathBuf
|
||||||
where P: AsRef<Path> {
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
let mut buf = directory.to_path_buf();
|
let mut buf = directory.to_path_buf();
|
||||||
for component in path.as_ref().components() {
|
for component in path.as_ref().components() {
|
||||||
match component {
|
match component {
|
||||||
|
|||||||
@@ -108,7 +108,9 @@ impl NKitHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_from<R>(reader: &mut R, block_size: u32, has_junk_bits: bool) -> io::Result<Self>
|
pub fn read_from<R>(reader: &mut R, block_size: u32, has_junk_bits: bool) -> io::Result<Self>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
let version_string: [u8; 8] = read_from(reader)?;
|
let version_string: [u8; 8] = read_from(reader)?;
|
||||||
if version_string[0..7] != VERSION_PREFIX
|
if version_string[0..7] != VERSION_PREFIX
|
||||||
|| version_string[7] < b'1'
|
|| version_string[7] < b'1'
|
||||||
@@ -202,7 +204,9 @@ impl NKitHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to<W>(&self, w: &mut W) -> io::Result<()>
|
pub fn write_to<W>(&self, w: &mut W) -> io::Result<()>
|
||||||
where W: Write + ?Sized {
|
where
|
||||||
|
W: Write + ?Sized,
|
||||||
|
{
|
||||||
w.write_all(&VERSION_PREFIX)?;
|
w.write_all(&VERSION_PREFIX)?;
|
||||||
w.write_all(&[b'0' + self.version])?;
|
w.write_all(&[b'0' + self.version])?;
|
||||||
let flags = self.calc_flags();
|
let flags = self.calc_flags();
|
||||||
@@ -266,15 +270,21 @@ impl NKitHeader {
|
|||||||
pub struct JunkBits(Vec<u8>);
|
pub struct JunkBits(Vec<u8>);
|
||||||
|
|
||||||
impl JunkBits {
|
impl JunkBits {
|
||||||
pub fn new(block_size: u32) -> Self { Self(vec![0; Self::len(block_size)]) }
|
pub fn new(block_size: u32) -> Self {
|
||||||
|
Self(vec![0; Self::len(block_size)])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_from<R>(reader: &mut R, block_size: u32) -> io::Result<Self>
|
pub fn read_from<R>(reader: &mut R, block_size: u32) -> io::Result<Self>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
Ok(Self(read_vec(reader, Self::len(block_size))?))
|
Ok(Self(read_vec(reader, Self::len(block_size))?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to<W>(&self, w: &mut W) -> io::Result<()>
|
pub fn write_to<W>(&self, w: &mut W) -> io::Result<()>
|
||||||
where W: Write + ?Sized {
|
where
|
||||||
|
W: Write + ?Sized,
|
||||||
|
{
|
||||||
w.write_all(&self.0)
|
w.write_all(&self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +317,9 @@ pub struct ReadAdapter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReadAdapter<'a> {
|
impl<'a> ReadAdapter<'a> {
|
||||||
pub fn new(reader: &'a mut dyn DiscStream, offset: u64) -> Self { Self { reader, pos: offset } }
|
pub fn new(reader: &'a mut dyn DiscStream, offset: u64) -> Self {
|
||||||
|
Self { reader, pos: offset }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for ReadAdapter<'_> {
|
impl Read for ReadAdapter<'_> {
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ struct Split<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Split<T> {
|
impl<T> Split<T> {
|
||||||
fn contains(&self, pos: u64) -> bool { self.begin <= pos && pos < self.begin + self.size }
|
fn contains(&self, pos: u64) -> bool {
|
||||||
|
self.begin <= pos && pos < self.begin + self.size
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// .iso.1, .iso.2, etc.
|
// .iso.1, .iso.2, etc.
|
||||||
@@ -56,7 +58,9 @@ fn split_path_3(input: &Path, index: u32) -> PathBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SplitFileReader {
|
impl SplitFileReader {
|
||||||
pub fn empty() -> Self { Self { files: Vec::new(), open_file: Default::default() } }
|
pub fn empty() -> Self {
|
||||||
|
Self { files: Vec::new(), open_file: Default::default() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new(path: &Path) -> Result<Self> {
|
pub fn new(path: &Path) -> Result<Self> {
|
||||||
let mut files = vec![];
|
let mut files = vec![];
|
||||||
@@ -97,11 +101,15 @@ impl SplitFileReader {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> u64 { self.files.last().map_or(0, |f| f.begin + f.size) }
|
pub fn len(&self) -> u64 {
|
||||||
|
self.files.last().map_or(0, |f| f.begin + f.size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for SplitFileReader {
|
impl Clone for SplitFileReader {
|
||||||
fn clone(&self) -> Self { Self { files: self.files.clone(), open_file: Default::default() } }
|
fn clone(&self) -> Self {
|
||||||
|
Self { files: self.files.clone(), open_file: Default::default() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiscStream for SplitFileReader {
|
impl DiscStream for SplitFileReader {
|
||||||
@@ -138,5 +146,7 @@ impl DiscStream for SplitFileReader {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_len(&mut self) -> io::Result<u64> { Ok(self.len()) }
|
fn stream_len(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.len())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,7 +167,9 @@ impl BlockReader for BlockReaderTGC {
|
|||||||
Ok(Block::sectors(sector, count, if read == 0 { BlockKind::None } else { BlockKind::Raw }))
|
Ok(Block::sectors(sector, count, if read == 0 { BlockKind::None } else { BlockKind::Raw }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { SECTOR_SIZE as u32 }
|
fn block_size(&self) -> u32 {
|
||||||
|
SECTOR_SIZE as u32
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
DiscMeta { format: Format::Tgc, disc_size: Some(self.inner.len()), ..Default::default() }
|
DiscMeta { format: Format::Tgc, disc_size: Some(self.inner.len()), ..Default::default() }
|
||||||
@@ -329,7 +331,11 @@ impl DiscWriter for DiscWriterTGC {
|
|||||||
Ok(DiscFinalization::default())
|
Ok(DiscFinalization::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_bound(&self) -> u64 { self.output_size }
|
fn progress_bound(&self) -> u64 {
|
||||||
|
self.output_size
|
||||||
|
}
|
||||||
|
|
||||||
fn weight(&self) -> DiscWriterWeight { DiscWriterWeight::Light }
|
fn weight(&self) -> DiscWriterWeight {
|
||||||
|
DiscWriterWeight::Light
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,11 +45,17 @@ struct WBFSHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WBFSHeader {
|
impl WBFSHeader {
|
||||||
fn sector_size(&self) -> u32 { 1 << self.sector_size_shift }
|
fn sector_size(&self) -> u32 {
|
||||||
|
1 << self.sector_size_shift
|
||||||
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { 1 << self.block_size_shift }
|
fn block_size(&self) -> u32 {
|
||||||
|
1 << self.block_size_shift
|
||||||
|
}
|
||||||
|
|
||||||
fn max_blocks(&self) -> u32 { NUM_WII_SECTORS >> (self.block_size_shift - 15) }
|
fn max_blocks(&self) -> u32 {
|
||||||
|
NUM_WII_SECTORS >> (self.block_size_shift - 15)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DISC_HEADER_SIZE: usize = 0x100;
|
const DISC_HEADER_SIZE: usize = 0x100;
|
||||||
@@ -143,7 +149,9 @@ impl BlockReader for BlockReaderWBFS {
|
|||||||
Ok(Block::new(block_idx, block_size, BlockKind::Raw))
|
Ok(Block::new(block_idx, block_size, BlockKind::Raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { self.header.block_size() }
|
fn block_size(&self) -> u32 {
|
||||||
|
self.header.block_size()
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
let mut result = DiscMeta {
|
let mut result = DiscMeta {
|
||||||
@@ -201,7 +209,7 @@ impl BlockProcessor for BlockProcessorWBFS {
|
|||||||
&mut self.lfg,
|
&mut self.lfg,
|
||||||
self.disc_id,
|
self.disc_id,
|
||||||
self.disc_num,
|
self.disc_num,
|
||||||
self.scrub_update_partition
|
self.scrub_update_partition,
|
||||||
)? {
|
)? {
|
||||||
CheckBlockResult::Normal => {
|
CheckBlockResult::Normal => {
|
||||||
BlockResult { block_idx, disc_data, block_data, meta: CheckBlockResult::Normal }
|
BlockResult { block_idx, disc_data, block_data, meta: CheckBlockResult::Normal }
|
||||||
@@ -321,7 +329,7 @@ impl DiscWriter for DiscWriterWBFS {
|
|||||||
lfg: LaggedFibonacci::default(),
|
lfg: LaggedFibonacci::default(),
|
||||||
disc_id,
|
disc_id,
|
||||||
disc_num,
|
disc_num,
|
||||||
scrub_update_partition: options.scrub_update_partition
|
scrub_update_partition: options.scrub_update_partition,
|
||||||
},
|
},
|
||||||
self.block_count as u32,
|
self.block_count as u32,
|
||||||
options.processor_threads,
|
options.processor_threads,
|
||||||
@@ -383,7 +391,11 @@ impl DiscWriter for DiscWriterWBFS {
|
|||||||
Ok(finalization)
|
Ok(finalization)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_bound(&self) -> u64 { self.inner.disc_size() }
|
fn progress_bound(&self) -> u64 {
|
||||||
|
self.inner.disc_size()
|
||||||
|
}
|
||||||
|
|
||||||
fn weight(&self) -> DiscWriterWeight { DiscWriterWeight::Medium }
|
fn weight(&self) -> DiscWriterWeight {
|
||||||
|
DiscWriterWeight::Medium
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,7 +118,9 @@ impl WIAFileHeader {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_rvz(&self) -> bool { self.magic == RVZ_MAGIC }
|
pub fn is_rvz(&self) -> bool {
|
||||||
|
self.magic == RVZ_MAGIC
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disc kind
|
/// Disc kind
|
||||||
@@ -140,7 +142,9 @@ impl From<DiscKind> for u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<DiscKind> for U32 {
|
impl From<DiscKind> for U32 {
|
||||||
fn from(value: DiscKind) -> Self { u32::from(value).into() }
|
fn from(value: DiscKind) -> Self {
|
||||||
|
u32::from(value).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<u32> for DiscKind {
|
impl TryFrom<u32> for DiscKind {
|
||||||
@@ -186,7 +190,9 @@ impl From<WIACompression> for u32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<WIACompression> for U32 {
|
impl From<WIACompression> for U32 {
|
||||||
fn from(value: WIACompression) -> Self { u32::from(value).into() }
|
fn from(value: WIACompression) -> Self {
|
||||||
|
u32::from(value).into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<u32> for WIACompression {
|
impl TryFrom<u32> for WIACompression {
|
||||||
@@ -332,9 +338,13 @@ pub struct WIAPartitionData {
|
|||||||
static_assert!(size_of::<WIAPartitionData>() == 0x10);
|
static_assert!(size_of::<WIAPartitionData>() == 0x10);
|
||||||
|
|
||||||
impl WIAPartitionData {
|
impl WIAPartitionData {
|
||||||
pub fn start_sector(&self) -> u32 { self.first_sector.get() }
|
pub fn start_sector(&self) -> u32 {
|
||||||
|
self.first_sector.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn end_sector(&self) -> u32 { self.first_sector.get() + self.num_sectors.get() }
|
pub fn end_sector(&self) -> u32 {
|
||||||
|
self.first_sector.get() + self.num_sectors.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn contains_sector(&self, sector: u32) -> bool {
|
pub fn contains_sector(&self, sector: u32) -> bool {
|
||||||
let start = self.first_sector.get();
|
let start = self.first_sector.get();
|
||||||
@@ -399,11 +409,17 @@ pub struct WIARawData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WIARawData {
|
impl WIARawData {
|
||||||
pub fn start_offset(&self) -> u64 { self.raw_data_offset.get().align_down(SECTOR_SIZE as u64) }
|
pub fn start_offset(&self) -> u64 {
|
||||||
|
self.raw_data_offset.get().align_down(SECTOR_SIZE as u64)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_sector(&self) -> u32 { (self.start_offset() / SECTOR_SIZE as u64) as u32 }
|
pub fn start_sector(&self) -> u32 {
|
||||||
|
(self.start_offset() / SECTOR_SIZE as u64) as u32
|
||||||
|
}
|
||||||
|
|
||||||
pub fn end_offset(&self) -> u64 { self.raw_data_offset.get() + self.raw_data_size.get() }
|
pub fn end_offset(&self) -> u64 {
|
||||||
|
self.raw_data_offset.get() + self.raw_data_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn end_sector(&self) -> u32 {
|
pub fn end_sector(&self) -> u32 {
|
||||||
// Round up for unaligned raw data end offsets
|
// Round up for unaligned raw data end offsets
|
||||||
@@ -465,10 +481,14 @@ const COMPRESSED_BIT: u32 = 1 << 31;
|
|||||||
|
|
||||||
impl RVZGroup {
|
impl RVZGroup {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn data_size(&self) -> u32 { self.data_size_and_flag.get() & !COMPRESSED_BIT }
|
pub fn data_size(&self) -> u32 {
|
||||||
|
self.data_size_and_flag.get() & !COMPRESSED_BIT
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_compressed(&self) -> bool { self.data_size_and_flag.get() & COMPRESSED_BIT != 0 }
|
pub fn is_compressed(&self) -> bool {
|
||||||
|
self.data_size_and_flag.get() & COMPRESSED_BIT != 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&WIAGroup> for RVZGroup {
|
impl From<&WIAGroup> for RVZGroup {
|
||||||
@@ -968,10 +988,11 @@ impl BlockReader for BlockReaderWIA {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut block = if info.in_partition {
|
let mut block = if info.in_partition {
|
||||||
let mut block =
|
let mut block = Block::sectors(
|
||||||
Block::sectors(info.sector, info.num_sectors, BlockKind::PartDecrypted {
|
info.sector,
|
||||||
hash_block: false,
|
info.num_sectors,
|
||||||
});
|
BlockKind::PartDecrypted { hash_block: false },
|
||||||
|
);
|
||||||
block.hash_exceptions = exception_lists.into_boxed_slice();
|
block.hash_exceptions = exception_lists.into_boxed_slice();
|
||||||
block
|
block
|
||||||
} else {
|
} else {
|
||||||
@@ -981,7 +1002,9 @@ impl BlockReader for BlockReaderWIA {
|
|||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_size(&self) -> u32 { self.disc.chunk_size.get() }
|
fn block_size(&self) -> u32 {
|
||||||
|
self.disc.chunk_size.get()
|
||||||
|
}
|
||||||
|
|
||||||
fn meta(&self) -> DiscMeta {
|
fn meta(&self) -> DiscMeta {
|
||||||
let level = self.disc.compression_level.get();
|
let level = self.disc.compression_level.get();
|
||||||
@@ -1877,7 +1900,9 @@ impl DiscWriter for DiscWriterWIA {
|
|||||||
Ok(finalization)
|
Ok(finalization)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn progress_bound(&self) -> u64 { self.inner.disc_size() }
|
fn progress_bound(&self) -> u64 {
|
||||||
|
self.inner.disc_size()
|
||||||
|
}
|
||||||
|
|
||||||
fn weight(&self) -> DiscWriterWeight {
|
fn weight(&self) -> DiscWriterWeight {
|
||||||
if self.disc.compression() == WIACompression::None {
|
if self.disc.compression() == WIACompression::None {
|
||||||
|
|||||||
@@ -173,12 +173,16 @@ pub enum Error {
|
|||||||
|
|
||||||
impl From<&str> for Error {
|
impl From<&str> for Error {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: &str) -> Error { Error::Other(s.to_string()) }
|
fn from(s: &str) -> Error {
|
||||||
|
Error::Other(s.to_string())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Error {
|
impl From<String> for Error {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(s: String) -> Error { Error::Other(s) }
|
fn from(s: String) -> Error {
|
||||||
|
Error::Other(s)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<zerocopy::AllocError> for Error {
|
impl From<zerocopy::AllocError> for Error {
|
||||||
@@ -202,7 +206,9 @@ pub trait ErrorContext {
|
|||||||
|
|
||||||
impl ErrorContext for std::io::Error {
|
impl ErrorContext for std::io::Error {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn context(self, context: impl Into<String>) -> Error { Error::Io(context.into(), self) }
|
fn context(self, context: impl Into<String>) -> Error {
|
||||||
|
Error::Io(context.into(), self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper trait for adding context to result errors.
|
/// Helper trait for adding context to result errors.
|
||||||
@@ -212,11 +218,13 @@ pub trait ResultContext<T> {
|
|||||||
|
|
||||||
/// Adds context to a result error using a closure.
|
/// Adds context to a result error using a closure.
|
||||||
fn with_context<F>(self, f: F) -> Result<T>
|
fn with_context<F>(self, f: F) -> Result<T>
|
||||||
where F: FnOnce() -> String;
|
where
|
||||||
|
F: FnOnce() -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, E> ResultContext<T> for Result<T, E>
|
impl<T, E> ResultContext<T> for Result<T, E>
|
||||||
where E: ErrorContext
|
where
|
||||||
|
E: ErrorContext,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn context(self, context: impl Into<String>) -> Result<T> {
|
fn context(self, context: impl Into<String>) -> Result<T> {
|
||||||
@@ -225,7 +233,9 @@ where E: ErrorContext
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn with_context<F>(self, f: F) -> Result<T>
|
fn with_context<F>(self, f: F) -> Result<T>
|
||||||
where F: FnOnce() -> String {
|
where
|
||||||
|
F: FnOnce() -> String,
|
||||||
|
{
|
||||||
self.map_err(|e| e.context(f()))
|
self.map_err(|e| e.context(f()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,7 +255,8 @@ pub(crate) trait IoResultContext<T> {
|
|||||||
fn io_context(self, context: impl Into<String>) -> std::io::Result<T>;
|
fn io_context(self, context: impl Into<String>) -> std::io::Result<T>;
|
||||||
|
|
||||||
fn io_with_context<F>(self, f: F) -> std::io::Result<T>
|
fn io_with_context<F>(self, f: F) -> std::io::Result<T>
|
||||||
where F: FnOnce() -> String;
|
where
|
||||||
|
F: FnOnce() -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> IoResultContext<T> for std::io::Result<T> {
|
impl<T> IoResultContext<T> for std::io::Result<T> {
|
||||||
@@ -256,7 +267,9 @@ impl<T> IoResultContext<T> for std::io::Result<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn io_with_context<F>(self, f: F) -> std::io::Result<T>
|
fn io_with_context<F>(self, f: F) -> std::io::Result<T>
|
||||||
where F: FnOnce() -> String {
|
where
|
||||||
|
F: FnOnce() -> String,
|
||||||
|
{
|
||||||
self.map_err(|e| e.io_context(f()))
|
self.map_err(|e| e.io_context(f()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
100
nod/src/read.rs
100
nod/src/read.rs
@@ -91,7 +91,8 @@ pub trait DiscStream: DynClone + Send {
|
|||||||
dyn_clone::clone_trait_object!(DiscStream);
|
dyn_clone::clone_trait_object!(DiscStream);
|
||||||
|
|
||||||
impl<T> DiscStream for T
|
impl<T> DiscStream for T
|
||||||
where T: AsRef<[u8]> + Send + Clone
|
where
|
||||||
|
T: AsRef<[u8]> + Send + Clone,
|
||||||
{
|
{
|
||||||
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
||||||
let data = self.as_ref();
|
let data = self.as_ref();
|
||||||
@@ -104,44 +105,60 @@ where T: AsRef<[u8]> + Send + Clone
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_len(&mut self) -> io::Result<u64> { Ok(self.as_ref().len() as u64) }
|
fn stream_len(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.as_ref().len() as u64)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct CloneableStream<T>(pub T)
|
pub(crate) struct CloneableStream<T>(pub T)
|
||||||
where T: Read + Seek + Clone + Send;
|
where
|
||||||
|
T: Read + Seek + Clone + Send;
|
||||||
|
|
||||||
impl<T> CloneableStream<T>
|
impl<T> CloneableStream<T>
|
||||||
where T: Read + Seek + Clone + Send
|
where
|
||||||
|
T: Read + Seek + Clone + Send,
|
||||||
{
|
{
|
||||||
pub fn new(stream: T) -> Self { Self(stream) }
|
pub fn new(stream: T) -> Self {
|
||||||
|
Self(stream)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DiscStream for CloneableStream<T>
|
impl<T> DiscStream for CloneableStream<T>
|
||||||
where T: Read + Seek + Clone + Send
|
where
|
||||||
|
T: Read + Seek + Clone + Send,
|
||||||
{
|
{
|
||||||
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
||||||
self.0.seek(io::SeekFrom::Start(offset))?;
|
self.0.seek(io::SeekFrom::Start(offset))?;
|
||||||
self.0.read_exact(buf)
|
self.0.read_exact(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stream_len(&mut self) -> io::Result<u64> { self.0.seek(io::SeekFrom::End(0)) }
|
fn stream_len(&mut self) -> io::Result<u64> {
|
||||||
|
self.0.seek(io::SeekFrom::End(0))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct NonCloneableStream<T>(pub Arc<Mutex<T>>)
|
pub(crate) struct NonCloneableStream<T>(pub Arc<Mutex<T>>)
|
||||||
where T: Read + Seek + Send;
|
where
|
||||||
|
T: Read + Seek + Send;
|
||||||
|
|
||||||
impl<T> Clone for NonCloneableStream<T>
|
impl<T> Clone for NonCloneableStream<T>
|
||||||
where T: Read + Seek + Send
|
where
|
||||||
|
T: Read + Seek + Send,
|
||||||
{
|
{
|
||||||
fn clone(&self) -> Self { Self(self.0.clone()) }
|
fn clone(&self) -> Self {
|
||||||
|
Self(self.0.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> NonCloneableStream<T>
|
impl<T> NonCloneableStream<T>
|
||||||
where T: Read + Seek + Send
|
where
|
||||||
|
T: Read + Seek + Send,
|
||||||
{
|
{
|
||||||
pub fn new(stream: T) -> Self { Self(Arc::new(Mutex::new(stream))) }
|
pub fn new(stream: T) -> Self {
|
||||||
|
Self(Arc::new(Mutex::new(stream)))
|
||||||
|
}
|
||||||
|
|
||||||
fn lock(&self) -> io::Result<std::sync::MutexGuard<'_, T>> {
|
fn lock(&self) -> io::Result<std::sync::MutexGuard<'_, T>> {
|
||||||
self.0.lock().map_err(|_| io::Error::other("NonCloneableStream mutex poisoned"))
|
self.0.lock().map_err(|_| io::Error::other("NonCloneableStream mutex poisoned"))
|
||||||
@@ -149,7 +166,8 @@ where T: Read + Seek + Send
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DiscStream for NonCloneableStream<T>
|
impl<T> DiscStream for NonCloneableStream<T>
|
||||||
where T: Read + Seek + Send
|
where
|
||||||
|
T: Read + Seek + Send,
|
||||||
{
|
{
|
||||||
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> io::Result<()> {
|
||||||
let mut stream = self.lock()?;
|
let mut stream = self.lock()?;
|
||||||
@@ -194,7 +212,9 @@ impl DiscReader {
|
|||||||
/// access (e.g. for preloading blocks during reading or parallel block processing during
|
/// access (e.g. for preloading blocks during reading or parallel block processing during
|
||||||
/// conversion).
|
/// conversion).
|
||||||
pub fn new_from_cloneable_read<R>(stream: R, options: &DiscOptions) -> Result<DiscReader>
|
pub fn new_from_cloneable_read<R>(stream: R, options: &DiscOptions) -> Result<DiscReader>
|
||||||
where R: Read + Seek + Clone + Send + 'static {
|
where
|
||||||
|
R: Read + Seek + Clone + Send + 'static,
|
||||||
|
{
|
||||||
Self::new_stream(Box::new(CloneableStream::new(stream)), options)
|
Self::new_stream(Box::new(CloneableStream::new(stream)), options)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,40 +223,54 @@ impl DiscReader {
|
|||||||
/// Multithreaded accesses will be synchronized, which will limit performance (e.g. for
|
/// Multithreaded accesses will be synchronized, which will limit performance (e.g. for
|
||||||
/// preloading blocks during reading or parallel block processing during conversion).
|
/// preloading blocks during reading or parallel block processing during conversion).
|
||||||
pub fn new_from_non_cloneable_read<R>(stream: R, options: &DiscOptions) -> Result<DiscReader>
|
pub fn new_from_non_cloneable_read<R>(stream: R, options: &DiscOptions) -> Result<DiscReader>
|
||||||
where R: Read + Seek + Send + 'static {
|
where
|
||||||
|
R: Read + Seek + Send + 'static,
|
||||||
|
{
|
||||||
Self::new_stream(Box::new(NonCloneableStream::new(stream)), options)
|
Self::new_stream(Box::new(NonCloneableStream::new(stream)), options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Detects the format of a disc image from a read stream.
|
/// Detects the format of a disc image from a read stream.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn detect<R>(stream: &mut R) -> io::Result<Option<Format>>
|
pub fn detect<R>(stream: &mut R) -> io::Result<Option<Format>>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
block::detect(stream)
|
block::detect(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The disc's primary header.
|
/// The disc's primary header.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn header(&self) -> &DiscHeader { self.0.header() }
|
pub fn header(&self) -> &DiscHeader {
|
||||||
|
self.0.header()
|
||||||
|
}
|
||||||
|
|
||||||
/// The Wii disc's region information.
|
/// The Wii disc's region information.
|
||||||
///
|
///
|
||||||
/// **GameCube**: This will return `None`.
|
/// **GameCube**: This will return `None`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn region(&self) -> Option<&[u8; REGION_SIZE]> { self.0.region() }
|
pub fn region(&self) -> Option<&[u8; REGION_SIZE]> {
|
||||||
|
self.0.region()
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns extra metadata included in the disc file format, if any.
|
/// Returns extra metadata included in the disc file format, if any.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn meta(&self) -> DiscMeta { self.0.meta() }
|
pub fn meta(&self) -> DiscMeta {
|
||||||
|
self.0.meta()
|
||||||
|
}
|
||||||
|
|
||||||
/// The disc's size in bytes, or an estimate if not stored by the format.
|
/// The disc's size in bytes, or an estimate if not stored by the format.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn disc_size(&self) -> u64 { self.0.disc_size() }
|
pub fn disc_size(&self) -> u64 {
|
||||||
|
self.0.disc_size()
|
||||||
|
}
|
||||||
|
|
||||||
/// A list of Wii partitions on the disc.
|
/// A list of Wii partitions on the disc.
|
||||||
///
|
///
|
||||||
/// **GameCube**: This will return an empty slice.
|
/// **GameCube**: This will return an empty slice.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn partitions(&self) -> &[PartitionInfo] { self.0.partitions() }
|
pub fn partitions(&self) -> &[PartitionInfo] {
|
||||||
|
self.0.partitions()
|
||||||
|
}
|
||||||
|
|
||||||
/// Opens a decrypted partition read stream for the specified partition index.
|
/// Opens a decrypted partition read stream for the specified partition index.
|
||||||
///
|
///
|
||||||
@@ -263,25 +297,35 @@ impl DiscReader {
|
|||||||
self.0.open_partition_kind(kind, options)
|
self.0.open_partition_kind(kind, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn into_inner(self) -> disc::reader::DiscReader { self.0 }
|
pub(crate) fn into_inner(self) -> disc::reader::DiscReader {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufRead for DiscReader {
|
impl BufRead for DiscReader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> { self.0.fill_buf() }
|
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||||
|
self.0.fill_buf()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn consume(&mut self, amt: usize) { self.0.consume(amt) }
|
fn consume(&mut self, amt: usize) {
|
||||||
|
self.0.consume(amt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for DiscReader {
|
impl Read for DiscReader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
self.0.read(buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Seek for DiscReader {
|
impl Seek for DiscReader {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> { self.0.seek(pos) }
|
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||||
|
self.0.seek(pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extra metadata about the underlying disc file format.
|
/// Extra metadata about the underlying disc file format.
|
||||||
@@ -475,7 +519,9 @@ impl PartitionMeta {
|
|||||||
|
|
||||||
/// A view into the file system table (FST).
|
/// A view into the file system table (FST).
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fst(&self) -> Result<Fst<'_>, &'static str> { Fst::new(&self.raw_fst) }
|
pub fn fst(&self) -> Result<Fst<'_>, &'static str> {
|
||||||
|
Fst::new(&self.raw_fst)
|
||||||
|
}
|
||||||
|
|
||||||
/// A view into the DOL header.
|
/// A view into the DOL header.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -31,12 +31,16 @@ pub fn sha1_hash(buf: &[u8]) -> HashBytes {
|
|||||||
/// Hashes a byte slice with XXH64.
|
/// Hashes a byte slice with XXH64.
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub fn xxh64_hash(buf: &[u8]) -> u64 { xxhash_rust::xxh64::xxh64(buf, 0) }
|
pub fn xxh64_hash(buf: &[u8]) -> u64 {
|
||||||
|
xxhash_rust::xxh64::xxh64(buf, 0)
|
||||||
|
}
|
||||||
|
|
||||||
pub type DigestThread = (Sender<Bytes>, JoinHandle<DigestResult>);
|
pub type DigestThread = (Sender<Bytes>, JoinHandle<DigestResult>);
|
||||||
|
|
||||||
pub fn digest_thread<H>() -> DigestThread
|
pub fn digest_thread<H>() -> DigestThread
|
||||||
where H: Hasher + Send + 'static {
|
where
|
||||||
|
H: Hasher + Send + 'static,
|
||||||
|
{
|
||||||
let (tx, rx) = crossbeam_channel::bounded::<Bytes>(1);
|
let (tx, rx) = crossbeam_channel::bounded::<Bytes>(1);
|
||||||
let handle = thread::Builder::new()
|
let handle = thread::Builder::new()
|
||||||
.name(format!("Digest {}", H::NAME))
|
.name(format!("Digest {}", H::NAME))
|
||||||
@@ -131,43 +135,63 @@ pub trait Hasher {
|
|||||||
impl Hasher for md5::Md5 {
|
impl Hasher for md5::Md5 {
|
||||||
const NAME: &'static str = "MD5";
|
const NAME: &'static str = "MD5";
|
||||||
|
|
||||||
fn new() -> Self { Digest::new() }
|
fn new() -> Self {
|
||||||
|
Digest::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(self) -> DigestResult { DigestResult::Md5(Digest::finalize(self).into()) }
|
fn finalize(self) -> DigestResult {
|
||||||
|
DigestResult::Md5(Digest::finalize(self).into())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "md5::Md5::update", skip_all)]
|
#[instrument(name = "md5::Md5::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { Digest::update(self, data) }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
Digest::update(self, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for sha1::Sha1 {
|
impl Hasher for sha1::Sha1 {
|
||||||
const NAME: &'static str = "SHA-1";
|
const NAME: &'static str = "SHA-1";
|
||||||
|
|
||||||
fn new() -> Self { Digest::new() }
|
fn new() -> Self {
|
||||||
|
Digest::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(self) -> DigestResult { DigestResult::Sha1(Digest::finalize(self).into()) }
|
fn finalize(self) -> DigestResult {
|
||||||
|
DigestResult::Sha1(Digest::finalize(self).into())
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "sha1::Sha1::update", skip_all)]
|
#[instrument(name = "sha1::Sha1::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { Digest::update(self, data) }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
Digest::update(self, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for crc32fast::Hasher {
|
impl Hasher for crc32fast::Hasher {
|
||||||
const NAME: &'static str = "CRC32";
|
const NAME: &'static str = "CRC32";
|
||||||
|
|
||||||
fn new() -> Self { crc32fast::Hasher::new() }
|
fn new() -> Self {
|
||||||
|
crc32fast::Hasher::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(self) -> DigestResult { DigestResult::Crc32(crc32fast::Hasher::finalize(self)) }
|
fn finalize(self) -> DigestResult {
|
||||||
|
DigestResult::Crc32(crc32fast::Hasher::finalize(self))
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "crc32fast::Hasher::update", skip_all)]
|
#[instrument(name = "crc32fast::Hasher::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { crc32fast::Hasher::update(self, data) }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
crc32fast::Hasher::update(self, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for xxhash_rust::xxh64::Xxh64 {
|
impl Hasher for xxhash_rust::xxh64::Xxh64 {
|
||||||
const NAME: &'static str = "XXH64";
|
const NAME: &'static str = "XXH64";
|
||||||
|
|
||||||
fn new() -> Self { xxhash_rust::xxh64::Xxh64::new(0) }
|
fn new() -> Self {
|
||||||
|
xxhash_rust::xxh64::Xxh64::new(0)
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(self) -> DigestResult {
|
fn finalize(self) -> DigestResult {
|
||||||
DigestResult::Xxh64(xxhash_rust::xxh64::Xxh64::digest(&self))
|
DigestResult::Xxh64(xxhash_rust::xxh64::Xxh64::digest(&self))
|
||||||
@@ -175,7 +199,9 @@ impl Hasher for xxhash_rust::xxh64::Xxh64 {
|
|||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "xxhash_rust::xxh64::Xxh64::update", skip_all)]
|
#[instrument(name = "xxhash_rust::xxh64::Xxh64::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { xxhash_rust::xxh64::Xxh64::update(self, data) }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
xxhash_rust::xxh64::Xxh64::update(self, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "openssl")]
|
#[cfg(feature = "openssl")]
|
||||||
@@ -188,14 +214,16 @@ mod openssl_util {
|
|||||||
pub type HasherSHA1 = HashWrapper<MessageDigestSHA1>;
|
pub type HasherSHA1 = HashWrapper<MessageDigestSHA1>;
|
||||||
|
|
||||||
pub struct HashWrapper<T>
|
pub struct HashWrapper<T>
|
||||||
where T: MessageDigest
|
where
|
||||||
|
T: MessageDigest,
|
||||||
{
|
{
|
||||||
hasher: openssl::hash::Hasher,
|
hasher: openssl::hash::Hasher,
|
||||||
_marker: std::marker::PhantomData<T>,
|
_marker: std::marker::PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> HashWrapper<T>
|
impl<T> HashWrapper<T>
|
||||||
where T: MessageDigest
|
where
|
||||||
|
T: MessageDigest,
|
||||||
{
|
{
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -212,19 +240,25 @@ mod openssl_util {
|
|||||||
pub struct MessageDigestMD5;
|
pub struct MessageDigestMD5;
|
||||||
|
|
||||||
impl MessageDigest for MessageDigestMD5 {
|
impl MessageDigest for MessageDigestMD5 {
|
||||||
fn new() -> openssl::hash::MessageDigest { openssl::hash::MessageDigest::md5() }
|
fn new() -> openssl::hash::MessageDigest {
|
||||||
|
openssl::hash::MessageDigest::md5()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageDigestSHA1;
|
pub struct MessageDigestSHA1;
|
||||||
|
|
||||||
impl MessageDigest for MessageDigestSHA1 {
|
impl MessageDigest for MessageDigestSHA1 {
|
||||||
fn new() -> openssl::hash::MessageDigest { openssl::hash::MessageDigest::sha1() }
|
fn new() -> openssl::hash::MessageDigest {
|
||||||
|
openssl::hash::MessageDigest::sha1()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for HasherMD5 {
|
impl Hasher for HasherMD5 {
|
||||||
const NAME: &'static str = "MD5";
|
const NAME: &'static str = "MD5";
|
||||||
|
|
||||||
fn new() -> Self { Self::new() }
|
fn new() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(mut self) -> DigestResult {
|
fn finalize(mut self) -> DigestResult {
|
||||||
DigestResult::Md5((*self.hasher.finish().unwrap()).try_into().unwrap())
|
DigestResult::Md5((*self.hasher.finish().unwrap()).try_into().unwrap())
|
||||||
@@ -232,13 +266,17 @@ mod openssl_util {
|
|||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "openssl_util::HasherMD5::update", skip_all)]
|
#[instrument(name = "openssl_util::HasherMD5::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { self.hasher.update(data).unwrap() }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
self.hasher.update(data).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hasher for HasherSHA1 {
|
impl Hasher for HasherSHA1 {
|
||||||
const NAME: &'static str = "SHA-1";
|
const NAME: &'static str = "SHA-1";
|
||||||
|
|
||||||
fn new() -> Self { Self::new() }
|
fn new() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
|
||||||
fn finalize(mut self) -> DigestResult {
|
fn finalize(mut self) -> DigestResult {
|
||||||
DigestResult::Sha1((*self.hasher.finish().unwrap()).try_into().unwrap())
|
DigestResult::Sha1((*self.hasher.finish().unwrap()).try_into().unwrap())
|
||||||
@@ -246,7 +284,9 @@ mod openssl_util {
|
|||||||
|
|
||||||
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
#[allow(unused_braces)] // https://github.com/rust-lang/rust/issues/116347
|
||||||
#[instrument(name = "openssl_util::HasherSHA1::update", skip_all)]
|
#[instrument(name = "openssl_util::HasherSHA1::update", skip_all)]
|
||||||
fn update(&mut self, data: &[u8]) { self.hasher.update(data).unwrap() }
|
fn update(&mut self, data: &[u8]) {
|
||||||
|
self.hasher.update(data).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ pub struct LaggedFibonacci {
|
|||||||
|
|
||||||
impl Default for LaggedFibonacci {
|
impl Default for LaggedFibonacci {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Self { Self { buffer: [0u32; LFG_K], position: 0 } }
|
fn default() -> Self {
|
||||||
|
Self { buffer: [0u32; LFG_K], position: 0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LaggedFibonacci {
|
impl LaggedFibonacci {
|
||||||
@@ -107,7 +109,9 @@ impl LaggedFibonacci {
|
|||||||
/// This is used for rebuilding junk data in WIA/RVZ files.
|
/// This is used for rebuilding junk data in WIA/RVZ files.
|
||||||
#[instrument(name = "LaggedFibonacci::init_with_reader", skip_all)]
|
#[instrument(name = "LaggedFibonacci::init_with_reader", skip_all)]
|
||||||
pub fn init_with_reader<R>(&mut self, reader: &mut R) -> io::Result<()>
|
pub fn init_with_reader<R>(&mut self, reader: &mut R) -> io::Result<()>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
reader.read_exact(self.buffer[..SEED_SIZE].as_mut_bytes())?;
|
reader.read_exact(self.buffer[..SEED_SIZE].as_mut_bytes())?;
|
||||||
for x in self.buffer[..SEED_SIZE].iter_mut() {
|
for x in self.buffer[..SEED_SIZE].iter_mut() {
|
||||||
*x = u32::from_be(*x);
|
*x = u32::from_be(*x);
|
||||||
@@ -175,7 +179,9 @@ impl LaggedFibonacci {
|
|||||||
/// Writes junk data to the output stream.
|
/// Writes junk data to the output stream.
|
||||||
#[instrument(name = "LaggedFibonacci::write", skip_all)]
|
#[instrument(name = "LaggedFibonacci::write", skip_all)]
|
||||||
pub fn write<W>(&mut self, w: &mut W, mut len: u64) -> io::Result<()>
|
pub fn write<W>(&mut self, w: &mut W, mut len: u64) -> io::Result<()>
|
||||||
where W: Write + ?Sized {
|
where
|
||||||
|
W: Write + ?Sized,
|
||||||
|
{
|
||||||
while len > 0 {
|
while len > 0 {
|
||||||
while self.position >= LFG_K_BYTES {
|
while self.position >= LFG_K_BYTES {
|
||||||
self.forward();
|
self.forward();
|
||||||
@@ -291,10 +297,13 @@ mod tests {
|
|||||||
lfg.init_with_seed([0x47, 0x41, 0x4c, 0x45], 0, 0x600000);
|
lfg.init_with_seed([0x47, 0x41, 0x4c, 0x45], 0, 0x600000);
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 16];
|
||||||
lfg.fill(&mut buf);
|
lfg.fill(&mut buf);
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0xE9, 0x47, 0x67, 0xBD, 0x41, 0x50, 0x4D, 0x5D, 0x61, 0x48, 0xB1, 0x99, 0xA0, 0x12,
|
0xE9, 0x47, 0x67, 0xBD, 0x41, 0x50, 0x4D, 0x5D, 0x61, 0x48, 0xB1, 0x99, 0xA0, 0x12,
|
||||||
0x0C, 0xBA
|
0x0C, 0xBA
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -303,10 +312,13 @@ mod tests {
|
|||||||
lfg.init_with_seed([0x47, 0x41, 0x4c, 0x45], 0, 0x608000);
|
lfg.init_with_seed([0x47, 0x41, 0x4c, 0x45], 0, 0x608000);
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 16];
|
||||||
lfg.fill(&mut buf);
|
lfg.fill(&mut buf);
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0xE2, 0xBB, 0xBD, 0x77, 0xDA, 0xB2, 0x22, 0x42, 0x1C, 0x0C, 0x0B, 0xFC, 0xAC, 0x06,
|
0xE2, 0xBB, 0xBD, 0x77, 0xDA, 0xB2, 0x22, 0x42, 0x1C, 0x0C, 0x0B, 0xFC, 0xAC, 0x06,
|
||||||
0xEA, 0xD0
|
0xEA, 0xD0
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -315,10 +327,13 @@ mod tests {
|
|||||||
lfg.init_with_seed([0x47, 0x50, 0x49, 0x45], 0, 0x322904);
|
lfg.init_with_seed([0x47, 0x50, 0x49, 0x45], 0, 0x322904);
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 16];
|
||||||
lfg.fill(&mut buf);
|
lfg.fill(&mut buf);
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0x97, 0xD8, 0x23, 0x0B, 0x12, 0xAA, 0x20, 0x45, 0xC2, 0xBD, 0x71, 0x8C, 0x30, 0x32,
|
0x97, 0xD8, 0x23, 0x0B, 0x12, 0xAA, 0x20, 0x45, 0xC2, 0xBD, 0x71, 0x8C, 0x30, 0x32,
|
||||||
0xC5, 0x2F
|
0xC5, 0x2F
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -327,10 +342,13 @@ mod tests {
|
|||||||
lfg.init_with_seed([0x47, 0x50, 0x49, 0x45], 0, 0x322904);
|
lfg.init_with_seed([0x47, 0x50, 0x49, 0x45], 0, 0x322904);
|
||||||
let mut buf = [0u8; 16];
|
let mut buf = [0u8; 16];
|
||||||
lfg.write(&mut buf.as_mut_slice(), 16).unwrap();
|
lfg.write(&mut buf.as_mut_slice(), 16).unwrap();
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0x97, 0xD8, 0x23, 0x0B, 0x12, 0xAA, 0x20, 0x45, 0xC2, 0xBD, 0x71, 0x8C, 0x30, 0x32,
|
0x97, 0xD8, 0x23, 0x0B, 0x12, 0xAA, 0x20, 0x45, 0xC2, 0xBD, 0x71, 0x8C, 0x30, 0x32,
|
||||||
0xC5, 0x2F
|
0xC5, 0x2F
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -338,11 +356,14 @@ mod tests {
|
|||||||
let mut lfg = LaggedFibonacci::default();
|
let mut lfg = LaggedFibonacci::default();
|
||||||
let mut buf = [0u8; 32];
|
let mut buf = [0u8; 32];
|
||||||
lfg.fill_sector_chunked(&mut buf, [0x47, 0x4D, 0x38, 0x45], 0, 0x27FF0);
|
lfg.fill_sector_chunked(&mut buf, [0x47, 0x4D, 0x38, 0x45], 0, 0x27FF0);
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0xAD, 0x6F, 0x21, 0xBE, 0x05, 0x57, 0x10, 0xED, 0xEA, 0xB0, 0x8E, 0xFD, 0x91, 0x58,
|
0xAD, 0x6F, 0x21, 0xBE, 0x05, 0x57, 0x10, 0xED, 0xEA, 0xB0, 0x8E, 0xFD, 0x91, 0x58,
|
||||||
0xA2, 0x0E, 0xDC, 0x0D, 0x59, 0xC0, 0x02, 0x98, 0xA5, 0x00, 0x39, 0x5B, 0x68, 0xA6,
|
0xA2, 0x0E, 0xDC, 0x0D, 0x59, 0xC0, 0x02, 0x98, 0xA5, 0x00, 0x39, 0x5B, 0x68, 0xA6,
|
||||||
0x5D, 0x53, 0x2D, 0xB6
|
0x5D, 0x53, 0x2D, 0xB6
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -351,10 +372,13 @@ mod tests {
|
|||||||
let mut buf = [0u8; 32];
|
let mut buf = [0u8; 32];
|
||||||
lfg.write_sector_chunked(&mut buf.as_mut_slice(), 32, [0x47, 0x4D, 0x38, 0x45], 0, 0x27FF0)
|
lfg.write_sector_chunked(&mut buf.as_mut_slice(), 32, [0x47, 0x4D, 0x38, 0x45], 0, 0x27FF0)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(buf, [
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
[
|
||||||
0xAD, 0x6F, 0x21, 0xBE, 0x05, 0x57, 0x10, 0xED, 0xEA, 0xB0, 0x8E, 0xFD, 0x91, 0x58,
|
0xAD, 0x6F, 0x21, 0xBE, 0x05, 0x57, 0x10, 0xED, 0xEA, 0xB0, 0x8E, 0xFD, 0x91, 0x58,
|
||||||
0xA2, 0x0E, 0xDC, 0x0D, 0x59, 0xC0, 0x02, 0x98, 0xA5, 0x00, 0x39, 0x5B, 0x68, 0xA6,
|
0xA2, 0x0E, 0xDC, 0x0D, 0x59, 0xC0, 0x02, 0x98, 0xA5, 0x00, 0x39, 0x5B, 0x68, 0xA6,
|
||||||
0x5D, 0x53, 0x2D, 0xB6
|
0x5D, 0x53, 0x2D, 0xB6
|
||||||
]);
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ where
|
|||||||
/// A reader with a fixed window.
|
/// A reader with a fixed window.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WindowedReader<T>
|
pub struct WindowedReader<T>
|
||||||
where T: BufRead + Seek
|
where
|
||||||
|
T: BufRead + Seek,
|
||||||
{
|
{
|
||||||
base: T,
|
base: T,
|
||||||
pos: u64,
|
pos: u64,
|
||||||
@@ -46,7 +47,8 @@ where T: BufRead + Seek
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> WindowedReader<T>
|
impl<T> WindowedReader<T>
|
||||||
where T: BufRead + Seek
|
where
|
||||||
|
T: BufRead + Seek,
|
||||||
{
|
{
|
||||||
/// Creates a new windowed stream with offset and size.
|
/// Creates a new windowed stream with offset and size.
|
||||||
///
|
///
|
||||||
@@ -60,11 +62,14 @@ where T: BufRead + Seek
|
|||||||
/// Returns the length of the window.
|
/// Returns the length of the window.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::len_without_is_empty)]
|
#[allow(clippy::len_without_is_empty)]
|
||||||
pub fn len(&self) -> u64 { self.end - self.begin }
|
pub fn len(&self) -> u64 {
|
||||||
|
self.end - self.begin
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Read for WindowedReader<T>
|
impl<T> Read for WindowedReader<T>
|
||||||
where T: BufRead + Seek
|
where
|
||||||
|
T: BufRead + Seek,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
||||||
@@ -77,7 +82,8 @@ where T: BufRead + Seek
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> BufRead for WindowedReader<T>
|
impl<T> BufRead for WindowedReader<T>
|
||||||
where T: BufRead + Seek
|
where
|
||||||
|
T: BufRead + Seek,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||||
@@ -98,7 +104,8 @@ where T: BufRead + Seek
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Seek for WindowedReader<T>
|
impl<T> Seek for WindowedReader<T>
|
||||||
where T: BufRead + Seek
|
where
|
||||||
|
T: BufRead + Seek,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
@@ -118,12 +125,16 @@ where T: BufRead + Seek
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn stream_position(&mut self) -> io::Result<u64> { Ok(self.pos) }
|
fn stream_position(&mut self) -> io::Result<u64> {
|
||||||
|
Ok(self.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn div_rem<T>(x: T, y: T) -> (T, T)
|
pub(crate) fn div_rem<T>(x: T, y: T) -> (T, T)
|
||||||
where T: Div<Output = T> + Rem<Output = T> + Copy {
|
where
|
||||||
|
T: Div<Output = T> + Rem<Output = T> + Copy,
|
||||||
|
{
|
||||||
(x / y, x % y)
|
(x / y, x % y)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,10 +148,14 @@ macro_rules! impl_align {
|
|||||||
($ty:ident) => {
|
($ty:ident) => {
|
||||||
impl Align for $ty {
|
impl Align for $ty {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn align_up(self, align: Self) -> Self { (self + (align - 1)) & !(align - 1) }
|
fn align_up(self, align: Self) -> Self {
|
||||||
|
(self + (align - 1)) & !(align - 1)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn align_down(self, align: Self) -> Self { self & !(align - 1) }
|
fn align_down(self, align: Self) -> Self {
|
||||||
|
self & !(align - 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,9 @@ where
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn read_u16_be<R>(reader: &mut R) -> io::Result<u16>
|
pub fn read_u16_be<R>(reader: &mut R) -> io::Result<u16>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
let mut buf = [0u8; 2];
|
let mut buf = [0u8; 2];
|
||||||
reader.read_exact(&mut buf)?;
|
reader.read_exact(&mut buf)?;
|
||||||
Ok(u16::from_be_bytes(buf))
|
Ok(u16::from_be_bytes(buf))
|
||||||
@@ -146,7 +148,9 @@ where R: Read + ?Sized {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn read_u32_be<R>(reader: &mut R) -> io::Result<u32>
|
pub fn read_u32_be<R>(reader: &mut R) -> io::Result<u32>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
let mut buf = [0u8; 4];
|
let mut buf = [0u8; 4];
|
||||||
reader.read_exact(&mut buf)?;
|
reader.read_exact(&mut buf)?;
|
||||||
Ok(u32::from_be_bytes(buf))
|
Ok(u32::from_be_bytes(buf))
|
||||||
@@ -154,14 +158,18 @@ where R: Read + ?Sized {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn read_u64_be<R>(reader: &mut R) -> io::Result<u64>
|
pub fn read_u64_be<R>(reader: &mut R) -> io::Result<u64>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
let mut buf = [0u8; 8];
|
let mut buf = [0u8; 8];
|
||||||
reader.read_exact(&mut buf)?;
|
reader.read_exact(&mut buf)?;
|
||||||
Ok(u64::from_be_bytes(buf))
|
Ok(u64::from_be_bytes(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_with_zero_fill<R>(r: &mut R, mut buf: &mut [u8]) -> io::Result<usize>
|
pub fn read_with_zero_fill<R>(r: &mut R, mut buf: &mut [u8]) -> io::Result<usize>
|
||||||
where R: Read + ?Sized {
|
where
|
||||||
|
R: Read + ?Sized,
|
||||||
|
{
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
while !buf.is_empty() {
|
while !buf.is_empty() {
|
||||||
let read = r.read(buf)?;
|
let read = r.read(buf)?;
|
||||||
@@ -177,7 +185,9 @@ where R: Read + ?Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn box_to_bytes<T>(b: Box<T>) -> Box<[u8]>
|
pub fn box_to_bytes<T>(b: Box<T>) -> Box<[u8]>
|
||||||
where T: IntoBytes {
|
where
|
||||||
|
T: IntoBytes,
|
||||||
|
{
|
||||||
let p = Box::into_raw(b);
|
let p = Box::into_raw(b);
|
||||||
let sp = unsafe { std::slice::from_raw_parts_mut(p as *mut u8, size_of::<T>()) };
|
let sp = unsafe { std::slice::from_raw_parts_mut(p as *mut u8, size_of::<T>()) };
|
||||||
unsafe { Box::from_raw(sp) }
|
unsafe { Box::from_raw(sp) }
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ use std::ffi::OsStr;
|
|||||||
use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
|
use argp::{EarlyExit, FromArgs, TopLevelCommand, parser::ParseGlobalOptions};
|
||||||
|
|
||||||
struct ArgsOrVersion<T>(T)
|
struct ArgsOrVersion<T>(T)
|
||||||
where T: FromArgs;
|
where
|
||||||
|
T: FromArgs;
|
||||||
|
|
||||||
impl<T> TopLevelCommand for ArgsOrVersion<T> where T: FromArgs {}
|
impl<T> TopLevelCommand for ArgsOrVersion<T> where T: FromArgs {}
|
||||||
|
|
||||||
impl<T> FromArgs for ArgsOrVersion<T>
|
impl<T> FromArgs for ArgsOrVersion<T>
|
||||||
where T: FromArgs
|
where
|
||||||
|
T: FromArgs,
|
||||||
{
|
{
|
||||||
fn _from_args(
|
fn _from_args(
|
||||||
command_name: &[&str],
|
command_name: &[&str],
|
||||||
@@ -59,6 +61,8 @@ where T: FromArgs
|
|||||||
/// This function will exit early from the current process if argument parsing was unsuccessful or if information like `--help` was requested.
|
/// This function will exit early from the current process if argument parsing was unsuccessful or if information like `--help` was requested.
|
||||||
/// Error messages will be printed to stderr, and `--help` output to stdout.
|
/// Error messages will be printed to stderr, and `--help` output to stdout.
|
||||||
pub fn from_env<T>() -> T
|
pub fn from_env<T>() -> T
|
||||||
where T: TopLevelCommand {
|
where
|
||||||
|
T: TopLevelCommand,
|
||||||
|
{
|
||||||
argp::parse_args_or_exit::<ArgsOrVersion<T>>(argp::DEFAULT).0
|
argp::parse_args_or_exit::<ArgsOrVersion<T>>(argp::DEFAULT).0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,20 +85,26 @@ fn check(args: CheckArgs) -> Result<()> {
|
|||||||
};
|
};
|
||||||
rename_map.insert(path.clone(), path.with_file_name(file_name));
|
rename_map.insert(path.clone(), path.with_file_name(file_name));
|
||||||
}
|
}
|
||||||
disc_results.insert(hashes.crc32, DiscResult {
|
disc_results.insert(
|
||||||
|
hashes.crc32,
|
||||||
|
DiscResult {
|
||||||
name,
|
name,
|
||||||
// hashes,
|
// hashes,
|
||||||
redump_entry: Some(entry.clone()),
|
redump_entry: Some(entry.clone()),
|
||||||
matched: full_match,
|
matched: full_match,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("{}: ❌ Not found", name);
|
println!("{}: ❌ Not found", name);
|
||||||
disc_results.insert(hashes.crc32, DiscResult {
|
disc_results.insert(
|
||||||
|
hashes.crc32,
|
||||||
|
DiscResult {
|
||||||
name,
|
name,
|
||||||
// hashes,
|
// hashes,
|
||||||
redump_entry: None,
|
redump_entry: None,
|
||||||
matched: false,
|
matched: false,
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => println!("{}: ❌ Error: {}", name, e),
|
Err(e) => println!("{}: ❌ Error: {}", name, e),
|
||||||
@@ -192,7 +198,7 @@ fn load_disc(path: &Path, name: &str, full_verify: bool) -> Result<DiscHashes> {
|
|||||||
digest_md5: false,
|
digest_md5: false,
|
||||||
digest_sha1: true,
|
digest_sha1: true,
|
||||||
digest_xxh64: false,
|
digest_xxh64: false,
|
||||||
scrub_update_partition: false
|
scrub_update_partition: false,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
pb.finish();
|
pb.finish();
|
||||||
|
|||||||
@@ -60,13 +60,17 @@ impl FromStr for LogLevel {
|
|||||||
|
|
||||||
impl fmt::Display for LogLevel {
|
impl fmt::Display for LogLevel {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", match self {
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
LogLevel::Error => "error",
|
LogLevel::Error => "error",
|
||||||
LogLevel::Warn => "warn",
|
LogLevel::Warn => "warn",
|
||||||
LogLevel::Info => "info",
|
LogLevel::Info => "info",
|
||||||
LogLevel::Debug => "debug",
|
LogLevel::Debug => "debug",
|
||||||
LogLevel::Trace => "trace",
|
LogLevel::Trace => "trace",
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ use std::{
|
|||||||
path::{MAIN_SEPARATOR, Path},
|
path::{MAIN_SEPARATOR, Path},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn path_display(path: &Path) -> PathDisplay<'_> { PathDisplay { path } }
|
pub fn path_display(path: &Path) -> PathDisplay<'_> {
|
||||||
|
PathDisplay { path }
|
||||||
|
}
|
||||||
|
|
||||||
pub struct PathDisplay<'a> {
|
pub struct PathDisplay<'a> {
|
||||||
path: &'a Path,
|
path: &'a Path,
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ pub struct EntryIter<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EntryIter<'static> {
|
impl EntryIter<'static> {
|
||||||
pub fn new() -> EntryIter<'static> { Self { data: loaded_data(), index: 0 } }
|
pub fn new() -> EntryIter<'static> {
|
||||||
|
Self { data: loaded_data(), index: 0 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for EntryIter<'a> {
|
impl<'a> Iterator for EntryIter<'a> {
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ pub fn convert_and_verify(
|
|||||||
digest_md5: md5,
|
digest_md5: md5,
|
||||||
digest_sha1: true,
|
digest_sha1: true,
|
||||||
digest_xxh64: true,
|
digest_xxh64: true,
|
||||||
scrub_update_partition: false
|
scrub_update_partition: false,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
pb.finish();
|
pb.finish();
|
||||||
|
|||||||
Reference in New Issue
Block a user