1    Introduction

1.1    Overview

std.lib.bin is part of the standard foundation library set. This page collects the public API reference for the namespace.

2    Walkthrough

2.1    NIO buffers

std.lib.bin.buffer creates typed NIO buffers. buffer is the general constructor; convenience functions like int-buffer and double-buffer are also available.

create and write to a buffer

^{:refer std.lib.bin.buffer/buffer :added "3.0"}
(buffer 16)
=> java.nio.ByteBuffer

^{:refer std.lib.bin.buffer/int-buffer :added "3.0"}
(int-buffer 4 {:direct true :endian :little})
=> java.nio.IntBuffer

^{:refer std.lib.bin.buffer/buffer-write :added "3.0"}
(let [^java.nio.ByteBuffer b (buffer 16)]
  (buffer-write b (int-array [1 2 3 4]))
  [(.get b 3) (.get b 7) (.get b 11) (.get b 15)])
=> [1 2 3 4]

read from a buffer

^{:refer std.lib.bin.buffer/buffer-read :added "3.0"}
(let [buf (buffer 4)
      out (int-array 1)]
  (.put ^java.nio.ByteBuffer buf 3 (byte 1))
  (buffer-read buf out)
  (first out))
=> 1

2.2    Binary conversions

std.lib.bin.type converts values between bit strings, bit sequences, bit sets, byte arrays, and numbers.

convert between binary representations

^{:refer std.lib.bin.type/bitseq :added "3.0"}
(btype/bitseq (byte-array [49]))
=> [1 0 0 0 1 1]

^{:refer std.lib.bin.type/bitstr :added "3.0"}
(btype/bitstr (byte-array [49]))
=> "100011"

^{:refer std.lib.bin.type/number :added "3.0"}
(btype/number "100011")
=> 49

^{:refer std.lib.bin.type/bytes :added "3.0"}
(-> (btype/bytes "100011")
    seq)
=> [49]

3    API



bitseq ^

[obj]
Added 3.0

converts to a bitseq binary representation

