Brotli compressor and decompressor written in rust that optionally avoids the stdlib
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 2 年前 | ||
| 6 个月前 | ||
| 7 年前 | ||
| 2 年前 | ||
| 7 年前 | ||
| 17 天前 | ||
| 3 年前 | ||
| 2 年前 | ||
| 7 年前 | ||
| 17 天前 | ||
| 1 年前 | ||
| 1 年前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 2 年前 |
rust-brotli
8.0.3 版本新特性
修复:避免在 Broccoli FFI 边界与 BroCatLi 交互时出现的 panic 问题 修复:CompressMulti 工作线程在出错时会正常退出
8.0.2 版本新特性
修复 ffi API 中的内存泄漏问题
8.0.1 版本新特性
提升 ffi 构建的兼容性
8.0.0 版本新特性
- 修复 LZ77 以符合规范要求
- 不再使用 lz77 字典末尾的内容作为上下文种子。而是像没有字典时一样使用零作为种子。这与规范中使用自定义字典的 brotli 行为一致,具体参见
- https://datatracker.ietf.org/doc/draft-vandevenne-shared-brotli-format/
7.0.0 版本新特性
- 修复短写入(short writes)错误
- 允许部分 API 使用 quality=10,并将默认值设为 9.5
6.0.0 版本新特性
- 移除未使用的 SIMD 相关 use 语句
- 隐藏部分警告 - 这些是待办事项(TODOs),将在单独的 PR 中修复
- 不在 MSRV 构建中包含 SIMD - 将 nightly 版本与 MSRV 结合没有实际意义
5.0.0 版本新特性
- FFI 默认不再启用,以避免当多个依赖 crate 包含不同版本的 brotli 时可能出现的 ODR(One Definition Rule)问题。
4.0.0 版本新特性
固定依赖于 rust-brotli-decompressor,该版本可通过 ffi-api 标志禁用 ffi。 这有助于避免与其他 brotli 库发生符号冲突。
3.5 版本新特性
更新 SIMD 支持。 改进 CI 集成。 清理部分 clippy 警告。
3.4 版本新特性
当 Brotli 解压缩器的 reader 和 writer 处理末尾带有额外位的 brotli 流时,行为更加完善。 目前已对 stdsimd 等可选特性进行测试或暂时禁用。
3.2 版本新特性
- Reader 和 Writer 类均支持 into_inner 转换
3.0 版本新特性
- 完全兼容的 FFI,可直接替代 https://github.com/google/brotli 二进制文件
- 完全支持自定义分配器
- 多线程压缩,多个线程可协同处理单个文件
- 可连接模式,以支持 https://github.com/google/brotli/issues/628 中提出的功能需求
- 如果第一个文件使用 -apendable 参数,第二个文件使用 -catable 参数,则可通过二进制工具 catbrotli 实现此功能
- 验证模式,可对文件进行双重检查,确保其能使用相同设置进行解压缩;此模式对基准测试或模糊测试非常有用
- 幻数(Magic Number):brotli 文件可包含一个有用的头部,其中包含几个幻数字节、可连接性信息以及用于预分配内存的最终输出大小
2.5 版本新特性
- 在 2.5 版本中,回调函数还会向下传递一个分配器,用于创建新的 StaticCommands、PDF 以及 256 位浮点向量。
- 在 2.4 版本中,带有压缩中间表示的回调函数现在每次传递一个完整的元块。此外,这些项是可变的,以便进行进一步优化(如果需要)
2.3 版本新特性
- 现在,Flush 会生成输出,而不是调用流上的 finish。这使您能够使用写入器抽象来获取即时输出,而不必借助 CompressStream 内部抽象
项目要求
将 C 语言版 brotli 压缩器直接移植到 Rust,且不依赖标准库
不依赖 Rust 标准库:该库非常适合在 Rust 内核等环境中进行解压缩。
这有助于在采用相同算法、数据结构和优化的情况下,对 C 和 Rust 进行直接比较。
压缩使用方法
Rust brotli 当前支持 0 - 11 级压缩 在 0-9 级压缩级别下,它们应与 brotli C 压缩引擎的结果位对位相同 推荐的 lg_window_size 介于 20 和 22 之间
使用 io::Read 抽象
let mut input = brotli::CompressorReader::new(&mut io::stdin(), 4096 /* buffer size */,
quality as u32, lg_window_size as u32);
那么你可以像读取任何其他 io::Read 类一样简单地读取输入
使用 io::Write 抽象
let mut writer = brotli::Compressor::new(&mut io::stdout(), 4096 /* buffer size */,
quality as u32, lg_window_size as u32);
此外,还提供了使用 with_params 静态函数构建压缩器读取器或写入器的方法
例如:
let params = BrotliEncoderParams::default();
// modify params to fit the application needs
let mut writer = brotli::Compressor::with_params(&mut io::stdout(), 4096 /* buffer size */,
params);
或供读者参考
let params = BrotliEncoderParams::default();
// modify params to fit the application needs
let mut writer = brotli::CompressorReader::with_params(&mut io::stdin(), 4096 /* buffer size */,
params);
使用流复制抽象
match brotli::BrotliCompress(&mut io::stdin(), &mut io::stdout(), &brotli_encoder_params) {
Ok(_) => {},
Err(e) => panic!("Error {:?}", e),
}
解压缩使用方法
使用 io::Read 抽象
let mut input = brotli::Decompressor::new(&mut io::stdin(), 4096 /* buffer size */);
那么你可以像读取任何其他 io::Read 类一样简单地读取输入
使用 io::Write 抽象
let mut writer = brotli::DecompressorWriter::new(&mut io::stdout(), 4096 /* buffer size */);
使用流复制抽象
match brotli::BrotliDecompress(&mut io::stdin(), &mut io::stdout()) {
Ok(_) => {},
Err(e) => panic!("Error {:?}", e),
}
手动内存管理
在不使用标准库的情况下使用 brotli 分为 3 个步骤
- 设置内存管理器
- 设置 BrotliState
- 在循环中调用 BrotliDecompressStream
详细说明
// at global scope declare a MemPool type -- in this case we'll choose the heap to
// avoid unsafe code, and avoid restrictions of the stack size
declare_stack_allocator_struct!(MemPool, heap);
// at local scope, make a heap allocated buffers to hold uint8's uint32's and huffman codes
let mut u8_buffer = define_allocator_memory_pool!(4096, u8, [0; 32 * 1024 * 1024], heap);
let mut u32_buffer = define_allocator_memory_pool!(4096, u32, [0; 1024 * 1024], heap);
let mut hc_buffer = define_allocator_memory_pool!(4096, HuffmanCode, [0; 4 * 1024 * 1024], heap);
let heap_u8_allocator = HeapPrealloc::<u8>::new_allocator(4096, &mut u8_buffer, bzero);
let heap_u32_allocator = HeapPrealloc::<u32>::new_allocator(4096, &mut u32_buffer, bzero);
let heap_hc_allocator = HeapPrealloc::<HuffmanCode>::new_allocator(4096, &mut hc_buffer, bzero);
// At this point no more syscalls are going to be needed since everything can come from the allocators.
// Feel free to activate SECCOMP jailing or other mechanisms to secure your application if you wish.
// Now it's possible to setup the decompressor state
let mut brotli_state = BrotliState::new(heap_u8_allocator, heap_u32_allocator, heap_hc_allocator);
// at this point the decompressor simply needs an input and output buffer and the ability to track
// the available data left in each buffer
loop {
result = BrotliDecompressStream(&mut available_in, &mut input_offset, &input.slice(),
&mut available_out, &mut output_offset, &mut output.slice_mut(),
&mut written, &mut brotli_state);
// just end the decompression if result is BrotliResult::ResultSuccess or BrotliResult::ResultFailure
}
此接口与 C 语言 brotli 解压缩器所使用的接口完全相同。
您也可以随意使用直接调用 Box 的自定义分配器。此示例展示了一种在初始分配后避免后续系统调用的机制。
使用 C 接口
rust-brotli 是官方 https://github.com/google/brotli C 实现的即插即用替代品。这意味着您可以在任何支持该库的地方使用它。要以这种方式构建 rust-brotli,请进入 c 子目录并在那里运行 make:
cd c && make
这将构建 c/target/release/libbrotli.so,并构建用于压缩和解压缩任何 brotli 文件的纯 C 命令行工具。
c/target/release 中的 libbrotli.so 应该能够替换任何其他 libbrotli.so 文件,同时具备使用安全 Rust 带来的所有优势(FFI 绑定部分除外)。
该代码还支持更广泛的选项,包括强制预测模式(例如 UTF8、有符号、MSB 或 LSB)以及将文字成本权重从 540 更改为其他值。
流拼接
Brotli 支持创建可拼接的流,这在需要独立压缩块但作为单个流解压缩的流式场景中非常有用。
简单拼接(快速)
对第一个文件使用 -bare -appendable,对后续文件使用 -bare -catable。这些文件可以通过简单的字节拼接(无需特殊工具)进行组合,并在末尾添加一个结束字节(0x03):
# Create the base file with header but no trailer (must specify window size)
brotli -c -bare -appendable -w22 input1.txt > base.br
# Create bare-catable streams (no header, no trailer, same window size!)
brotli -c -bare -catable -w22 input2.txt > part2.br
brotli -c -bare -catable -w22 input3.txt > part3.br
# Simple concatenation with finalization byte
# Note: printf '\x03' adds the required final byte
(cat base.br part2.br part3.br; printf '\x03') > combined.br
# Decompress normally
brotli -d combined.br -o output.txt
优势:
- 即时拼接(无需处理)
- 无需特殊工具
- 裸流可按任意顺序追加
要求:
- 所有文件必须使用相同的窗口大小(推荐
-w22) - 第一个文件:
-bare -appendable(包含头部,无尾部) - 后续文件:
-bare -catable(无头部、无尾部、无字典引用) - 必须追加一个最终的
0x03字节以完成流
高效拼接(大小优化)
使用带有 -catable 和 -appendable 标志的 catbrotli 工具可获得更好的压缩效果,但会花费一定的处理时间:
# Create files for catbrotli tool
brotli -c -appendable input1.txt > appendable.br
brotli -c -catable input2.txt > catable1.br
brotli -c -catable input3.txt > catable2.br
# Concatenate using catbrotli tool
catbrotli appendable.br catable1.br catable2.br > combined.br
权衡取舍: catbrotli 生成的输出更小,但需要 CPU 时间来智能处理流。当大小比拼接速度更重要时,请使用此工具。
技术参考:流参数交互
流类型及其参数:
| 流类型 | bare_stream | byte_align | appendable | catable | use_dictionary | 描述 |
|---|---|---|---|---|---|---|
| 标准 | false | false | false | false | true | 带有头部和尾部的普通 brotli 流 |
| 首个(简单拼接) | true | true | true | false | true | 有头部,无尾部 - 用于简单的 cat 拼接 |
| 后续(简单拼接) | true | true | true | true | false | 无头部,无尾部,无字典引用 - 追加到首个流 |
| 可追加(catbrotli) | false | varies | true | false | true | 供 catbrotli 工具使用 |
| 可拼接(catbrotli) | false | varies | true | true | false | 供 catbrotli 工具使用 |
重要说明:
- 参数依赖关系由库在 CLI 和 API 使用中自动应用
- 库的
SanitizeParams函数确保:catable = true→ 自动设置appendable = true和use_dictionary = falsebare_stream = true→ 自动设置byte_align = true!appendable→ 自动设置byte_align = false
- 使用
set_parameter()时,依赖关系会立即应用 - 直接设置字段时(例如
params.catable = true),依赖关系会在压缩初始化期间应用 - 无需手动修正 - 库会处理所有参数依赖关系
- 可拼接流的
use_dictionary = false可防止引用块边界之前的字节 - 简单拼接需要一个最终的
0x03字节来完成流 - 所有拼接的流必须使用相同的窗口大小
API 使用示例:
// First file: -bare -appendable equivalent
params.bare_stream = true; // Sets bare_stream=true, byte_align=true (automatic)
params.appendable = true; // Sets appendable=true
// Subsequent files: -bare -catable equivalent
params.bare_stream = true; // Sets bare_stream=true, byte_align=true (automatic)
params.catable = true; // Sets catable=true, appendable=true, use_dictionary=false (automatic)
// All parameter dependencies are handled automatically by the library.
// No manual fixups required - just set the primary flags you want.
项目介绍
Brotli compressor and decompressor written in rust that optionally avoids the stdlib