115 lines
3.4 KiB
Plaintext
115 lines
3.4 KiB
Plaintext
(relative-include "zlib_helper.h")
|
||
(add-cflag "-lz")
|
||
|
||
|
||
(doc ZLib "is a high-level wrapper around [zlib](https://zlib.net/).
|
||
|
||
## Installation
|
||
|
||
```clojure
|
||
(load \"git@git.veitheller.de:carpentry/zlib.git@0.0.2\")
|
||
```
|
||
|
||
## Usage
|
||
|
||
The `ZLib` module provides only two functions, [`inflate`](#inflate) and
|
||
[`deflate`](#deflate). These functions work in tandem to provide you with data
|
||
compression.
|
||
|
||
```clojure
|
||
; deflate returns a Result of either binary data or an error message
|
||
(let [deflated (ZLib.deflate \"mystring\")]
|
||
(match deflated
|
||
; inflate returns a Result of either a string or an error message
|
||
(Success bin) (println* &(inflate bin))
|
||
(Error msg) (IO.errorln &msg)))
|
||
```
|
||
|
||
Because it’s a `Result` type, we can apply combinators to it.
|
||
|
||
```clojure
|
||
(=> (ZLib.deflate \"mystring\")
|
||
(Result.and-then &ZLib.inflate)
|
||
(Result.map-error &(fn [msg] (do (println* &msg) msg)))
|
||
)
|
||
```
|
||
|
||
You can also choose different levels of compression using `inflate-with`. The
|
||
levels are defined in [`ZLib.ZLevel`](#ZLevel), and are `NoCompression`,
|
||
`BestSpeed`, `BestCompression`, and `DefaultCompression`, which is, well, the
|
||
default.")
|
||
; i tried doing this in carp, but it’s a bit of a pain to wrap the API
|
||
; idiomatically, so for now you’ll only get regular inflation and deflation
|
||
(defmodule ZLib
|
||
(register-type ZBytes [
|
||
len Int
|
||
bytes String
|
||
])
|
||
(hidden ZBytes)
|
||
|
||
(register-type ZRes)
|
||
(defmodule ZRes
|
||
(register ok? (Fn [&ZRes] Bool) "ZRes_is_ok")
|
||
(register bytes (Fn [ZRes] ZLib.ZBytes) "ZRes_bytes")
|
||
(register str (Fn [ZRes] String) "ZRes_str")
|
||
(register err (Fn [ZRes] String) "ZRes_err")
|
||
)
|
||
(hidden ZRes)
|
||
|
||
(deftype ZLevel
|
||
(NoCompression [])
|
||
(BestSpeed [])
|
||
(BestCompression [])
|
||
(DefaultCompression [])
|
||
)
|
||
|
||
(defmodule ZLevel
|
||
(defn to-int [l]
|
||
(match l
|
||
(NoCompression) 0
|
||
(BestSpeed) 1
|
||
(BestCompression) 9
|
||
(DefaultCompression) -1)))
|
||
(doc ZLevel "is a type used in conjunction with
|
||
[`deflate-with`](#deflate-with). It controls the compression level.
|
||
|
||
The constructors are `NoCompression`, `BestSpeed`, `BestCompression`, and
|
||
`DefaultCompression`, which is, well, the default.")
|
||
|
||
(private inflate-)
|
||
(hidden inflate-)
|
||
(register inflate- (Fn [ZLib.ZBytes] ZRes) "ZLib_inflate_c")
|
||
(doc inflate "takes a bytes object `s` and returns a `Result`.
|
||
|
||
The `Result` will be a `Success` containing the inflated string if all goes
|
||
well, and an `Error` returning an error message otherwise.")
|
||
(defn inflate [s]
|
||
(let [r (inflate- s)]
|
||
(if (ZRes.ok? &r)
|
||
(Result.Success (ZRes.str r))
|
||
(Result.Error (ZRes.err r)))))
|
||
|
||
(private deflate-)
|
||
(hidden deflate-)
|
||
(register deflate- (Fn [&String Int] ZRes) "ZLib_deflate_c")
|
||
(doc deflate-with "takes a bytes object `s`, a `Zlevel` `level` and returns
|
||
a `Result`.
|
||
|
||
The `Result` will be a `Success` containing the deflated bytes if all goes
|
||
well, and an `Error` returning an error message otherwise.")
|
||
(defn deflate-with [s level]
|
||
(let [r (deflate- s (ZLevel.to-int level))]
|
||
(if (ZRes.ok? &r)
|
||
(Result.Success (ZRes.bytes r))
|
||
(Result.Error (ZRes.err r)))))
|
||
|
||
(doc deflate "takes a bytes object `s` and returns a `Result`.
|
||
|
||
The `Result` will be a `Success` containing the deflated bytes if all goes
|
||
well, and an `Error` returning an error message otherwise.
|
||
|
||
It is equivalent to calling [`deflate-with`](#deflate-with) with
|
||
`(ZLevel.DefaultCompression)`.")
|
||
(defn deflate [s] (deflate-with s (ZLevel.DefaultCompression)))
|
||
)
|