Skip to main content

brotli_fast 1.0.0 copy "brotli_fast: ^1.0.0" to clipboard
brotli_fast: ^1.0.0 copied to clipboard

Fast, pure Dart Brotli (RFC 7932) encoder and decoder with no native dependencies. Works on the VM, AOT, Flutter, and the web (JS and Wasm), with one-shot functions, a dart:convert codec and streaming.

brotli_fast #

pub package Null Safety Dart CI codecov GitHub Tag Last Commits Code size License

A fast, pure Dart Brotli encoder and decoder with no native dependencies and no package dependencies. It runs everywhere Dart runs (VM, AOT, Flutter, and the web through dart2js and dart2wasm) and produces the same bytes on every platform.

import 'package:brotli_fast/brotli_fast.dart';

final packed = brotliEncode(bytes);              // quality 5
final smallest = brotliEncode(bytes, quality: 11);
final restored = brotliDecode(packed);

Features #

  • All of Brotli: qualities 0–11 and window sizes 10–24 bits on the encoder, and the full RFC 7932 format on the decoder, including the static dictionary and every transform.
  • Fast: a dedicated fast tier for qualities 0–5 and a tuned high-ratio encoder for 6–11; a decoder with a fused hot loop and a 64-bit bit reader on the VM. See Performance.
  • One-shot, dart:convert and streams: brotliEncode/brotliDecode, the brotli codec, and stream transformers that emit output as input arrives.
  • Dictionaries: raw (compound) dictionaries for both directions, which help small, similar payloads, and serialized shared dictionaries on decode.
  • Large-window format: windows up to 1 GiB (non-standard, opt-in on decode).
  • Safe decoding: malformed or truncated input throws a typed BrotliException, and a size limit guards against decompression bombs.
  • Checked against the reference: CI decodes our streams with Google's brotli CLI, and theirs with ours, at every quality.

Usage #

One-shot #

import 'package:brotli_fast/brotli_fast.dart';

final packed = brotliEncode(data, quality: 9);
final restored = brotliDecode(packed);

quality trades speed for size: 0–5 favor speed (5, the default, is a good balance), 6–11 favor ratio and get progressively slower. windowBits (default 22, a 4 MiB window) can be lowered to save memory on the decoding side.

Strings #

import 'dart:convert';

final text = utf8.fuse(brotli);
final packed = text.encode('héllo, wörld');
final restored = text.decode(packed);

Streams #

brotli.encoder and brotli.decoder are stream transformers:

import 'dart:io';

await File('data.json')
    .openRead()
    .transform(brotli.encoder)
    .pipe(File('data.json.br').openWrite());

await File('data.json.br')
    .openRead()
    .transform(brotli.decoder)
    .pipe(File('data.json').openWrite());

Use BrotliCodec(quality: 9) or BrotliEncoder(quality: 9) for other settings. The streaming encoder emits a compressed block for every 128 KiB of input. It keeps the input it has seen in memory, so it bounds latency, not memory.

Dictionaries #

When many small payloads share structure (JSON with a common schema, HTML templates), a dictionary known to both sides shrinks them considerably:

final dictionary = BrotliDictionary(utf8.encode(sampleRecords));

final packed = brotliEncode(record, quality: 9, dictionary: dictionary);
final restored = brotliDecode(packed, dictionary: dictionary);

Reuse one BrotliDictionary instance: its match index is built on the first encode. The decoder must be given the same bytes. Brotli streams carry no dictionary checksum, so a different dictionary decodes to different data.

Decoding untrusted input #

try {
  final restored = brotliDecode(input, maxOutputSize: 10 << 20); // 10 MiB
} on BrotliException catch (e) {
  print('rejected: ${e.code.name}'); // e.g. truncatedInput, outputLimitExceeded
}

brotliDecode limits output to 1 GiB by default. BrotliException is a FormatException.

Performance #

quality text encode text decode binary encode binary decode
0 1518 2915 512 1145
1 1185 3349 520 1146
5 (default) 855 3328 357 1306
9 92 2815 26 1329

Throughput in MB/s on the deterministic 1 MiB text and binary corpus of benchmark/, measured AOT on an Apple M5 (median of 5 runs). Numbers are machine-specific; run dart run benchmark/perf_history.dart to measure on your own hardware. benchmark/HISTORY.md tracks them over time.

Compatibility #

  • Streams: standard RFC 7932, readable by any Brotli decoder (browsers, the brotli CLI, HTTP servers and proxies). Large-window streams (windowBits above 24) need a decoder that opts in.
  • Platforms: Dart SDK 3.13+; VM, AOT, Flutter, dart2js and dart2wasm. Web builds produce byte-identical output to the VM.

API Documentation #

See the API documentation.

Source #

The official source code is hosted @ GitHub.

Features and bugs #

Please file feature requests and bugs at the issue tracker.

Origin #

brotli_fast is inspired by brotli_neo (repository dart_brotli, MIT license): a full rewrite as a pure Dart Brotli package, with:

  • One optimized implementation: up to 1.7× faster encoding at the default quality and 2.2× at quality 9, with output byte-identical to brotli_neo's.
  • A new, simpler API: brotliEncode/brotliDecode, the brotli dart:convert codec with stream support, and BrotliDictionary.
  • Correctness fixes: valid streams that failed or decoded wrongly now decode correctly, and every quality is cross-checked against Google's reference brotli tool in CI.
  • No dependencies.

License #

Apache License 2.0. Includes the RFC 7932 static dictionary and tables from google/brotli (MIT); see NOTICE.

3
likes
150
points
47
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Fast, pure Dart Brotli (RFC 7932) encoder and decoder with no native dependencies. Works on the VM, AOT, Flutter, and the web (JS and Wasm), with one-shot functions, a dart:convert codec and streaming.

Repository (GitHub)
View/report issues

Topics

#brotli #compression #codec #decompression

License

Apache-2.0 (license)

More

Packages that depend on brotli_fast