Brotlic (or BrotlyC) is a thin wrapper around brotli. It
provides Rust bindings to all compression and decompression APIs. On the fly compression and
decompression is supported for both BufRead
and Write
via CompressorReader<R>
,
CompressorWriter<W>
, DecompressorReader<R>
and DecompressorWriter<W>
. For low-level
instances, see BrotliEncoder
and BrotliDecoder
. These can be configured via
BrotliEncoderOptions
and BrotliDecoderOptions
respectively.
A C compiler is required for building brotli with cargo.
When dealing with [BufRead
]:
DecompressorReader<R>
- Reads a brotli compressed input stream and decompresses it.CompressorReader<R>
- Reads a stream and compresses it while reading.When dealing with [Write
]:
CompressorWriter<W>
- Writes brotli compressed data to the underlying writer.DecompressorWriter<W>
- Writes brotli decompressed data to the underlying writer.To simplify this decision, the following table outlines all the differences:
| | Input | Output | Wraps |
|---------------------------|--------------|--------------|-------------|
| CompressorReader<R>
| Uncompressed | Compressed | [BufRead
] |
| DecompressorReader<R>
| Compressed | Uncompressed | [BufRead
] |
| CompressorWriter<W>
| Uncompressed | Compressed | [Write
] |
| DecompressorWriter<W>
| Compressed | Uncompressed | [Write
] |
To compress a file with brotli:
```rust use std::fs::File; use std::io::{self, Write}; use brotlic::CompressorWriter;
let mut input = File::open("test.txt")?; // uncompressed text file let mut output = File::create("test.brotli")?; // compressed text output file let mut output_compressed = CompressorWriter::new(output);
outputcompressed.writeall(b"test")?; ```
To decompress that same file:
```rust use std::fs::File; use std::io::{self, BufReader, Read}; use brotlic::DecompressorReader;
let mut input = BufReader::new(File::open("test.brotli")?); // uncompressed text file let mut input_decompressed = DecompressorReader::new(input); // requires BufRead
let mut text = String::new(); inputdecompressed.readto_string(&mut text)?;
assert_eq!(text, "test"); ```
To compress and decompress in memory:
```rust use std::io::{self, Cursor, Read, Write}; use brotlic::{CompressorWriter, DecompressorReader};
let input = vec![0; 1024];
// create a wrapper around Write that supports on the fly brotli compression. let mut compressor = CompressorWriter::new(Cursor::new(Vec::new())); // write to memory compressor.writeall(input.asslice()); let encodedinput = compressor.intoinner()?.into_inner(); // read to vec
// create a wrapper around BufRead that supports on the fly brotli decompression. let mut decompressedreader = DecompressorReader::new(Cursor::new(encodedinput)); let mut decoded_input = Vec::new();
decompressedreader.readtoend(&mut decodedinput)?;
asserteq!(input, decodedinput); ```
Sometimes it can be desirable to trade run-time costs for an even better compression ratio:
```rust use std::io::Cursor; use brotlic::{BlockSize, BrotliEncoderOptions, CompressorWriter, Quality, WindowSize};
let encoder = BrotliEncoderOptions::new() .quality(Quality::best()) .windowsize(WindowSize::best()) .blocksize(BlockSize::best()) .build()?;
let writer = Cursor::new(Vec::new()); let compressedwriter = CompressorWriter::withencoder(encoder, writer); ```
It is recommended to not use the encoder directly but instead pass it onto the higher level abstractions.