v 3.0
(definvoke bitseq
  [:compose {:val (comp protocol.binary/-to-bitseq prepare-binary)
             :arglists '([obj])}])
link
(binary/bitseq (byte-array [49])) => [1 0 0 0 1 1]

bitset ^

[obj]
Added 3.0

converts to a bitset binary representation

v 3.0
(definvoke bitset
  [:compose {:val (comp protocol.binary/-to-bitset prepare-binary)
             :arglists '([obj])}])
link
(-> (binary/bitset "100011") (bitset-to-bitseq)) => [1 0 0 0 1 1]

bitstr ^

[obj]
Added 3.0

converts to a bitstr binary representation

v 3.0
(definvoke bitstr
  [:compose {:val (comp protocol.binary/-to-bitstr prepare-binary)
             :arglists '([obj])}])
link
(binary/bitstr (byte-array [49])) => "100011"

buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert wrap], :or {type :byte, direct false, endian +endian-native+, convert true, wrap false}}]
Added 3.0

either creates or wraps a byte buffer of a given type

v 3.0
(defn buffer
  ([len-or-elems]
   (buffer len-or-elems {}))
  ([len-or-elems {:keys [type direct endian convert wrap]
                  :or {type    :byte
                       direct  false
                       endian  +endian-native+
                       convert true
                       wrap    false}}]
   (let [[len elems] (if (number? len-or-elems)
                       [len-or-elems nil]
                       [(count len-or-elems) len-or-elems])]
     (if wrap
       ((get-in +buffer-records+ [type :wrap]) elems)
       (buffer-create type elems len direct endian convert)))))
link
(buffer 10) => java.nio.ByteBuffer (buffer 10 {:type :float :convert false}) => java.nio.ByteBuffer (buffer 10 {:type :float :direct true}) => java.nio.FloatBuffer (def farr (float-array [1 2 3 4])) (= (.array ^java.nio.FloatBuffer (buffer farr {:type :float :wrap true})) farr) => true (not= (.array ^java.nio.FloatBuffer (buffer farr {:type :float})) farr) => true

buffer-read ^

[buff] [buff arr]
Added 3.0

reads primitive array from buffer

v 3.0
(defn buffer-read
  ([^java.nio.Buffer buff]
   (cond (.hasArray buff)
         (.array buff)

         :else
         (let [len (.capacity buff)
               arr ((buffer-primitive buff :array-fn) len)]
           (buffer-read buff arr))))
  ([^java.nio.Buffer buff arr]
   (let [comp  (class/class:array-component (type arr))
         ctype (class/primitive comp :type)]
     (cond (instance? (get-in +buffer-records+ [ctype :buffer])
                      buff)
           (do (doto buff
                 (.rewind)
                 (buffer-get arr))
               arr)

           (instance? ByteBuffer buff)
           (recur (buffer-convert buff ctype) arr)

           :else
           (throw (ex-info "Incompatible buffer and array" {:buffer {:type (type buff)}
                                                            :array  {:type ctype}}))))))
link
(def -buf- (buffer 4)) (def -out- (int-array 1)) (do (.put ^java.nio.ByteBuffer -buf- 3 (byte 1)) (buffer-read -buf- -out-) (first -out-)) => 1

buffer-write ^

[buff arr]
Added 3.0

writes primitive array to a buffer

v 3.0
(defn buffer-write
  ([^java.nio.Buffer buff arr]
   (let [comp  (class/class:array-component (type arr))
         ctype (class/primitive comp :type)]
     (cond (instance? (get-in +buffer-records+ [ctype :buffer])
                      buff)
           (doto buff
             (buffer-put arr)
             (.rewind))

           (instance? ByteBuffer buff)
           (recur (buffer-convert buff ctype) arr)

           :else
           (throw (ex-info "Incompatible buffer and array" {:buffer {:type (type buff)}
                                                            :array  {:type ctype}}))))))
link
(def ^java.nio.ByteBuffer -buf- (buffer 16)) (buffer-write -buf- (int-array [1 2 3 4])) [(.get -buf- 3) (.get -buf- 7) (.get -buf- 11) (.get -buf- 15)] => [1 2 3 4]

byte-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(byte-buffer 5 {:direct true :endian :little}) => java.nio.ByteBuffer

bytes ^

[obj]
Added 3.0

converts to a byte array binary representation

v 3.0
(definvoke bytes
  [:compose {:val (comp protocol.binary/-to-bytes prepare-binary)
             :arglists '([obj])}])
link
(-> (binary/bytes "100011") (seq)) => [49]

char-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(char-buffer 5 {:direct true :endian :little}) => java.nio.CharBuffer

double-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(double-buffer 5 {:direct true :endian :little}) => java.nio.DoubleBuffer

float-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(float-buffer 5 {:direct true :endian :little}) => java.nio.FloatBuffer

input-stream ^

[obj]
Added 3.0

creates an inputstream from various representations

v 3.0
(definvoke ^InputStream input-stream
  [:compose {:val (comp protocol.binary/-to-input-stream prepare-input-stream)
             :arglists '([obj])}])
link
(input-stream 9223372036854775808N) => java.io.ByteArrayInputStream

int-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(int-buffer 5 {:direct true :endian :little}) => java.nio.IntBuffer

long-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(long-buffer 5 {:direct true :endian :little}) => java.nio.LongBuffer

number ^

[obj]
Added 3.0

converts to a number binary representation

v 3.0
(definvoke number
  [:compose {:val (comp protocol.binary/-to-number prepare-binary)
             :arglists '([obj])}])
link
(binary/number "100011") => 49 (-> (binary/number (byte-array [78 45 34 -12 45 34 56])) (binary/bitstr) (binary/bitset) (binary/bytes) (seq)) => [78 45 34 -12 45 34 56]

output-stream ^

[obj]
Added 3.0

creates an inputstream from various representations

v 3.0
(defn ^OutputStream output-stream
  ([obj]
   (protocol.binary/-to-output-stream obj)))
link
(output-stream (fs/file "project.clj")) => java.io.FileOutputStream

short-buffer ^

[len-or-elems] [len-or-elems {:keys [type direct endian convert], :as opts}]
GeneratedAdded 3.0

generated
;; generated at runtime, no single source form
link
(short-buffer 5 {:direct true :endian :little}) => java.nio.ShortBuffer

4    std.lib.bin: A Comprehensive Summary

The std.lib.bin namespace, along with its sub-namespaces std.lib.bin.buffer and std.lib.bin.type, provides a comprehensive set of utilities for working with binary data in Clojure. This module focuses on efficient manipulation of byte buffers, conversion between various binary representations (bit strings, bit sequences, bit sets, numbers, byte arrays), and handling I/O streams and channels for binary data.

4.1    std.lib.bin (Main Namespace)

This namespace primarily acts as an aggregator, re-exporting key functions from its sub-namespaces std.lib.bin.buffer and std.lib.bin.type. It simplifies access to the binary manipulation capabilities by providing a unified interface.

Key Re-exported Functions:

  • From std.lib.bin.buffer: buffer, buffer-read, buffer-write, and type-specific buffer creation functions like byte-buffer, char-buffer, short-buffer, int-buffer, long-buffer, float-buffer, double-buffer.n* From std.lib.bin.type: input-stream, output-stream, bitseq, bitstr, bitset, bytes, number.

4.2    std.lib.bin.buffer (NIO Buffer Manipulation)

This sub-namespace provides tools for creating, manipulating, and converting Java NIO ByteBuffer and its type-specific views (e.g., IntBuffer, DoubleBuffer). It emphasizes direct memory manipulation and control over byte order (endianness).

Core Concepts:

  • NIO Buffers: Leverages Java's java.nio package for efficient, direct memory access to binary data.n Endianness: Explicit control over ByteOrder (big-endian or little-endian) for multi-byte data types.n Type-Specific Buffers: Supports creating and working with buffers for various primitive types (byte, char, short, int, long, float, double).

Key Functions:

  • byte-order: Converts a keyword (:little, :big) to a java.nio.ByteOrder object.n buffer: The primary function for creating or wrapping NIO buffers. It allows specifying the buffer type (:byte, :int, etc.), whether it's direct or heap-allocated, endianness, and if it should convert to a type-specific view.n Type-specific buffer creation functions (e.g., byte-buffer, double-buffer): Convenience wrappers around buffer for specific primitive types.n buffer-convert: Converts a ByteBuffer to a type-specific buffer (e.g., DoubleBuffer).n buffer-type: Returns metadata (e.g., :type, :array-fn) about the primitive type associated with a given buffer class.n buffer-primitive: Similar to buffer-type, but works with a buffer instance.n buffer-put: Writes a primitive array into a buffer.n buffer-get: Reads data from a buffer into a primitive array.n buffer-write: Writes a primitive array into a ByteBuffer, handling type conversion if necessary.n* buffer-read: Reads data from a buffer into a primitive array, handling type conversion.

4.3    std.lib.bin.type (Binary Data Conversion and I/O)

This sub-namespace focuses on converting data between various binary representations and providing unified interfaces for binary I/O (streams and channels). It extends the std.protocol.binary/IBinary and std.protocol.binary/IByteSource/IByteSink/IByteChannel protocols to many common Java types.

Core Concepts:

  • IBinary Protocol: Defines a set of functions for converting an object to different binary forms: bitstr (binary string), bitseq (sequence of 0s and 1s), bitset (java.util.BitSet), bytes (byte array), and number (numeric representation).n IByteSource / IByteSink / IByteChannel Protocols: Provide a unified way to get InputStream, OutputStream, or ByteChannel from various data sources (e.g., File, URL, ByteBuffer, byte[]).n Supported Formats: The module explicitly supports conversion for: bit strings, bit sequences, bit sets, numbers (Long, BigInt), byte arrays, InputStream, ByteBuffer, File, Path, Channel, URL, URI.

Key Functions:

  • bitstr-to-bitseq, bitseq-to-bitstr: Convert between binary strings and sequences.n bitseq-to-number, long-to-bitseq: Convert between binary sequences and numbers (handling large numbers with BigInt).n bitseq-to-bitset, bitset-to-bitseq: Convert between binary sequences and BitSet.n bitset-to-bytes, bytes-to-bitset: Convert between BitSet and byte arrays.n bitstr?: Checks if a string is a valid binary string (contains only '0' and '1').n input-stream: Creates an InputStream from various binary representations.n output-stream: Creates an OutputStream from various binary representations.n channel: Creates a ByteChannel from various binary representations.n bitstr, bitseq, bitset, bytes, number (definvoke functions): These are the primary entry points for converting any supported object into its respective binary representation, leveraging the IBinary protocol.

4.4    Usage Pattern:

This module is essential for any application requiring low-level binary data handling, network communication, file I/O, or cryptographic operations where precise control over data representation and efficient processing are critical. It abstracts away much of the boilerplate Java interop for NIO buffers and binary conversions, providing a more idiomatic Clojure interface.

Usage Pattern: example

;; Example: Creating and writing to a ByteBuffer
(require '[std.lib.bin :as bin])

(def my-buffer (bin/int-buffer 4)) ; Creates an IntBuffer with capacity 4
(bin/buffer-write my-buffer (int-array [10 20 30 40]))

;; Example: Converting a number to a bit sequence and then to bytes
(require '[std.lib.bin.type :as btype])

(def num-val 49)
(def bit-seq (btype/bitseq num-val)) ; => [1 0 0 0 1 1]
(def byte-arr (btype/bytes num-val)) ; => byte-array with [49]