Packages

An incredibly fast, pure Elixir Bencoding library.

Current section

Files

Jump to
bento lib bento.ex
Raw

lib/bento.ex

defmodule Bento do
alias Bento.Encoder
alias Bento.Parser
alias Bento.Metainfo
@doc """
Bencode a value.
iex> Bento.encode([1, "two", [3]])
{:ok, "li1e3:twoli3eee"}
"""
@spec encode(Encoder.t, Keyword.t) :: {:ok, iodata} | {:ok, String.t} | {:error, {:invalid, any}}
def encode(value, options \\ []) do
{:ok, encode!(value, options)}
rescue
exception in [Bento.EncodeError] ->
{:error, {:invalid, exception.value}}
end
@doc """
Bencode a value as iodata.
iex> Bento.encode_to_iodata([1, "two", [3]])
{:ok, [108, [[105, "1", 101], ["3", 58, "two"], [108, [[105, "3", 101]], 101]], 101]}
"""
@spec encode_to_iodata(Encoder.t, Keyword.t) :: {:ok, iodata} | {:error, {:invalid, any}}
def encode_to_iodata(value, options \\ []) do
encode(value, [iodata: true] ++ options)
end
@doc """
Bencode a value, raises an exception on error.
iex> Bento.encode!([1, "two", [3]])
"li1e3:twoli3eee"
"""
@spec encode!(Encoder.t, Keyword.t) :: iodata | no_return
def encode!(value, options \\ []) do
iodata = Encoder.encode(value)
unless options[:iodata] do
iodata |> IO.iodata_to_binary()
else
iodata
end
end
@doc """
Decode bencoded data to a value.
iex> Bento.decode("li1e3:twoli3eee")
{:ok, [1, "two", [3]]}
"""
@spec decode(iodata, Keyword.t) :: {:ok, Parser.t} | {:error, :invalid} | {:error, {:invalid, String.t}}
def decode(iodata, options \\ []) do
case Parser.parse(iodata) do
{:ok, value} -> {:ok, Poison.Decode.decode(value, options)}
error -> error
end
end
@doc """
Decode bencoded data to a value, raises an exception on error.
iex> Bento.decode!("li1e3:twoli3eee")
[1, "two", [3]]
"""
@spec decode!(iodata, Keyword.t) :: Parser.t | no_return
def decode!(iodata, options \\ []) do
Parser.parse!(iodata) |> Poison.Decode.decode(options)
end
@doc """
Like `decode`, but ensures the data is a valid torrent metainfo file.
"""
def torrent(iodata) do
case decode(iodata, as: %Metainfo.Torrent{}) do
{:ok, value} ->
case Metainfo.info(value) do
{:ok, info} -> struct(value, %{"info" => info})
error -> error
end
error -> error
end
end
@doc """
Like `decode!`, but ensures the data is a valid torrent metainfo file.
"""
def torrent!(iodata) do
torrent = decode!(iodata, as: %Metainfo.Torrent{})
struct(torrent, ["info": Metainfo.info!(torrent)])
end
end