21个版本

0.3.2 2024年6月17日
0.3.1 2024年2月20日
0.2.3 2022年8月13日
0.1.0 2022年6月4日
0.0.1 2021年3月29日

54压缩 类别中

Download history 132/week @ 2024-04-28 127/week @ 2024-05-05 25/week @ 2024-05-12 61/week @ 2024-05-19 52/week @ 2024-05-26 40/week @ 2024-06-02 61/week @ 2024-06-09 207/week @ 2024-06-16 104/week @ 2024-06-23 38/week @ 2024-06-30 54/week @ 2024-07-28 24/week @ 2024-08-11

每月 78 次下载
用于 chd-capi

BSD-3-Clause许可证

235KB
4K SLoC

chd-rs

Latest Version Docs License Minimum Supported Rust Version 1.59

在纯Safe Rust中重新实现CHD文件格式,与libchdr直接兼容。

chd-rs旨在成为内存安全、文档完善、从头开始实现的CHD库,可通过chd.cpp进行验证,同时易于阅读和使用作为在其它语言中本地实现该格式的文档。它是独立的,并且只需Rust编译器即可构建,无需完整的C/C++工具链。

性能具有竞争力,但在基准测试中略慢于libchdr,这是由于使用了更成熟的(但完全正确)纯Rust压缩编解码器实现。Deflate(zlib)压缩由flate2支持,LZMA由lzma-rs支持,而FLAC解压缩由claxon支持。虽然性能很重要,但重点是可读性和正确性。

用法

使用ChdChd::open方法打开,然后从0迭代到chd.header().hunk_count()来读取块。

目标缓冲区的大小必须恰好为chd.header().hunk_size(),以使用hunk.read_hunk_in进行解压缩,该方法接受输出切片和存储压缩数据的缓冲区。

fn main() -> Result<()> {
    let mut f = BufReader::new(File::open("image.chd")?;
    let mut chd = Chd::open(&mut f, None)?;
    let hunk_count = chd.header().hunk_count();
    let hunk_size = chd.header().hunk_size();
    
    // buffer to store decompressed hunks
    let mut out_buf = chd.get_hunksized_buffer();
    
    // buffer for temporary compressed
    let mut temp_buf = Vec::new();
    for hunk_num in 0..hunk_count {
        let mut hunk = chd.hunk(hunk_num)?;
        hunk.read_hunk_in(&mut temp_buf, &mut out_buf)?;
    }
}

为了更符合人体工程学但速度较慢的使用,chd::read提供了在块级别实现ReadSeek的缓冲适配器。文件级别的缓冲适配器也可用。

借用迭代器

通过unstable_lending_iterators,块和元数据可以稍微更符合人体工程学地迭代,尽管需要使用while let循环。此API在泛型关联类型LendingIterator特质稳定之前是不稳定的。

[dependencies]
chd = { version = "0.2", features = ["unstable_lending_iterators"] }

然后可以像这样迭代块。

fn main() -> Result<()> {
    let mut f = BufReader::new(File::open("image.chd")?);
    let mut chd = Chd::open(&mut f, None)?;
    
    // buffer to store decompressed hunks
    let mut out_buf = chd.get_hunksized_buffer();
    
    // buffer for temporary compressed
    let mut temp_buf = Vec::new();
    let mut hunk_iter = chd.hunks();
    while let Some(mut hunk) = hunk_iter.next() {
        hunk.read_hunk_in(&mut temp_buf, &mut out_buf)?;
    }
}

Chd::metadata中存在类似的API用于元数据。

验证块校验和

默认情况下,chd-rs出于性能考虑不会验证解压缩块的校验和。应启用功能verify_block_crc以验证块校验和。

[dependencies]
chd = { version = "0.2", features = ["verify_block_crc"] }

支持的编解码器

chd-rs支持以下压缩编解码器,比libchdr的覆盖范围更广。对于实现细节,请参阅chd::compression模块。

V1-4 编解码器

⚠️V1-4的支持没有像V5支持那样经过严格的测试。 ⚠️

  • 无(CHDCOMPRESSION_NONE
  • Zlib(CHDCOMPRESSION_ZLIB
  • Zlib+(CHDCOMPRESSION_ZLIB

V5 编解码器

  • 无(CHD_CODEC_NONE
  • LZMA(CHD_CODEC_LZMA
  • Deflate(CHD_CODEC_ZLIB
  • FLAC(CHD_CODEC_FLAC
  • Huffman(CHD_CODEC_HUFF
  • Zstandard(CHD_CODEC_ZSTD
  • CD LZMA(CHD_CODEC_CD_LZMA
  • CD Deflate(CHD_CODEC_CD_ZLIB
  • CD FLAC(CHD_CODEC_CD_FLAC
  • CD Zstandard(CHD_CODEC_CD_ZSTD
  • AV Huffman(CHD_CODEC_AVHUFF

编解码器和Huffman API

默认情况下,编解码器和静态Huffman实现不是作为公共API的一部分公开,但可以通过codec_apihuffman_api功能分别启用。这些API可能会更改,但应认为它们主要稳定。

特别是,HuffmanDecoder的类型签名将在generic_const_exprs稳定后发生变化。

rchdman 命令行工具

作为一个概念证明,chd-rs实现了chdman的极其基本的重实现,用于只读目的。以下功能在rchdman中可用。

  • info 显示CHD的信息。
  • verify 验证CHD的完整性。不验证元数据的完整性。
  • extractraw 从CHD输入文件中提取原始文件。
  • dumpmeta 将元数据从CHD输出到标准输出或文件。

rchdman的结果应与chdman相同。rchdman旨在简单,不包括多线程或其他功能,因此通常比chdman慢。没有计划在rchdman中实现写入操作。

性能

默认情况下,chd-rs 使用纯 Rust 编解码器,但如果需要最大性能,可以启用 max_perf。这启用了 flate2 的 zlib-ng 后端,以及在自定义的 lzma-rs 分支 中使用实验性 API,以牺牲更高的内存使用为代价来提高性能。结合 codegen-units=1Profile Guided Optimization,chd-rs 的性能与 libchdr 相当,差距在 1% 以内。

未启用 max_perf 时,chd-rs 已经在无需链接 zlib-ng 等C库的情况下,性能达到 libchdr 的 15%。

libchdr API

⚠️C API 尚未经过充分测试。使用时请自行承担风险。 ⚠️

chd-rs 提供了一个与 chd.h 兼容的 C API。以下是 ABI 兼容性的详细信息,但作为动态库编译时未经过测试。更多详情请参见 /chd-rs-capi

依赖项

~1.7–3MB
~56K SLoC