README.md

[![Build Status](https://github.com/jallum/flatbuffer/workflows/CI/badge.svg)](https://github.com/jallum/flatbuffer/actions) [![Hex.pm](https://img.shields.io/hexpm/v/flatbuffer.svg)](https://hex.pm/packages/flatbuffer) [![Documentation](https://img.shields.io/badge/documentation-gray)](https://hexdocs.pm/flatbuffer/)


---

# Flatbuffer

This is a [flatbuffers](https://google.github.io/flatbuffers/) implementation in Elixir.

In contrast to existing implementations there is no need to compile code from a schema. Instead, data and schemas are processed dynamically at runtime, offering greater flexibility.

## Using Flatbuffer

Schema file:
```
table Root {
  foreground:Color;
  background:Color;
}

table Color {
  red:   ubyte;
  green: ubyte;
  blue:  ubyte;
}
root_type Root;
```

Parsing the schema:
```elixir
iex(1)> {:ok, schema} = Flatbuffer.Schema.from_file("Example.fbs")
{:ok,
 %Flatbuffer.Schema{
   entities: %{
     "Color" => {:table,
      %{
        fields: [
          red: {:ubyte, %{default: 0}},
          green: {:ubyte, %{default: 0}},
          blue: {:ubyte, %{default: 0}}
        ],
        indices: %{
          blue: {2, {:ubyte, %{default: 0}}},
          green: {1, {:ubyte, %{default: 0}}},
          red: {0, {:ubyte, %{default: 0}}}
        }
      }},
     "Root" => {:table,
      %{
        fields: [
          foreground: {:table, %{name: "Color"}},
          background: {:table, %{name: "Color"}}
        ],
        indices: %{
          foreground: {0, {:table, %{name: "Color"}}},
          background: {1, {:table, %{name: "Color"}}}
        }
      }}
   },
   root_type: {:table, %{name: "Root"}},
   id: nil
 }}
 ```

Serializing data:
```elixir
iex(2)> color_scheme = %{foreground: %{red: 128, green: 20, blue: 255}, background: %{red: 0, green: 100, blue: 128}}
iex(3)> color_scheme_fb = Flatbuffer.to_binary(color_scheme, schema)
<<16, 0, 0, 0, 0, 0, 0, 0, 8, 0, 12, 0, 4, 0, 8, 0, 8, 0, 0, 0, 18, 0, 0,
  0, 31, 0, 0, 0, 10, 0, 7, 0, 4, 0, 5, 0, 6, 0, 10, 0, 0, 0, 128, 20,
  255, 10, 0, 6, 0, 0, ...>>
```

So we can `read` the whole thing which converts it back into a map:
```elixir
iex(4)> Flatbuffer.read!(color_scheme_fb, schema)
%{
  foreground: %{blue: 255, green: 20, red: 128},
  background: %{blue: 128, green: 100, red: 0}
}
```

Or we can `get` a value from the buffer without decoding the whole thing. This
can be done either with an atom key (for the root-table fields) or with a 
key-path composed of a list of atoms and integers:
```elixir
iex(5)> Flatbuffer.get(color_scheme_fb, [:background], schema)
%{blue: 128, green: 100, red: 0}
iex(6)> Flatbuffer.get(color_scheme_fb, [:background, :green], schema)
100
```

## Conveniences:

For schemas that will be often used or that need to be included with an
application, you can use `Flatbuffer.use/1` to compile the schema into a 
module:
```elixir
defmodule ColorScheme do
  use Flatbuffer,
    path: "priv/fb",
    schema: "color_scheme.fbs"
end
```

The schema (and any includes) will be read and parsed, and then compiled into 
the module. The source files for the schema do not need to be read again or 
included with the application. The functions of `Flatbuffer` are available in 
the module, but with the schema predefined.

For example:
```elixir
iex> color_scheme = %{foreground: %{red: 128, green: 20, blue: 255}, background: %{red: 0, green: 100, blue: 128}}
iex(2)> color_scheme_fb = ColorScheme.to_binary(color_scheme)
<<16, 0, 0, 0, 0, 0, 0, 0, 8, 0, 12, 0, 4, 0, 8, 0, 8, 0, 0, 0, 18, 0, 0,
  0, 31, 0, 0, 0, 10, 0, 7, 0, 4, 0, 5, 0, 6, 0, 10, 0, 0, 0, 128, 20,
  255, 10, 0, 6, 0, 0, ...>>
```

We can `get` a value from the buffer without decoding the whole thing. This
can be done either with an atom key (for the root-table fields) or with a 
key-path composed of a list of atoms and integers:

```elixir
iex(3)> ColorScheme.get(color_scheme_fb, :background)
%{blue: 128, green: 100, red: 0}
iex(4)> ColorScheme.get(color_scheme_fb, [:background, :green])
100
```


## Comparing Flatbuffer to flatc

### features both in Flatbuffer and flatc

* tables
* scalars
* strings
* vflatbufferrs
* structs
* unions
* enums
* defaults
* file identifier + validation
* random access
* validate file identifiers
* includes

### features only in flatcs

* shared strings
* shared vtables
* alignment
* additional attributes