Liking cljdoc? Tell your friends :D

bencode-cljc

"Instead of cursing the darkness, light a candle." ― Benjamin Franklin

A functional Clojure(script) BEncode serialization library.

[com.jamesleonis/bencode-cljc "0.2.2"]

Clojars Project

Why?

A dependency-free implementation of BEncode. bencode-cljc aims to be a portable implementation to boldly go wherever Clojure goes.

Official support

  • Clojure
  • ClojureScript

Usage

(ns your.awesome.app
  (:require [bencode-cljc.core :refer [serialize deserialize]]))

(def out (serialize {"spam" (list "a" "b")})
; => "d4:spaml1:a1:bee"

(deserialize out)
; => {"spam" '("a" "b")}

Details

serialize operates on Clojure data structures and outputs a Clojure string.

deserialize operates on the opposite of serialize.

If an error is encountered in either, nil is returned.

Encoding

As an encoder, bencode-cljc is fairly strict. The aim is full compatibility with existing BEncoded services, and not a fully featured transport encoder. As such, only Integer, Maps, Lists, and Strings are supported.

This comes with some unfortunate side-effects:

  • nil values are unsupported.
    • Yep, let your outrage flow through you.
    • The BEncode spec does not implement an encoding for nil/null values, so they are treated as a malformed input.
  • Sets are not allowed. Convert it to a list.
  • float, decimal, and other floating-point numbers are not allowed
  • map keys are coerced to strings. Complex values (lists, maps) and numbers are not allowed as keys.

But I'm not an evil taskmaster. I bend.

  • Map keys can be keywords. However they are converted to strings via name. This truncates the namespace from namespaced keywords.
    • A future improvement might allow for deserializing map keys to keywords.
  • Vectors are automatically converted to lists.

Decoding

In keeping with a portable implementation, deserialize operates on vanilla Clojure strings.

Contrary to the Wikipedia entry, BEncode does not have the bijection property. List item order is undefined [1] [2]. Beware comparing either serialized or deserialized values.

Development

The test suite is built in CLJC, and is runs both Clojure and Clojurescript. Leiningen is deprecated and not guaranteed to work.

Clojure

To run the Clojure tests, use the Clojure CLI to start the test runner. The CLI tools are all that are required.

clojure -M:test:runner

To run the benchmarks

clojure -M:benchmark-clj

To build and deploy with build.clj

clojure -T:build all
clojure -T:build deploy

Clojurescript

The Clojurescript build additionally requires Node.js and Shadow-CLJS. Artifacts will be generated in the build folder

npx shadow-cljs -A:test compile test

To run the benchmarks, use the benchmark tag

npx shadow-cljs -A:benchmark-cljs compile benchmark

To build a release, compile with the lib tag

npx shadow-cljs release lib

Changelog

0.2.2

  • Add benchmarking suite for both Clojure(script)
  • Add build.clj support
  • Deprecated Leiningen support
  • BUG: Hard Clojure dependency in POM.xml

0.2.1

  • Add Changelog
  • Add deps.edn and shadow-cljs.edn support

0.2.0

  • Test against several BitTorrent files (Debian and Ubuntu ISO .torrent files)

0.1.2

  • Run CLJS tests before CLJ tests to see results faster
  • BUGFIX: Maps deserializes arbitrary keys

0.1.1

  • Relicense from GPL to EPLv2 for licensing compatibility
  • BUGFIX: CLJS unit tests run twice
  • BUGFIX: Exception thrown when serializing symbol in map key position

0.1.0

  • Initial Release

License

Copyright © 2017-2025 James Leonis

Distributed under the EPLv2 license. See LICENSE file.

Can you improve this documentation?Edit on GitLab

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close