README.md

# LibdeflateEx

[![Hex.pm](https://img.shields.io/hexpm/v/libdeflate_ex.svg)](https://hex.pm/packages/libdeflate_ex)
[![Docs](https://img.shields.io/badge/hex-docs-blue.svg)](https://hexdocs.pm/libdeflate_ex)

> **Note:** This is a simple Elixir wrapper over the Rust crate
> [libdeflater](https://crates.io/crates/libdeflater). Code was written with
> [Claude Code](https://claude.ai/claude-code), however the test suite verifies
> all functions against their Erlang `:zlib` counterparts in both directions.

Fast deflate, zlib, and gzip compression/decompression for Elixir, powered by
[libdeflate](https://github.com/ebiggers/libdeflate) via a Rust NIF.

libdeflate is significantly faster than zlib for both compression and
decompression, especially for smaller payloads, while achieving comparable or
better compression ratios.

## Installation

Add `libdeflate_ex` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:libdeflate_ex, "~> 0.1.0"}
  ]
end
```

You need a Rust toolchain installed (via [rustup](https://rustup.rs/)) for the
NIF to compile.

## Usage

### Compression

All compression functions accept a compression level from 1 (fastest) to 12
(highest compression). The default level is 6.

```elixir
# Deflate (raw, no header)
{:ok, compressed} = LibdeflateEx.deflate_compress("hello world")
{:ok, compressed} = LibdeflateEx.deflate_compress("hello world", 9)

# Zlib (deflate + zlib header/checksum)
{:ok, compressed} = LibdeflateEx.zlib_compress("hello world")

# Gzip
{:ok, compressed} = LibdeflateEx.gzip_compress("hello world")
```

### Decompression

Decompression requires the exact uncompressed size to be known ahead of time.
This is common in formats like ZIP where the size is stored in metadata.

```elixir
original = "hello world"
{:ok, compressed} = LibdeflateEx.deflate_compress(original)
{:ok, ^original} = LibdeflateEx.deflate_decompress(compressed, byte_size(original))
```

### Bang variants

Every function has a `!` variant that raises on error instead of returning an
error tuple:

```elixir
compressed = LibdeflateEx.gzip_compress!("hello world")
original = LibdeflateEx.gzip_decompress!(compressed, 11)
```

### Interoperability

LibdeflateEx produces standard-compliant output. Zlib and gzip streams are
interoperable with Erlang's `:zlib` module and other implementations:

```elixir
# Compress with LibdeflateEx, decompress with Erlang :zlib
{:ok, compressed} = LibdeflateEx.zlib_compress("hello world")
:zlib.uncompress(compressed)
#=> "hello world"
```

## License

Licensed under either of

- MIT License ([LICENSE-MIT](LICENSE-MIT))
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))

at your option.