Codex (bin_codex v0.1.1)
Provides functions to create composable and bidirectional serializers.
Introduction
The Codex
module provides a number of predefined codecs and combinators that you can use to build new codes.
iex> import Codex
...> first_codec = [byte(), byte(), byte()] |> sequence()
...> <<0x10, 0xFF, 0xAB>> |> decode(first_codec)
{:ok, [16, 255, 171], <<>>}
Link to this section Summary
Functions
Combines two codecs into a codec that produces a 2-element tuple of each value.
A codec that always encodes to and decodes from the same value.
Creates a new codec.
Decodes a value from its binary form using the supplied codec.
Encodes a value to its binary form using the supplied codec.
Creates a codec that always fails with the supplied error message.
Creates a codec that always fails with the supplied error messages.
Uses the first codec, falling back to the second if it fails.
A codec that always decodes to a certain value.
Link to this section Types
boolean_codec()
Specs
codec(a)
Specs
decode_result(a)
Specs
decode_result(a) :: {:ok, a, remaining_bits()} | {:error, String.t(), remaining_bits()}
decoder(a)
Specs
decoder(a) :: (bitstring() -> decode_result(a))
encode_result()
Specs
encoder(a)
Specs
encoder(a) :: (a -> encode_result())
list_codec(a)
Specs
list_codec(a) :: codec([a])
remaining_bits()
Specs
remaining_bits() :: bitstring()
type()
Specs
type() :: any()
type2()
Specs
type2() :: any()
Link to this section Functions
append(list_codec, codec)
Specs
append(list_codec(type()), codec(type())) :: list_codec(type())
bit()
Specs
bit() :: codec(0 | 1)
bits(count)
Specs
bits(non_neg_integer()) :: codec(non_neg_integer())
bits_remaining()
Specs
bits_remaining() :: boolean_codec()
bool_bit()
Specs
bool_bit() :: boolean_codec()
byte()
Specs
byte() :: codec(non_neg_integer())
bytes(count)
Specs
bytes(non_neg_integer()) :: codec(non_neg_integer())
choice(list)
Specs
choice([codec(type())]) :: list_codec(type())
combine(codec1, codec2)
Specs
Combines two codecs into a codec that produces a 2-element tuple of each value.
Examples
iex> import Codex
...> {198, 2} |> encode(combine(byte(), byte()))
{:ok, <<198, 2>>}
...> <<198, 2>> |> decode(combine(byte(), byte()))
{:ok, {198, 2}, <<>>}
cons(codec, list_codec)
Specs
cons(codec(type()), list_codec(type())) :: list_codec(type())
constant(value, bits)
Specs
A codec that always encodes to and decodes from the same value.
It fails if it doesn't see the expected value that it always encodes/decodes.
Examples
iex> import Codex
...> codec = constant(10, <<200>>)
...> <<200>> |> decode(codec)
{:ok, 10, <<>>}
...> <<234>> |> decode(codec)
{:error, "<<234>> did not equal <<200>> in constant", <<234>>}
...> 10 |> encode(codec)
{:ok, <<200>>}
...> 22 |> encode(codec)
{:error, "22 did not equal 10 in constant"}
convert(codec, convert_to, convert_from)
Specs
create(encode, decode)
Specs
Creates a new codec.
It is recommended to use the other, well tested, functions in the module to build a codec instead of creating your own unless you absolutely have to.
When creating your own codec it MUST be idempotent.
Examples
iex> Codex.create(fn _ -> {:ok, <<>>} end, fn
...> <<>> -> {:ok, false, <<>>}
...> bits -> {:ok, true, bits}
...> end)
#Codex<...>
decode(bits, codex)
Specs
decode(bitstring(), codec(type())) :: decode_result(type())
Decodes a value from its binary form using the supplied codec.
The third element of the tuple is any remaining unparsed bits.
Examples
iex> import Codex
iex> <<198>> |> decode(byte())
{:ok, 198, <<>>}
done(codec)
Specs
empty()
Specs
encode(value, codex)
Specs
encode(type(), codec(type())) :: encode_result()
Encodes a value to its binary form using the supplied codec.
Examples
iex> import Codex
...> 198 |> encode(byte())
{:ok, <<198>>}
ensure(codec, boolean_codec, error)
Specs
fail(error)
Specs
Creates a codec that always fails with the supplied error message.
This is not useful on its own but can be useful when building other codecs.
Examples
iex> defmodule Example do
...> import Codex
...> def choose([]), do: fail("None of the choices worked")
...> def choose([codec | rest]), do: fallback(codec, choice(rest))
...> end
...> <<1>> |> Codex.decode(Example.choose([Codex.byte(), Codex.bits(4)]))
{:ok, 1, <<>>}
...> <<1::2>> |> Codex.decode(Example.choose([Codex.bits(4), Codex.byte()]))
{:error, "None of the choices worked", <<1::2>>}
fail(encode_error, decode_error)
Specs
Creates a codec that always fails with the supplied error messages.
Same as fail/1
but you can supply a different error message for encoding and decoding.
fallback(codec1, codec2)
Specs
Uses the first codec, falling back to the second if it fails.
Examples
iex> import Codex
...> optional_byte = byte() |> fallback(nothing())
...> <<8>> |> Codex.decode(optional_byte)
{:ok, 8, <<>>}
...> <<8::4>> |> Codex.decode(optional_byte)
{:ok, nil, <<8::4>>}
join(codec, group_size \\ 1)
Specs
join(list_codec(binary()), pos_integer()) :: codec(binary())
length_prefixed(length_codec, codec)
Specs
length_prefixed(codec(non_neg_integer()), codec(type())) :: list_codec(type())
list(codec)
Specs
list(codec(type())) :: list_codec(type())
list_of(count, codec)
Specs
list_of(non_neg_integer(), codec(type())) :: list_codec(type())
lookahead(codec)
Specs
lookahead(codec(any())) :: boolean_codec()
non_empty_list(codec)
Specs
not_(boolean_codec)
Specs
not_(boolean_codec()) :: boolean_codec()
nothing()
Specs
optional(codec)
Specs
pad(codec, bits)
peek(codec)
Specs
recover(codec)
Specs
recover(codec(any())) :: boolean_codec()
refute(codec, boolean_codec, error)
Specs
reverse(list_codec)
Specs
reverse(list_codec(type())) :: list_codec(type())
sequence(list)
Specs
sequence([codec(type())]) :: list_codec(type())
take_until(codec, boolean_codec)
Specs
take_until(codec(type()), boolean_codec()) :: list_codec(type())
take_while(boolean_codec, codec)
Specs
take_while(boolean_codec(), codec(type())) :: list_codec(type())
then(codec, f, g)
Specs
value(value)
Specs
A codec that always decodes to a certain value.
It never consumes bits while decoding so it can't fail. It can fail on encoding if the value to encode doesn't match.
Examples
iex> import Codex
...> codec = value(10)
...> <<>> |> decode(codec)
{:ok, 10, <<>>}
...> <<200>> |> decode(codec)
{:ok, 10, <<200>>}
...> 10 |> encode(codec)
{:ok, <<>>}
...> 22 |> encode(codec)
{:error, "22 did not equal 10 in constant"}