rvz 0.2.0

RVZ compression library.
Documentation
# rvz

`rvz` is a library for reading Wii RVZ compressed disks.

The RVZ file format was introduced by the Dolphin emulator as an improvement
over the WIA file format, and is documented
[here](https://github.com/dolphin-emu/dolphin/blob/500728360cd177466f699962b441363cd1dd9ed7/docs/WiaAndRvz.md).

RVZ files compress GameCube and Wii disk images, in some cases drastically
reducing the overall file size. It achieves this by storing the decrypted
contents of the disks and applying compression where it is beneficial.
Additionally, a lot of the padding in these disk images can be modeled as bytes
from a Lagged Fibonacci Generator, drastically reducing the storage requirement
of these random-looking sequences of bytes.

This storage format is lossless, as it stores all of the information required
to reconstruct the original disk. However, not all data is cheaply
reconstructed. The format lends itself well to the use case of games, as
partition data is already decrypted. To reconstruct the original disk, all
hashes in Wii disks must be re-computed, which requires reading large portions
of the archive.

# Usage

```rust
use std::io;
use std::fs::File;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;

let file = File::open("path/to/rvz.rvz").expect("Failed to open RVZ");
let mut rvz = rvz::Rvz::new(file).expect("Failed to parse RVZ metadata");

// This contains (ideally) the metadata of the RVZ image. `Rvz::new` only does
// minimal error checking, additional validity checks need to be done with the
// metadata to confirm that the file is valid (e.g. check that size matches,
// check RVZ magic, etc.)
let metadata = &rvz.metadata;

let partition = &metadata.partitions[0];
let first_sector = partition.partition_data[0].first_sector;
let partition_offset = u64::from(first_sector) * 0x8000;
let partition_size =
    u64::from(partition.partition_data[0].sector_count +
    partition.partition_data[1].sector_count) * 0x800;

// This takes a long time, but is required to get proper hashes when reading
// from partitions, as the RVZ archive doesn't actually store hashes unless
// they differ from what can be computed from data.
rvz.compute_hashes().expect("Error while computing partition hashes");

rvz.seek(SeekFrom::Start(partition_offset)).expect("Unable to seek");

// This dumps the contents of the first partition to a file, decrypted
let mut file = File::create("path/to/partition/dump.raw")
    .expect("Failed to open output file");
io::copy(&mut rvz.by_ref().take(partition_size), &mut file)
    .expect("Failed to copy partition to file");

```

# TODO

 - Support GCN disks
 - Support more than just ZSTD compression
 - Better unit testing
 - Allow encrypting partitions, to be able to dump a full ISO
 - Apply exception lists (as far as I can tell, these are only used possibly
   for hacks or homebrew that have bad/incorrect hashes on disk?)

## License

This module is released under the following licenses:
 - GPL v2 or later
 - LGPL v2.1 or later
 - MPL 2.0

Refer to the `LICENSE` file for more information.