package decompress

  1. Overview
  2. Docs
Implementation of Zlib and GZip in OCaml

Install

Dune Dependency

Authors

Maintainers

Sources

decompress-v1.2.0.tbz
sha256=51983d4497ccb27c253e7464b03d38544aad51e0e7d537e405f4df6954c27ab0
sha512=17c7e3dc79b7cedaf649c208874a50a810002c71d061c133239b9813a9dfe424ba303a968ba68c728862bb20ceaa23465097334bc16b819317390d01c2f91f89

Description

Decompress is an implementation of Zlib and GZip in OCaml

It provides a pure non-blocking interface to inflate and deflate data flow.

Published: 08 Jul 2020

README

Decompress - Pure OCaml implementation of RFC1951/Zlib/Gzip

decompress is a library which implements:

The library

The library is available with:

$ opam install decompress

It provides three sub-packages:

  • decompress.de to handle RFC1951 stream

  • decompress.zl to handle Zlib stream

  • decompress.gz to handle Gzip stream

Each sub-package provide 3 sub-modules:

  • Inf to inflate/decompress a stream

  • Def to deflate/compress a stream

  • Higher as a easy entry point to use the stream

How to use it

Link issue

decompress uses checkseum to compute CRC of streams. checkseum provides 2 implementations:

  • a C implementation to be fast

  • an OCaml implementation to be usable with js_of_ocaml (or, at least, require only the caml runtime)

When the user wants to make an OCaml executable, it must choose which implementation of checkseum he wants. A compilation of an executable with decompress.zl is:

$ ocamlfind opt -linkpkg -package checkseum.c,decompress.zl main.ml

Otherwise, the end-user should have a linking error (see #47).

With dune

checkseum uses a mechanism integrated into dune which solves the link issue. It provides a way to silently choose the default implementation of checkseum: checkseum.c.

By this way (and only with dune), an executable with decompress.zl is:

(executable
 (name main)
 (libraries decompress.zl))

Of course, the user still is able to choose which implementation he wants:

(executable
 (name main)
 (libraries checkseum.ocaml decompress.zl))

The API

decompress proposes to the user a full control of:

  • the input/output loop

  • the allocation

Input / Output

The process of the inflation/deflation is non-blocking and it does not require any syscalls as an usual MirageOS project. The user can decide how to get the input and to store the output.

An usual loop (which can fit into lwt or async) of decompress.zl is:

let rec go decoder = match Zl.Inf.decode decoder with
  | `Await decoder ->
    let len = input itmp 0 (Bigstringaf.length tmp) in
    go (Zl.Inf.src decoder itmp 0 len)
  | `Flush decoder ->
    let len = Bigstringaf.length otmp - Zl.Inf.dst_rem decoder in
    output stdout otmp 0 len ;
    go (Zl.Inf.flush decoder)
  | `Malformed err -> invalid_arg err
  | `End decoder ->
    let len = Bigstringaf.length otmp - Zl.Inf.dst_rem decoder in
    output stdout otmp 0 len in
go decoder
Allocation

Then, the process does not allocate large objects but it requires at the initialisation these objects. Such objects can be re-used by another inflation/deflation process - of course, these processes can not use same objects at the same time.

val decompress : window:De.window -> in_channel -> out_channel -> unit

let w0 = De.make_windows ~bits:15

(* Safe use of decompress *)
let () =
  decompress ~window:w0 stdin stdout ;
  decompress ~window:w0 (open_in "file.z") (open_out "file")

(* Unsafe use of decompress,
   the second process must use an other pre-allocated window. *)
let () =
  Lwt_main.run @@
    Lwt.join [ (decompress ~window:w0 stdin stdout |> Lwt.return)
             ; (decompress ~window:w0 (open_in "file.z") (open_out "file") |> Lwt.return) ]

This ability can be used on:

  • the input buffer given to the encoder/decoder with src

  • the output buffer given to the encoder/decoder

  • the window given to the encoder/decoder

  • the shared-queue used by the compression algorithm and the encoder

Example

An example exists into bin/main.ml where you can see how to use decompress.zl and decompress.de.

Higher interface

However, decompress provides a higher interface close to what camlzip provides to help newcomers to use decompress:

val compress : refill:(bigstring -> int) -> flush:(bigstring -> int -> unit) -> unit
val uncompress : refill:(bigstring -> int) -> flush:(bigstring -> int -> unit) -> unit

Build Requirements

  • OCaml >= 4.07.0

  • dune to build the project

  • base-bytes meta-package

  • bigarray-compat

  • checkseum

  • optint

Dependencies (6)

  1. checkseum >= "0.2.0"
  2. optint >= "0.0.4"
  3. bigarray-compat
  4. base-bytes
  5. dune >= "1.0"
  6. ocaml >= "4.07.0"

Dev Dependencies (5)

  1. base64 >= "3.0.0" & with-test
  2. camlzip >= "1.10" & with-test
  3. hxd with-test & < "0.3.0"
  4. alcotest with-test
  5. bigstringaf with-test

Used by (8)

  1. albatross = "1.1.0"
  2. carton < "0.3.0"
  3. carton-git < "0.3.0"
  4. carton-lwt < "0.3.0"
  5. git >= "3.0.0" & < "3.3.1"
  6. git-unix >= "3.0.0" & < "3.3.1"
  7. imagelib >= "20200929" & < "20210402"
  8. rfc1951 = "1.2.0"

Conflicts

None