Sml.Parser (SmlEx v0.1.0)

Copy Markdown View Source

Low-level parser for the SML binary encoding (type-length-value).

Every element starts with one or more TL bytes:

bit 7     more TL bytes follow
bits 6-4  type: 000 octet string, 100 boolean, 101 integer,
                110 unsigned, 111 list
bits 3-0  length nibble

With multiple TL bytes the length nibbles are concatenated. For lists the length is the number of elements; for all other types it is the number of bytes including the TL bytes.

Elements are mapped to plain Elixir terms:

SMLElixir
octet stringbinary
booleantrue / false
integer / unsignedinteger
listlist
0x01 (optional, absent)nil
0x00 (end of message):end_of_message

Signedness is lost in this representation; Sml.Decoder knows the schema and does not need it.

Summary

Functions

Parses one element from the beginning of data.

Parses all elements in data until it is exhausted.

Parses only the TL header of a list and returns its element count.

Parses count consecutive elements.

Types

error()

@type error() :: {:error, reason :: atom() | tuple(), rest :: binary()}

term_t()

@type term_t() ::
  binary() | boolean() | integer() | nil | :end_of_message | [term_t()]

Functions

parse(data)

@spec parse(binary()) :: {:ok, term_t(), binary()} | error()

Parses one element from the beginning of data.

Returns the element and the remaining bytes. On failure the remaining bytes point at the element that could not be parsed.

iex> Sml.Parser.parse(<<0x62, 0x1E, 0xFF>>)
{:ok, 30, <<0xFF>>}

iex> Sml.Parser.parse(<<0x72, 0x03, "EM", 0x52, 0xFF>>)
{:ok, ["EM", -1], ""}

parse_all(data)

@spec parse_all(binary()) :: {:ok, [term_t()]} | error()

Parses all elements in data until it is exhausted.

Handy for inspecting unknown data:

iex> Sml.Parser.parse_all(<<0x01, 0x42, 0x01, 0x00>>)
{:ok, [nil, true, :end_of_message]}

parse_list_header(data)

@spec parse_list_header(binary()) :: {:ok, non_neg_integer(), binary()} | error()

Parses only the TL header of a list and returns its element count.

parse_many(data, count)

@spec parse_many(binary(), non_neg_integer()) :: {:ok, [term_t()], binary()} | error()

Parses count consecutive elements.