brotlic 0.2.0

Bindings to the brotli library featuring a low-overhead encoder and decoder, `Write`rs and `Read`ers for compression and decompression at customizable compression qualities and window sizes.
Documentation

Brotlic

crates.io Released API docs MIT licensed

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.

Requirements

A C compiler is required for building brotli with cargo.

Usage

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:

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);

output_compressed.write_all(b"test")?;

To decompress that same file:

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();
input_decompressed.read_to_string(&mut text)?;

assert_eq!(text, "test");

To compress and decompress in memory:

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.write_all(input.as_slice());
let encoded_input = compressor.into_inner()?.into_inner(); // read to vec

// create a wrapper around BufRead that supports on the fly brotli decompression.
let mut decompressed_reader = DecompressorReader::new(Cursor::new(encoded_input));
let mut decoded_input = Vec::new();

decompressed_reader.read_to_end(&mut decoded_input)?;

assert_eq!(input, decoded_input);

Customizing compression quality

Sometimes it can be desirable to trade run-time costs for an even better compression ratio:

use std::io::Cursor;
use brotlic::{BlockSize, BrotliEncoderOptions, CompressorWriter, Quality, WindowSize};

let encoder = BrotliEncoderOptions::new()
    .quality(Quality::best())
    .window_size(WindowSize::best())
    .block_size(BlockSize::best())
    .build()?;

let writer = Cursor::new(Vec::new());
let compressed_writer = CompressorWriter::with_encoder(encoder, writer);

It is recommended to not use the encoder directly but instead pass it onto the higher level abstractions.

Credits