F3.FlatBuffer (F3 v0.1.0)

Copy Markdown

Bounded reader for the FlatBuffers tables this library needs.

Offsets are checked against the buffer before every read. A table that points at itself stops at a depth or visit cap and returns :depth rather than looping. This is not a general FlatBuffers toolkit. Field numbers are the positions in the pinned File.fbs and in Arrow IPC 53.

Summary

Types

:corrupt is a bad offset. :depth is the visit or nesting cap.

t()

One open table.

Functions

Raw byte vector, including an Arrow IPC message. Absent is nil.

Same as scalar/4, but an absent slot is nil instead of a default.

Opens the root table. The first four bytes are a little-endian offset from the start of bin. An empty or non-binary buffer is :corrupt. This does not raise for those inputs.

Signed or unsigned little-endian scalar. An absent slot returns default.

UTF-8 string. Absent is nil. Bytes that are not UTF-8 are :corrupt.

Vector of UTF-8 strings. Absent is an empty list.

Follows a table slot. Absent is nil. A slot that does not point at a table is :corrupt.

Vector of tables. Absent is an empty list.

Vector of unsigned little-endian integers. Absent is an empty list. width is 4 or 8. Any other width raises FunctionClauseError.

Union stored as a type byte at type_index and a table at the next slot.

Types

error()

@type error() :: :corrupt | :depth

:corrupt is a bad offset. :depth is the visit or nesting cap.

t()

@type t() :: %F3.FlatBuffer{
  bin: binary(),
  depth: non_neg_integer(),
  object_size: pos_integer(),
  pos: non_neg_integer(),
  visits: non_neg_integer(),
  vtable: non_neg_integer(),
  vtable_size: pos_integer()
}

One open table.

bin is the whole buffer. pos is the table's start. vtable is the vtable start. vtable_size and object_size come from that vtable. depth counts nested tables. visits counts tables opened from this root.

Functions

bytes(table, index)

@spec bytes(t(), non_neg_integer()) :: {:ok, binary() | nil} | {:error, error()}

Raw byte vector, including an Arrow IPC message. Absent is nil.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.bytes(table, 1)
{:ok, nil}

optional_scalar(table, index, kind)

@spec optional_scalar(
  t(),
  non_neg_integer(),
  :u8 | :u16 | :u32 | :u64 | :i16 | :i32 | :bool
) ::
  {:ok, term() | nil} | {:error, error()}

Same as scalar/4, but an absent slot is nil instead of a default.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.optional_scalar(table, 1, :u8)
{:ok, nil}

root(bin)

@spec root(binary()) :: {:ok, t()} | {:error, error()}

Opens the root table. The first four bytes are a little-endian offset from the start of bin. An empty or non-binary buffer is :corrupt. This does not raise for those inputs.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> table.pos
10

iex> F3.FlatBuffer.root(<<>>)
{:error, :corrupt}

scalar(table, index, kind, default)

@spec scalar(
  t(),
  non_neg_integer(),
  :u8 | :u16 | :u32 | :u64 | :i16 | :i32 | :bool,
  term()
) ::
  {:ok, term()} | {:error, error()}

Signed or unsigned little-endian scalar. An absent slot returns default.

index is the vtable field, starting at 0. kind is :u8, :u16, :u32, :u64, :i16, :i32, or :bool. A bad offset is :corrupt.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.scalar(table, 0, :u8, 0)
{:ok, 7}
iex> F3.FlatBuffer.scalar(table, 1, :u8, 0)
{:ok, 0}

string(table, index)

@spec string(t(), non_neg_integer()) :: {:ok, String.t() | nil} | {:error, error()}

UTF-8 string. Absent is nil. Bytes that are not UTF-8 are :corrupt.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.string(table, 1)
{:ok, nil}

string_vector(table, index)

@spec string_vector(t(), non_neg_integer()) :: {:ok, [String.t()]} | {:error, error()}

Vector of UTF-8 strings. Absent is an empty list.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.string_vector(table, 1)
{:ok, []}

table(table, index)

@spec table(t(), non_neg_integer()) :: {:ok, t() | nil} | {:error, error()}

Follows a table slot. Absent is nil. A slot that does not point at a table is :corrupt.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.table(table, 1)
{:ok, nil}

tables(table, index)

@spec tables(t(), non_neg_integer()) :: {:ok, [t()]} | {:error, error()}

Vector of tables. Absent is an empty list.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.tables(table, 1)
{:ok, []}

uints(table, index, width)

@spec uints(t(), non_neg_integer(), 4 | 8) ::
  {:ok, [non_neg_integer()]} | {:error, error()}

Vector of unsigned little-endian integers. Absent is an empty list. width is 4 or 8. Any other width raises FunctionClauseError.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 7, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.uints(table, 1, 4)
{:ok, []}

union(table, type_index)

@spec union(t(), non_neg_integer()) ::
  {:ok, :none | {non_neg_integer(), t()}} | {:error, error()}

Union stored as a type byte at type_index and a table at the next slot.

Type 0 is none. Any other type follows the table. The caller interprets the type byte. A non-zero type with no table is :corrupt.

Examples

iex> bin = <<10::little-32, 6::little-16, 8::little-16, 4::little-16, 6::little-32, 0, 0, 0, 0>>
iex> {:ok, table} = F3.FlatBuffer.root(bin)
iex> F3.FlatBuffer.union(table, 0)
{:ok, :none}