Msgpax v1.1.0 Msgpax

This module provides functions for serializing and de-serializing Elixir terms using the MessagePack format.

Data conversion

The following table shows how Elixir types are serialized to MessagePack types and how MessagePack types are de-serialized back to Elixir types.

ElixirMessagePackElixir
nilnilnil
truebooleantrue
falsebooleanfalse
-1integer-1
1.25float1.25
:okstring"ok"
Atomstring"Elixir.Atom"
"str"string"str"
"\xFF\xFF"string"\xFF\xFF"
#Msgpax.Bin<"\xFF">binary"\xFF"
%{foo: "bar"}map%{"foo" => "bar"}
[foo: "bar"]map%{"foo" => "bar"}
[1, true]array[1, true]
#Msgpax.Ext<4, "02:12">extension#Msgpax.Ext<4, "02:12">

Summary

Functions

Serializes term

Works as pack/1, but raises if there’s an error

De-serializes the given iodata

Works like unpack/2, but raises in case of errors

De-serializes part of the given iodata

Works like unpack_slice/2 but raises in case of error

Types

pack_error_reason ::
  {:too_big, any} |
  {:not_encodable, any}
unpack_error_reason ::
  {:excess_bytes, binary} |
  {:bad_format, binary} |
  :incomplete |
  {:not_supported_ext, integer} |
  {:ext_unpack_failure, Msgpax.Ext.type, module, binary}

Functions

pack(term, options \\ [])

Specs

pack(term, Keyword.t) ::
  {:ok, iodata} |
  {:error, pack_error_reason}

Serializes term.

This function returns iodata by default; if you want to force the result to be a binary, you can use IO.iodata_to_binary/1 or use the :iodata option (see the “Options” section below).

This function returns {:ok, iodata} if the serialization is sucessful, {:error, reason} otherwise. Reason can be:

  • {:bad_arg, term} - means that the given argument is not serializable. For example, this is returned when you try to pack bits instead of a binary (as only binaries can be serialized).
  • {:too_big, term} - means that the given term is too big to be encoded. What “too big” means depends on the term being encoded; for example, integers larger than 18446744073709551616 are too big to be encoded with MessagePack.

Options

  • :iodata - (boolean) if true, this function returns the encoded term as iodata, if false as a binary.

Examples

iex> {:ok, packed} = Msgpax.pack("foo")
iex> IO.iodata_to_binary(packed)
<<163, 102, 111, 111>>

iex> Msgpax.pack(20000000000000000000)
{:error, {:too_big, 20000000000000000000}}

iex> Msgpax.pack("foo", iodata: false)
{:ok, <<163, 102, 111, 111>>}
pack!(term, options \\ [])

Specs

pack!(term, Keyword.t) :: iodata | no_return

Works as pack/1, but raises if there’s an error.

This function works like pack/1, except it returns the term (instead of {:ok, term}) if the serialization is successful and raises a Msgpax.PackError exception otherwise.

Options

This function accepts the same options as pack/2.

Examples

iex> "foo" |> Msgpax.pack!() |> IO.iodata_to_binary()
<<163, 102, 111, 111>>

iex> Msgpax.pack!(20000000000000000000)
** (Msgpax.PackError) value is too big: 20000000000000000000

iex> Msgpax.pack!("foo", iodata: false)
<<163, 102, 111, 111>>
unpack(iodata, opts \\ [])

Specs

unpack(iodata, Keyword.t) ::
  {:ok, any} |
  {:error, unpack_error_reason}

De-serializes the given iodata.

This function de-serializes the given iodata into an Elixir term. It returns {:ok, term} if de-serialization is successful, {:error, reason} otherwise.

Options

  • :binary - (boolean) if true, then binaries are decoded as Msgpax.Bin structs instead of plain Elixir binaries.
  • :ext - (module) a module that implements the Msgpax.Ext.Unpacker behaviour. For more information, see the docs for Msgpax.Ext.Unpacker.

Examples

iex> Msgpax.unpack(<<163, "foo">>)
{:ok, "foo"}

iex> Msgpax.unpack(<<163, "foo", "junk">>)
{:error, {:excess_bytes, "junk"}}

iex> packed = Msgpax.pack!(Msgpax.Bin.new(<<3, 18, 122, 27, 115>>))
iex> {:ok, bin} = Msgpax.unpack(packed, binary: true)
iex> bin
#Msgpax.Bin<<<3, 18, 122, 27, 115>>>
unpack!(iodata, opts \\ [])

Specs

unpack!(iodata, Keyword.t) :: any | no_return

Works like unpack/2, but raises in case of errors.

This function works like unpack/2, but it returns term (instead of {:ok, term}) if de-serialization is successful, otherwise raises a Msgpax.UnpackError exception.

Example

iex> Msgpax.unpack!(<<163, "foo">>)
"foo"

iex> Msgpax.unpack!(<<163, "foo", "junk">>)
** (Msgpax.UnpackError) found excess bytes: "junk"

iex> packed = Msgpax.pack!(Msgpax.Bin.new(<<3, 18, 122, 27, 115>>))
iex> Msgpax.unpack!(packed, binary: true)
#Msgpax.Bin<<<3, 18, 122, 27, 115>>>
unpack_slice(iodata, opts \\ [])

Specs

unpack_slice(iodata, Keyword.t) ::
  {:ok, any, binary} |
  {:error, unpack_error_reason}

De-serializes part of the given iodata.

This function works like unpack/2, but instead of requiring the input to be a MessagePack-serialized term with nothing after that, it accepts leftover bytes at the end of iodata and only de-serializes the part of the input that makes sense. It returns {:ok, term, rest} if de-serialization is successful, {:error, reason} otherwise.

See unpack/2 for more information on the supported options.

Examples

iex> Msgpax.unpack_slice(<<163, "foo", "junk">>)
{:ok, "foo", "junk"}

iex> Msgpax.unpack_slice(<<163, "fo">>)
{:error, {:bad_format, 163}}
unpack_slice!(iodata, opts \\ [])

Specs

unpack_slice!(iodata, Keyword.t) ::
  {any, binary} |
  no_return

Works like unpack_slice/2 but raises in case of error.

This function works like unpack_slice/2, but returns just {term, rest} if de-serialization is successful and raises a Msgpax.UnpackError exception if it’s not.

Examples

iex> Msgpax.unpack_slice!(<<163, "foo", "junk">>)
{"foo", "junk"}

iex> Msgpax.unpack_slice!(<<163, "fo">>)
** (Msgpax.UnpackError) bad format: 163