VelocyPack

An Elixir parser and generator for VelocyPack v1.

The implementation is heavily inspired by Jason and borrows some code (specifically the Codegen module).

Examples

iex> {:ok, vpack} = VelocyPack.encode(10.2312514)
{:ok, <<27, 245, 78, 96, 149, 102, 118, 36, 64>>}
iex> VelocyPack.decode(vpack)
{:ok, 10.2312514}
iex> vpack = VelocyPack.encode!(%{a: "a", b: %{bool: true, float: 10.2312514}})
<<11, 37, 2, 65, 97, 65, 97, 65, 98, 11, 26, 2, 68, 98, 111, 111, 108, 26, 69, 102, 108, 111, 97, 116, 27, 245, 78, 96, 149, 102, 118, 36, 64, 3, 9, 3, 7>>
iex> VelocyPack.decode!(vpack)
%{"a" => "a", "b" => %{"bool" => true, "float" => 10.2312514}}
iex> VelocyPack.decode(<<11>>)
{:error, %VelocyPack.Error{message: "unexpected sequence", dump: nil}}
iex> VelocyPack.decode!(<<11>>)
** (VelocyPack.Error) unexpected sequence
iex> VelocyPack.decode(<<11, 823891328731>>)
{:error, %VelocyPack.Error{message: "unexpected byte", dump: "<<0xDB>>"}}
iex> VelocyPack.decode!(<<11, 823891328731>>)
** (VelocyPack.Error) unexpected byte: <<0xDB>>

Errors

decode/2 and encode/2 return {:error, reason} for malformed input instead of raising. Some of decode/2's reasons are plain terms naming where parsing stopped, rather than VelocyPack.Error exceptions:

iex> VelocyPack.decode(<<>>)
{:error, :unexpected_end}
iex> VelocyPack.decode(<<0x15>>)
{:error, {:unsupported_type, 21}}

decode!/2 raises all of them as VelocyPack.Error. encode/2's reasons are always exceptions, but of two types - Protocol.UndefinedError for a term with no VelocyPack.Encoder implementation, and VelocyPack.Error for an out-of-range integer or an invalid key. See the docs for VelocyPack.decode/2 and VelocyPack.encode/2 for the complete set.