This is a 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.
Schema file:
table Root {
foreground:Color;
background:Color;
}
table Color {
red: ubyte;
green: ubyte;
blue: ubyte;
}
root_type Root;
Parsing the schema:
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:
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:
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:
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
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:
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:
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:
iex(3)> ColorScheme.get(color_scheme_fb, :background)
%{blue: 128, green: 100, red: 0}
iex(4)> ColorScheme.get(color_scheme_fb, [:background, :green])
100
- tables
- scalars
- strings
- vflatbufferrs
- structs
- unions
- enums
- defaults
- file identifier + validation
- random access
- validate file identifiers
- includes
- shared strings
- shared vtables
- alignment
- additional attributes