Step by step examples to teach you Brotli.

Learn Brotli implementation via these examples.

What is Brotli?

Brotli is a generic-purpose lossless compression algorithm that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling, with a compression ratio comparable to the best currently available general-purpose compression methods. It is similar in speed with deflate but offers more dense compression.

The specification of the Brotli Compressed Data Format is defined in RFC 7932.

Rust Bindings

1. bitemyapp/brotli2-rs

Brotli encoders/decoers for Rust.

Brotli Compression/Decompression for Rust.

This crate is a binding to the official brotli implementation and provides in-memory and I/O streams for Rust wrappers.

Bindings to the official brotli implementation in Rust.

Step 1: Install it

# Cargo.toml
[dependencies]
brotli2 = "0.3"

Step 2: Write code

Here is a simple example:

use std::io::prelude::*;
use brotli2::read::{BrotliEncoder, BrotliDecoder};

// Round trip some bytes from a byte source, into a compressor, into a
// decompressor, and finally into a vector.
let data = "Hello, World!".as_bytes();
let compressor = BrotliEncoder::new(data, 9);
let mut decompressor = BrotliDecoder::new(compressor);

let mut contents = String::new();
decompressor.read_to_string(&mut contents).unwrap();
assert_eq!(contents, "Hello, World!");

Full Example

Let us look at a full Brotli Example.

Step 1. Write Code

Finally we need to write our code as follows:

(a). all-read-write-roundtrips.rs

extern crate brotli2;
extern crate rand;

use brotli2::raw::{compress_buf, decompress_buf};
use brotli2::read;
use brotli2::write;
use brotli2::CompressParams;
use rand::Rng;
use std::io::{Read, Write};

// Used in functions as temporary storage space before producing a vec
const BIGBUF_SIZE: usize = 120 * 1024 * 1024;
static mut BIGBUF: [u8; BIGBUF_SIZE] = [0; BIGBUF_SIZE];

fn main() {
    let v1 = vec![1; 1024];
    let v2 = vec![44; 10 * 1024 * 1024];
    let datas: &[&[u8]] = &[b"", b"a", b"aaaaa", b";", &v1, &v2];
    let mut params = CompressParams::new();
    params.quality(6);
    let params = &params;

    fn bufencode(data: &[u8], params: &CompressParams) -> Vec<u8> {
        let bufref = &mut unsafe { &mut BIGBUF[..] };
        let n = compress_buf(params, data, bufref).unwrap();
        assert!(n > 0 && n <= BIGBUF_SIZE && n == bufref.len());
        bufref.to_owned()
    }
    fn bufdecode(data: &[u8]) -> Vec<u8> {
        let bufref = &mut unsafe { &mut BIGBUF[..] };
        let n = decompress_buf(data, bufref).unwrap();
        assert!(n <= BIGBUF_SIZE && n == bufref.len());
        bufref.to_owned()
    }
    fn ioreadencode(data: &[u8], params: &CompressParams) -> Vec<u8> {
        let mut buf = vec![];
        read::BrotliEncoder::from_params(data, params)
            .read_to_end(&mut buf)
            .unwrap();
        assert!(buf.len() > 0);
        buf
    }
    fn ioreaddecode(data: &[u8]) -> Vec<u8> {
        let mut buf = vec![];
        read::BrotliDecoder::new(data)
            .read_to_end(&mut buf)
            .unwrap();
        buf
    }
    fn iowriteencode(data: &[u8], params: &CompressParams) -> Vec<u8> {
        let mut enc = write::BrotliEncoder::from_params(vec![], params);
        enc.write_all(data).unwrap();
        enc.finish().unwrap()
    }
    fn iowritedecode(data: &[u8]) -> Vec<u8> {
        let mut dec = write::BrotliDecoder::new(vec![]);
        dec.write_all(data).unwrap();
        dec.finish().unwrap()
    }

    let check = |data: &[u8]| {
        let c1 = &bufencode(data, params);
        let c2 = &ioreadencode(data, params);
        let c3 = &iowriteencode(data, params);
        assert!(data == &*bufdecode(c1));
        assert!(data == &*ioreaddecode(c1));
        assert!(data == &*iowritedecode(c1));
        // it's valid for them to be different, but we need to do more work
        if c2 != c1 {
            assert!(data == &*bufdecode(c2));
            assert!(data == &*ioreaddecode(c2));
            assert!(data == &*iowritedecode(c2));
        }
        if c3 != c1 && c3 != c2 {
            assert!(data == &*bufdecode(c2));
            assert!(data == &*ioreaddecode(c2));
            assert!(data == &*iowritedecode(c2));
        }
    };

    for &data in datas.iter() {
        check(data)
    }
    let mut rng = rand::thread_rng();
    for _ in 0..3 {
        let rnum: usize = rng.gen_range(1, 100 * 1024 * 1024);
        let mut buf = vec![0; rnum];
        rng.fill(&mut buf[..]);
        check(&buf)
    }
}

Documentation

Documentation.

Reference

Download the code below:

No. Link
1. Download Full Code
2. Read more here.
3. Follow code author here.

Read More.


More

Here are some more examples related to Brotli.

Categorized in: