# Bento
[](https://github.com/folz/bento)
[](https://hex.pm/packages/bento)
Bento is a new [Bencoding](https://en.wikipedia.org/wiki/Bencode) library for Elixir focusing on incredibly fast **speed**
without sacrificing **simplicity**, **completeness**, or **correctness**.
It takes inspiration from [Poison](https://github.com/devinus/poison), a
pure-Elixir JSON library, and uses several techniques found there to achieve this speed:
* Extensive [sub-binary matching](http://erlang.org/euc/07/papers/1700Gustafsson.pdf)
* A hand-rolled **parser** using several techniques [known to benefit HiPE](http://erlang.org/workshop/2003/paper/p36-sagonas.pdf)
for native compilation
* [IO list](http://jlouisramblings.blogspot.com/2013/07/problematic-traits-in-erlang.html)
encoding
* **Single-pass** decoding
Additionally, and unlike some other Elixir bencoding libraries, Bento will also reject all malformed input. This guarantees you're working with a well-formed bencoded file.
Preliminary [benchmarking](#benchmarking) shows that Bento performs over 2x faster when encoding, and at least as fast when decoding, compared to other existing Elixir libraries.
## Installation
Bento is [available in Hex](https://hex.pm/packages/bento). The package can be installed by:
1. Add bento to your list of dependencies in `mix.exs`:
def deps do
[{:bento, "~> 0.9.1"}]
end
2. Update your dependencies.
$ mix deps.get
## Usage
Encoding an Elixir data type:
```elixir
iex> Bento.encode([1, "two", [3]])
{:ok, "li1e3:twoli3eee"}
iex> Bento.encode!(%{"foo" => ["bar", "baz"], "qux" => "norf"})
"d3:fool3:bar3:baze3:qux4:norfe"
```
Decoding a bencoded string:
```elixir
iex> Bento.decode("li1e3:twoli3eee")
{:ok, [1, "two", [3]]}
iex> Bento.decode!("d3:fool3:bar3:baze3:qux4:norfe")
%{"foo" => ["bar", "baz"], "qux" => "norf"}
```
Bento is also metainfo-aware and comes with a .torrent decoder out of the box:
```elixir
iex> File.read!("test/_data/ubuntu-14.04.4-desktop-amd64.iso.torrent") |> Bento.torrent!()
%Bento.Metainfo.Torrent{announce: "http://torrent.ubuntu.com:6969/announce",
"announce-list": [["http://torrent.ubuntu.com:6969/announce"],
["http://ipv6.torrent.ubuntu.com:6969/announce"]],
comment: "Ubuntu CD releases.ubuntu.com", "created by": nil,
"creation date": 1455826371, encoding: nil,
info: %Bento.Metainfo.SingleFile{length: 1069547520, md5sum: nil,
name: "ubuntu-14.04.4-desktop-amd64.iso", "piece length": 524288,
pieces: <<109, 235, 143, 234, 36, 25, 142, 36, 20, 3, 227, 227, 134, 136, 205, 130, 176, ...>>,
private: nil}}
```
Since Bento uses [Poison](https://hex.pm/packages/poison)'s Decoder module for `.torrent()`, this means it also supports decoding bencoded data into any struct you choose, like so:
```elixir
defmodule Name do
defstruct [:family, :given]
end
iex> Bento.decode!("d6:family4:Folz5:given6:Rodneye", as: %Name{})
%Name{family: "Folz", given: "Rodney"}
```
## Benchmarking
```
$ MIX_ENV=bench mix bench
```
We currently benchmark against: [Bento](https://github.com/folz/bento) (this project), [bencode](https://github.com/gausby/bencode), [Bencodex](https://github.com/patrickgombert/Bencodex), [bencoder](https://github.com/alehander42/bencoder), and [bencoded](https://github.com/galina/bencoded).
We are aware of, but unable to benchmark against: [exbencode](https://github.com/antifuchs/exbencode) (build errors), and [elixir_bencode](https://github.com/AntonFagerberg/elixir_bencode) (module name conflicts with Bencode).
PRs that add libraries to the benchmarks are greatly appreciated!
## License
See [LICENSE](LICENSE).