#brotli #decompression #huffman #embedded-devices #lz77 #no-std

no-std bin+lib brotli 解压器

Brotli 解压器,具有避免使用 Rust stdlib 的接口。这使得它适合嵌入式设备和内核。它设计有可插拔的分配器,以便可以使用标准库的分配器。默认构建还包括标准库分配器和流接口。使用 --features=no-stdlib 禁用此功能。或者,使用 --features=unsafe 关闭数组边界检查和内存初始化,但为调用者提供安全接口。如果不添加 --features=unsafe 参数,则所有包含的代码都是安全的。除了此库之外,还可以通过下载 https://github.com/dropbox/rust-brotli 进行压缩

33 个稳定版本 (3 个主要版本)

使用旧的 Rust 2015

4.0.1 2024 年 5 月 27 日
3.0.0 2024 年 4 月 3 日
2.5.1 2023 年 10 月 28 日
2.3.4 2023 年 1 月 16 日
1.1.0 2017 年 6 月 1 日

#8嵌入式开发

Download history 542054/week @ 2024-05-03 584214/week @ 2024-05-10 588725/week @ 2024-05-17 611047/week @ 2024-05-24 679663/week @ 2024-05-31 694794/week @ 2024-06-07 641644/week @ 2024-06-14 692789/week @ 2024-06-21 678627/week @ 2024-06-28 666942/week @ 2024-07-05 658728/week @ 2024-07-12 678292/week @ 2024-07-19 702338/week @ 2024-07-26 728664/week @ 2024-08-02 731167/week @ 2024-08-09 599253/week @ 2024-08-16

2,893,127 每月下载量
用于 1,715 个 Crates (12 个直接使用)

BSD-3-Clause/MIT

2MB
31K SLoC

rust-brotli-decompressor

crates.io Build Status

版本 4.0.0 的新功能

  • 默认情况下,FFI 已不再激活,以避免在多个依赖 Crates 中包含多个 brotli 版本时出现 ODR 问题。

版本 3.0.0 的新功能

  • FFI 被特性门控在 ffi-api 特性标志之后(默认启用)

版本 2.5.0 的新功能

  • 如果使用额外的字节调用 write,则它将仅返回消耗的字节
  • 后续调用 write 将返回 Ok(0)

版本 2.4.0 的新功能

  • 如果读取到文件结束,它将返回 0 字节。
  • 后续调用 read 将在文件中有未消耗的字节时出错。

版本 2.3.5 的新功能

  • 修复 BrotliFillBitWindow 中的错误

版本 2.3.4 的新功能

  • 在解压器读取器/写入器中检查完全消耗的缓冲区。

版本 2.3.x 的新功能

  • Write 和 Read 实现的错误处理。
  • 修复了在反复调用 Decode 流时某些文件上的小缓冲区大小问题
  • 公开 BrotliDecoderIsFinished

版本 2.2.x 的新功能

  • 为读取器和写入器类实现into_impl
  • 删除了BrotliStateCleanup,因为它在drop()时发生

2.1.2版本的新特性

  • 更好地处理暂时性错误(修复了#4)
  • 在调试模式下遇到意外的字节时不要恐慌(处理算术溢出)
  • 更小的堆栈分配
  • 永远不要用nil创建slice::from_raw_parts
  • 更好的C FFI恐慌报告
  • 将修复brotli问题502和506 b的补丁回滚到旧版本

2.0.0版本的新特性

  • 遗留的自定义字典(主要用于测试多线程brotli编码和实验)
  • 新机制,请求库只依赖于自定义分配:自--features=std默认开启以来,使用--no-default-features标志。
  • https://github.com/google/brotli C API完全兼容,成为即插即用的替代品

项目需求

如果构建时传入--no-default-features,则将C brotli解压缩器的直接无stdlib端口移植到Rust

不依赖于Rust stdlib:这个库非常适合在rust内核中解压缩等。

这将有助于在相同的算法、数据结构和优化条件下,进行C和Rust的对比。

预期的当前性能损失来自于

  1. hgroups中的额外间接引用
  2. 每次访问时都会检查数组边界
  3. 无法从[u8]中加载完整的对齐64位或128位项

系统还启用了所有syscalls在分配器的内存池初始生成时“前置加载”。之后,可以激活SECCOMP或其他机制来保护应用程序,如果需要的话

使用零成本rust FFI抽象将rust-brotli-decompressor链接到C代码

此库有符合原始C接口的FFI导出。要构建它们,请进入c目录,并只需在那里键入make。这将构建一个小示例程序和一个cdylib,其中包含适当的ffi以便链接

示例,称为c/main.c,展示了如何使用流接口和非流接口解压缩程序。

如果需要nostdlib版本,则必须使用不稳定的rust(以启用自定义恐慌处理器),然后禁用BrotliDecoderDecompress函数,因为它没有指定自定义malloc的设施

如果选择nostdlib构建,则必须使用自定义malloc,并且必须设置no-stdlib-ffi-binding cargo功能,例如

cargo build --features='no-stdlib no-stdlib-ffi-binding' --release

用法

使用io::Read抽象

let mut input = brotli_decompressor::Decompressor::new(&mut io::stdin(), 4096 /* buffer size */);

然后您可以直接读取输入,就像读取任何其他io::Read类一样

使用Stream Copy抽象

match brotli_decompressor::BrotliDecompress(&mut io::stdin(), &mut io::stdout(), 65536 /* buffer size */) {
    Ok(_) => {},
    Err(e) => panic!("Error {:?}", e),
}

使用手动内存管理

使用无stdlib的brotli有3个步骤

  1. 设置内存管理器
  2. 设置BrotliState
  3. 在循环中,调用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的定制分配器。此示例演示了一种避免在初始分配之后进行后续syscalls的机制

依赖关系