Public API for hako — schemaless, low-alloc Clojure serialization.
Public API for hako — schemaless, low-alloc Clojure serialization.
(close-thread-locals!)Release the current thread's pooled Writer / Reader instances. Call at the end of a short-lived thread's work — closes the Writer's confined Arena and drops the Reader's scratch buffers. Idempotent.
Release the current thread's pooled Writer / Reader instances. Call at the end of a short-lived thread's work — closes the Writer's confined Arena and drops the Reader's scratch buffers. Idempotent.
(decode src)(decode src opts)Decode a hako-format value from src — a byte[] or a MemorySegment.
Options: :zero-copy — return MemorySegment slices for byte payloads instead of copying to byte[] (default false). Slices are valid only while the source segment / arena remain alive. :tolerate-unknown-tags — unknown user-tag ids resolve to TaggedValue rather than throwing (default false). :cache-idents — consult a JVM-global cache when interning decoded keywords / symbols. Wins on keyword-heavy payloads (~2x on 50+ unique kw), slight overhead on tiny maps (default false).
Decode a hako-format value from `src` — a byte[] or a MemorySegment.
Options:
:zero-copy — return MemorySegment slices for byte payloads instead of
copying to byte[] (default false). Slices are valid only
while the source segment / arena remain alive.
:tolerate-unknown-tags — unknown user-tag ids resolve to TaggedValue rather than
throwing (default false).
:cache-idents — consult a JVM-global cache when interning decoded
keywords / symbols. Wins on keyword-heavy payloads
(~2x on 50+ unique kw), slight overhead on tiny maps
(default false).(decode-into! rd src)(decode-into! rd src opts)Decode a value using the reusable Reader rd rebound to src.
Rebinds via .reset on each call.
The Reader must have been produced by the reader fn (or otherwise
have r/configure! called on it); .reset preserves the extension
handler and array-map thresholds.
Decode a value using the reusable Reader `rd` rebound to `src`. Rebinds via `.reset` on each call. The Reader must have been produced by the `reader` fn (or otherwise have `r/configure!` called on it); `.reset` preserves the extension handler and array-map thresholds.
(decode-many src)(decode-many src opts)Convenience wrapper. Equivalent to (into [] (decoder src opts)).
Convenience wrapper. Equivalent to `(into [] (decoder src opts))`.
(decode-pooled src)(decode-pooled src opts)Like decode but uses a thread-local reusable Reader. Skips the
~250 B allocation of the fresh-Reader path. Same semantics + options
as decode.
Callers on short-lived threads should call close-thread-locals! at
thread exit to avoid pinning the Reader + its scratch buffers. See
the ns docstring for the trade-off.
Like `decode` but uses a thread-local reusable Reader. Skips the ~250 B allocation of the fresh-Reader path. Same semantics + options as `decode`. Callers on short-lived threads should call `close-thread-locals!` at thread exit to avoid pinning the Reader + its scratch buffers. See the ns docstring for the trade-off.
(decoder src)(decoder src opts)Return a reducible + iterable source over all values in src
(a byte[] or MemorySegment). Terminates cleanly on both stream
outputs from encode-many and single-value outputs from encode.
Compose with standard Clojure fns:
(into #{} (filter :active) (hako/decoder bs)) (sequence xform (hako/decoder bs)) (eduction xform (hako/decoder bs)) (reduce f init (hako/decoder bs)) (transduce xform f init (hako/decoder bs)) (run! process! (hako/decoder bs))
Each reduction / iteration spins up a fresh Reader — the source is
safe to walk multiple times, and early termination via reduced or
a short .hasNext stops the reader immediately without over-reading.
Distinct from reader: reader returns a mutable Reader instance
(for decode-into!); decoder returns a lazy value-stream source.
Options — same as decode: :zero-copy, :tolerate-unknown-tags,
:cache-idents.
Return a reducible + iterable source over all values in `src`
(a byte[] or MemorySegment). Terminates cleanly on both stream
outputs from `encode-many` and single-value outputs from `encode`.
Compose with standard Clojure fns:
(into #{} (filter :active) (hako/decoder bs))
(sequence xform (hako/decoder bs))
(eduction xform (hako/decoder bs))
(reduce f init (hako/decoder bs))
(transduce xform f init (hako/decoder bs))
(run! process! (hako/decoder bs))
Each reduction / iteration spins up a fresh Reader — the source is
safe to walk multiple times, and early termination via `reduced` or
a short `.hasNext` stops the reader immediately without over-reading.
Distinct from `reader`: `reader` returns a mutable Reader instance
(for `decode-into!`); `decoder` returns a lazy value-stream source.
Options — same as `decode`: `:zero-copy`, `:tolerate-unknown-tags`,
`:cache-idents`.(encode value)(encode value opts)Encode value and return a fresh byte[].
For arena-backed zero-copy output use encode-to-segment.
Options: :initial-size — starting buffer size in bytes (default 256). :preserve-meta — preserve metadata on collections / IObjs (default false). :pack-homogeneous — detect all-Long / all-Double vectors and emit them as packed prim arrays (default false). :coerce-custom-comparator — allow encoding sorted-set-by / sorted-map-by as default-cmp sorted collections. Comparator is lost on decode. Warns once per JVM.
Encode `value` and return a fresh byte[].
For arena-backed zero-copy output use `encode-to-segment`.
Options:
:initial-size — starting buffer size in bytes (default 256).
:preserve-meta — preserve metadata on collections / IObjs (default false).
:pack-homogeneous — detect all-Long / all-Double vectors and emit
them as packed prim arrays (default false).
:coerce-custom-comparator — allow encoding sorted-set-by / sorted-map-by
as default-cmp sorted collections. Comparator
is lost on decode. Warns once per JVM.(encode-into! wr value)(encode-into! wr value opts)Encode value using the reusable wr. Returns a MemorySegment slice
covering the encoded bytes. The slice is valid until the next
encode-into! call on this writer, or close.
The Writer must have had w/install-handler! called at least once
(the writer fn does this). .reset preserves the handler.
Encode `value` using the reusable `wr`. Returns a MemorySegment slice covering the encoded bytes. The slice is valid until the next `encode-into!` call on this writer, or `close`. The Writer must have had `w/install-handler!` called at least once (the `writer` fn does this). `.reset` preserves the handler.
(encode-into-buffer! wr dst value)(encode-into-buffer! wr dst value opts)Encode value with wr and copy the bytes directly into dst
(a byte[] or ByteBuffer). Skips the MemorySegment.asSlice wrapper that
encode-into! returns — zero-alloc for heap-backed destinations.
For byte[] destinations, writes starting at off (default 0).
For ByteBuffer destinations, advances position by the byte count written.
Returns the number of bytes written.
Encode `value` with `wr` and copy the bytes directly into `dst` (a byte[] or ByteBuffer). Skips the MemorySegment.asSlice wrapper that `encode-into!` returns — zero-alloc for heap-backed destinations. For byte[] destinations, writes starting at `off` (default 0). For ByteBuffer destinations, advances position by the byte count written. Returns the number of bytes written.
(encode-many values)(encode-many values opts)Encode values (a sequence) into a single byte[] sharing one symbol
table across the whole stream. Reads compact when many values repeat
the same keyword / symbol identifiers.
The output has one envelope prefix followed by concatenated encoded
values. Use decode-many to read back.
Encode `values` (a sequence) into a single byte[] sharing one symbol table across the whole stream. Reads compact when many values repeat the same keyword / symbol identifiers. The output has one envelope prefix followed by concatenated encoded values. Use `decode-many` to read back.
(encode-many-into! wr values)(encode-many-into! wr values opts)Batch variant of encode-into!. Writes each value in values into
the reusable wr, sharing one symbol table across the whole batch.
Returns the MemorySegment slice — same lifecycle as encode-into!
(valid until the next encode call on wr).
Skips the per-call Writer construction that encode-many pays
(~500 B). Suitable for pipelines that batch-encode in a loop.
Batch variant of `encode-into!`. Writes each value in `values` into the reusable `wr`, sharing one symbol table across the whole batch. Returns the MemorySegment slice — same lifecycle as `encode-into!` (valid until the next encode call on `wr`). Skips the per-call Writer construction that `encode-many` pays (~500 B). Suitable for pipelines that batch-encode in a loop.
(encode-pooled value)(encode-pooled value opts)Like encode but uses a thread-local reusable Writer. The writer
is warmed once per thread — subsequent encodes skip the arena setup
cost (~500 B). Copies the encoded MemorySegment to a fresh byte[]
on return, same signature as encode.
Callers on short-lived threads should call close-thread-locals!
at thread exit to release the Writer's confined Arena.
Like `encode` but uses a thread-local reusable Writer. The writer is warmed once per thread — subsequent encodes skip the arena setup cost (~500 B). Copies the encoded MemorySegment to a fresh byte[] on return, same signature as `encode`. Callers on short-lived threads should call `close-thread-locals!` at thread exit to release the Writer's confined Arena.
(encode-to-segment arena value)(encode-to-segment arena value opts)Encode value into a MemorySegment owned by arena. Returns the segment.
Encode `value` into a MemorySegment owned by `arena`. Returns the segment.
(reader src)Allocate a reusable Reader bound to src (byte[] or MemorySegment).
Rebind via .reset(newSeg). Not thread-safe.
Allocate a reusable Reader bound to `src` (byte[] or MemorySegment). Rebind via `.reset(newSeg)`. Not thread-safe.
(writer)(writer initial-size)Allocate a reusable Writer with an initial buffer of initial-size
bytes (default 4096). Close via .close when done. Use encode-into!
for each message; the writer's arena is retained between calls.
Allocate a reusable Writer with an initial buffer of `initial-size` bytes (default 4096). Close via `.close` when done. Use `encode-into!` for each message; the writer's arena is retained between calls.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |