<div class="contents">
<div class="textblock"><p>Assuming you have written a schema using the above language in say <code>mygame.fbs</code> (FlatBuffer Schema, though the extension doesn't matter), you've generated a C++ header called <code>mygame_generated.h</code> using the compiler (e.g. <code>flatc -c mygame.fbs</code>), you can now start using this in your program by including the header. As noted, this header relies on <code>flatbuffers/flatbuffers.h</code>, which should be in your include path.</p>
<h3>Writing in C++</h3>
-<p>To start creating a buffer, create an instance of <code>FlatBufferBuilder</code> which will contain the buffer as it grows: </p><pre class="fragment">FlatBufferBuilder fbb;
-</pre><p>Before we serialize a Monster, we need to first serialize any objects that are contained there-in, i.e. we serialize the data tree using depth first, pre-order traversal. This is generally easy to do on any tree structures. For example: </p><pre class="fragment">auto name = fbb.CreateString("MyMonster");
-
-unsigned char inv[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
-auto inventory = fbb.CreateVector(inv, 10);
-</pre><p><code>CreateString</code> and <code>CreateVector</code> serialize these two built-in datatypes, and return offsets into the serialized data indicating where they are stored, such that <code>Monster</code> below can refer to them.</p>
+<p>To start creating a buffer, create an instance of <code>FlatBufferBuilder</code> which will contain the buffer as it grows:</p>
+<div class="fragment"><div class="line">FlatBufferBuilder fbb;</div>
+</div><!-- fragment --><p>Before we serialize a Monster, we need to first serialize any objects that are contained there-in, i.e. we serialize the data tree using depth first, pre-order traversal. This is generally easy to do on any tree structures. For example:</p>
+<div class="fragment"><div class="line"><span class="keyword">auto</span> name = fbb.CreateString(<span class="stringliteral">"MyMonster"</span>);</div>
+<div class="line"></div>
+<div class="line"><span class="keywordtype">unsigned</span> <span class="keywordtype">char</span> inv[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };</div>
+<div class="line"><span class="keyword">auto</span> inventory = fbb.CreateVector(inv, 10);</div>
+</div><!-- fragment --><p><code>CreateString</code> and <code>CreateVector</code> serialize these two built-in datatypes, and return offsets into the serialized data indicating where they are stored, such that <code>Monster</code> below can refer to them.</p>
<p><code>CreateString</code> can also take an <code>std::string</code>, or a <code>const char *</code> with an explicit length, and is suitable for holding UTF-8 and binary data if needed.</p>
-<p><code>CreateVector</code> can also take an <code>std::vector</code>. The offset it returns is typed, i.e. can only be used to set fields of the correct type below. To create a vector of struct objects (which will be stored as contiguous memory in the buffer, use <code>CreateVectorOfStructs</code> instead. </p><pre class="fragment">Vec3 vec(1, 2, 3);
-</pre><p><code>Vec3</code> is the first example of code from our generated header. Structs (unlike tables) translate to simple structs in C++, so we can construct them in a familiar way.</p>
-<p>We have now serialized the non-scalar components of of the monster example, so we could create the monster something like this: </p><pre class="fragment">auto mloc = CreateMonster(fbb, &vec, 150, 80, name, inventory, Color_Red, 0, Any_NONE);
-</pre><p>Note that we're passing <code>150</code> for the <code>mana</code> field, which happens to be the default value: this means the field will not actually be written to the buffer, since we'll get that value anyway when we query it. This is a nice space savings, since it is very common for fields to be at their default. It means we also don't need to be scared to add fields only used in a minority of cases, since they won't bloat up the buffer sizes if they're not actually used.</p>
+<p><code>CreateVector</code> can also take an <code>std::vector</code>. The offset it returns is typed, i.e. can only be used to set fields of the correct type below. To create a vector of struct objects (which will be stored as contiguous memory in the buffer, use <code>CreateVectorOfStructs</code> instead.</p>
+<div class="fragment"><div class="line">Vec3 vec(1, 2, 3);</div>
+</div><!-- fragment --><p><code>Vec3</code> is the first example of code from our generated header. Structs (unlike tables) translate to simple structs in C++, so we can construct them in a familiar way.</p>
+<p>We have now serialized the non-scalar components of of the monster example, so we could create the monster something like this:</p>
+<div class="fragment"><div class="line"><span class="keyword">auto</span> mloc = CreateMonster(fbb, &vec, 150, 80, name, inventory, Color_Red, 0, Any_NONE);</div>
+</div><!-- fragment --><p>Note that we're passing <code>150</code> for the <code>mana</code> field, which happens to be the default value: this means the field will not actually be written to the buffer, since we'll get that value anyway when we query it. This is a nice space savings, since it is very common for fields to be at their default. It means we also don't need to be scared to add fields only used in a minority of cases, since they won't bloat up the buffer sizes if they're not actually used.</p>
<p>We do something similarly for the union field <code>test</code> by specifying a <code>0</code> offset and the <code>NONE</code> enum value (part of every union) to indicate we don't actually want to write this field. You can use <code>0</code> also as a default for other non-scalar types, such as strings, vectors and tables.</p>
-<p>Tables (like <code>Monster</code>) give you full flexibility on what fields you write (unlike <code>Vec3</code>, which always has all fields set because it is a <code>struct</code>). If you want even more control over this (i.e. skip fields even when they are not default), instead of the convenient <code>CreateMonster</code> call we can also build the object field-by-field manually: </p><pre class="fragment">MonsterBuilder mb(fbb);
-mb.add_pos(&vec);
-mb.add_hp(80);
-mb.add_name(name);
-mb.add_inventory(inventory);
-auto mloc = mb.Finish();
-</pre><p>We start with a temporary helper class <code>MonsterBuilder</code> (which is defined in our generated code also), then call the various <code>add_</code> methods to set fields, and <code>Finish</code> to complete the object. This is pretty much the same code as you find inside <code>CreateMonster</code>, except we're leaving out a few fields. Fields may also be added in any order, though orderings with fields of the same size adjacent to each other most efficient in size, due to alignment. You should not nest these Builder classes (serialize your data in pre-order).</p>
-<p>Regardless of whether you used <code>CreateMonster</code> or <code>MonsterBuilder</code>, you now have an offset to the root of your data, and you can finish the buffer using: </p><pre class="fragment">FinishMonsterBuffer(fbb, mloc);
-</pre><p>The buffer is now ready to be stored somewhere, sent over the network, be compressed, or whatever you'd like to do with it. You can access the start of the buffer with <code>fbb.GetBufferPointer()</code>, and it's size from <code>fbb.GetSize()</code>.</p>
+<p>Tables (like <code>Monster</code>) give you full flexibility on what fields you write (unlike <code>Vec3</code>, which always has all fields set because it is a <code>struct</code>). If you want even more control over this (i.e. skip fields even when they are not default), instead of the convenient <code>CreateMonster</code> call we can also build the object field-by-field manually:</p>
+<div class="fragment"><div class="line">MonsterBuilder mb(fbb);</div>
+<div class="line">mb.add_pos(&vec);</div>
+<div class="line">mb.add_hp(80);</div>
+<div class="line">mb.add_name(name);</div>
+<div class="line">mb.add_inventory(inventory);</div>
+<div class="line"><span class="keyword">auto</span> mloc = mb.Finish();</div>
+</div><!-- fragment --><p>We start with a temporary helper class <code>MonsterBuilder</code> (which is defined in our generated code also), then call the various <code>add_</code> methods to set fields, and <code>Finish</code> to complete the object. This is pretty much the same code as you find inside <code>CreateMonster</code>, except we're leaving out a few fields. Fields may also be added in any order, though orderings with fields of the same size adjacent to each other most efficient in size, due to alignment. You should not nest these Builder classes (serialize your data in pre-order).</p>
+<p>Regardless of whether you used <code>CreateMonster</code> or <code>MonsterBuilder</code>, you now have an offset to the root of your data, and you can finish the buffer using:</p>
+<div class="fragment"><div class="line">FinishMonsterBuffer(fbb, mloc);</div>
+</div><!-- fragment --><p>The buffer is now ready to be stored somewhere, sent over the network, be compressed, or whatever you'd like to do with it. You can access the start of the buffer with <code>fbb.GetBufferPointer()</code>, and it's size from <code>fbb.GetSize()</code>.</p>
<p><code>samples/sample_binary.cpp</code> is a complete code sample similar to the code above, that also includes the reading code below.</p>
<h3>Reading in C++</h3>
-<p>If you've received a buffer from somewhere (disk, network, etc.) you can directly start traversing it using: </p><pre class="fragment">auto monster = GetMonster(buffer_pointer);
-</pre><p><code>monster</code> is of type <code>Monster *</code>, and points to somewhere inside your buffer. If you look in your generated header, you'll see it has convenient accessors for all fields, e.g. </p><pre class="fragment">assert(monster->hp() == 80);
-assert(monster->mana() == 150); // default
-assert(strcmp(monster->name()->c_str(), "MyMonster") == 0);
-</pre><p>These should all be true. Note that we never stored a <code>mana</code> value, so it will return the default.</p>
-<p>To access sub-objects, in this case the <code>Vec3</code>: </p><pre class="fragment">auto pos = monster->pos();
-assert(pos);
-assert(pos->z() == 3);
-</pre><p>If we had not set the <code>pos</code> field during serialization, it would be <code>NULL</code>.</p>
-<p>Similarly, we can access elements of the inventory array: </p><pre class="fragment">auto inv = monster->inventory();
-assert(inv);
-assert(inv->Get(9) == 9);
-</pre><h3>Direct memory access</h3>
+<p>If you've received a buffer from somewhere (disk, network, etc.) you can directly start traversing it using:</p>
+<div class="fragment"><div class="line"><span class="keyword">auto</span> monster = GetMonster(buffer_pointer);</div>
+</div><!-- fragment --><p><code>monster</code> is of type <code>Monster *</code>, and points to somewhere inside your buffer. If you look in your generated header, you'll see it has convenient accessors for all fields, e.g.</p>
+<div class="fragment"><div class="line">assert(monster->hp() == 80);</div>
+<div class="line">assert(monster->mana() == 150); <span class="comment">// default</span></div>
+<div class="line">assert(strcmp(monster->name()->c_str(), <span class="stringliteral">"MyMonster"</span>) == 0);</div>
+</div><!-- fragment --><p>These should all be true. Note that we never stored a <code>mana</code> value, so it will return the default.</p>
+<p>To access sub-objects, in this case the <code>Vec3</code>:</p>
+<div class="fragment"><div class="line"><span class="keyword">auto</span> pos = monster->pos();</div>
+<div class="line">assert(pos);</div>
+<div class="line">assert(pos->z() == 3);</div>
+</div><!-- fragment --><p>If we had not set the <code>pos</code> field during serialization, it would be <code>NULL</code>.</p>
+<p>Similarly, we can access elements of the inventory array:</p>
+<div class="fragment"><div class="line"><span class="keyword">auto</span> inv = monster->inventory();</div>
+<div class="line">assert(inv);</div>
+<div class="line">assert(inv->Get(9) == 9);</div>
+</div><!-- fragment --><h3>Direct memory access</h3>
<p>As you can see from the above examples, all elements in a buffer are accessed through generated accessors. This is because everything is stored in little endian format on all platforms (the accessor performs a swap operation on big endian machines), and also because the layout of things is generally not known to the user.</p>
<p>For structs, layout is deterministic and guaranteed to be the same accross platforms (scalars are aligned to their own size, and structs themselves to their largest member), and you are allowed to access this memory directly by using <code>sizeof()</code> and <code>memcpy</code> on the pointer to a struct, or even an array of structs.</p>
<p>To compute offsets to sub-elements of a struct, make sure they are a structs themselves, as then you can use the pointers to figure out the offset without having to hardcode it. This is handy for use of arrays of structs with calls like <code>glVertexAttribPointer</code> in OpenGL or similar APIs.</p>
<p>When you're processing large amounts of data from a source you know (e.g. your own generated data on disk), this is acceptable, but when reading data from the network that can potentially have been modified by an attacker, this is undesirable.</p>
<p>For this reason, you can optionally use a buffer verifier before you access the data. This verifier will check all offsets, all sizes of fields, and null termination of strings to ensure that when a buffer is accessed, all reads will end up inside the buffer.</p>
<p>Each root type will have a verification function generated for it, e.g. for <code>Monster</code>, you can call:</p>
-<p>bool ok = VerifyMonsterBuffer(Verifier(buf, len));</p>
-<p>if <code>ok</code> is true, the buffer is safe to read.</p>
+<div class="fragment"><div class="line"><span class="keywordtype">bool</span> ok = VerifyMonsterBuffer(Verifier(buf, len));</div>
+</div><!-- fragment --><p>if <code>ok</code> is true, the buffer is safe to read.</p>
<p>Besides untrusted data, this function may be useful to call in debug mode, as extra insurance against data being corrupted somewhere along the way.</p>
<p>While verifying a buffer isn't "free", it is typically faster than a full traversal (since any scalar data is not actually touched), and since it may cause the buffer to be brought into cache before reading, the actual overhead may be even lower than expected.</p>
<p>In specialized cases where a denial of service attack is possible, the verifier has two additional constructor arguments that allow you to limit the nesting depth and total amount of tables the verifier may encounter before declaring the buffer malformed.</p>
<p>This gives you maximum flexibility. You could even opt to support both, i.e. check for both files, and regenerate the binary from text when required, otherwise just load the binary.</p>
<p>This option is currently only available for C++, or Java through JNI.</p>
<p>As mentioned in the section "Building" above, this technique requires you to link a few more files into your program, and you'll want to include <code>flatbuffers/idl.h</code>.</p>
-<p>Load text (either a schema or json) into an in-memory buffer (there is a convenient <code>LoadFile()</code> utility function in <code>flatbuffers/util.h</code> if you wish). Construct a parser: </p><pre class="fragment">flatbuffers::Parser parser;
-</pre><p>Now you can parse any number of text files in sequence: </p><pre class="fragment">parser.Parse(text_file.c_str());
-</pre><p>This works similarly to how the command-line compiler works: a sequence of files parsed by the same <code>Parser</code> object allow later files to reference definitions in earlier files. Typically this means you first load a schema file (which populates <code>Parser</code> with definitions), followed by one or more JSON files.</p>
+<p>Load text (either a schema or json) into an in-memory buffer (there is a convenient <code>LoadFile()</code> utility function in <code>flatbuffers/util.h</code> if you wish). Construct a parser:</p>
+<div class="fragment"><div class="line">flatbuffers::Parser parser;</div>
+</div><!-- fragment --><p>Now you can parse any number of text files in sequence:</p>
+<div class="fragment"><div class="line">parser.Parse(text_file.c_str());</div>
+</div><!-- fragment --><p>This works similarly to how the command-line compiler works: a sequence of files parsed by the same <code>Parser</code> object allow later files to reference definitions in earlier files. Typically this means you first load a schema file (which populates <code>Parser</code> with definitions), followed by one or more JSON files.</p>
<p>As optional argument to <code>Parse</code>, you may specify a null-terminated list of include paths. If not specified, any include statements try to resolve from the current directory.</p>
<p>If there were any parsing errors, <code>Parse</code> will return <code>false</code>, and <code>Parser::err</code> contains a human readable error string with a line number etc, which you should present to the creator of that file.</p>
<p>After each JSON file, the <code>Parser::fbb</code> member variable is the <code>FlatBufferBuilder</code> that contains the binary buffer version of that file, that you can access as described above.</p>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>There's experimental support for reading FlatBuffers in Go. Generate code for Go with the <code>-g</code> option to <code>flatc</code>.</p>
-<p>See <code>go_test.go</code> for an example. You import the generated code, read a FlatBuffer binary file into a <code>[]byte</code>, which you pass to the <code>GetRootAsMonster</code> function: </p><pre class="fragment">import (
- example "MyGame/Example"
- flatbuffers "github.com/google/flatbuffers/go"
-
- io/ioutil
-)
-
-buf, err := ioutil.ReadFile("monster.dat")
-// handle err
-monster := example.GetRootAsMonster(buf, 0)
-</pre><p>Now you can access values like this: </p><pre class="fragment">hp := monster.Hp()
-pos := monster.Pos(nil)
-</pre><p>Note that whenever you access a new object like in the <code>Pos</code> example above, a new temporary accessor object gets created. If your code is very performance sensitive (you iterate through a lot of objects), you can replace nil with a pointer to a <code>Vec3</code> object you've already created. This allows you to reuse it across many calls and reduce the amount of object allocation (and thus garbage collection) your program does.</p>
-<p>To access vectors you pass an extra index to the vector field accessor. Then a second method with the same name suffixed by <code>Length</code> let's you know the number of elements you can access: </p><pre class="fragment">for i := 0; i < monster.InventoryLength(); i++ {
- monster.Inventory(i) // do something here
-}
-</pre><p>You can also construct these buffers in Go using the functions found in the generated code, and the FlatBufferBuilder class: </p><pre class="fragment">builder := flatbuffers.NewBuilder(0)
-</pre><p>Create strings: </p><pre class="fragment">str := builder.CreateString("MyMonster")
-</pre><p>Create a table with a struct contained therein: </p><pre class="fragment">example.MonsterStart(builder)
-example.MonsterAddPos(builder, example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, 4, 5, 6))
-example.MonsterAddHp(builder, 80)
-example.MonsterAddName(builder, str)
-example.MonsterAddInventory(builder, inv)
-example.MonsterAddTest_Type(builder, 1)
-example.MonsterAddTest(builder, mon2)
-example.MonsterAddTest4(builder, test4s)
-mon := example.MonsterEnd(builder)
-</pre><p>Unlike C++, Go does not support table creation functions like 'createMonster()'. This is to create the buffer without using temporary object allocation (since the <code>Vec3</code> is an inline component of <code>Monster</code>, it has to be created right where it is added, whereas the name and the inventory are not inline). Structs do have convenient methods that allow you to construct them in one call. These also have arguments for nested structs, e.g. if a struct has a field <code>a</code> and a nested struct field <code>b</code> (which has fields <code>c</code> and <code>d</code>), then the arguments will be <code>a</code>, <code>c</code> and <code>d</code>.</p>
-<p>Vectors also use this start/end pattern to allow vectors of both scalar types and structs: </p><pre class="fragment">example.MonsterStartInventoryVector(builder, 5)
-for i := 4; i >= 0; i-- {
- builder.PrependByte(byte(i))
-}
-inv := builder.EndVector(5)
-</pre><p>The generated method 'StartInventoryVector' is provided as a convenience function which calls 'StartVector' with the correct element size of the vector type which in this case is 'ubyte' or 1 byte per vector element. You pass the number of elements you want to write. You write the elements backwards since the buffer is being constructed back to front.</p>
+<p>See <code>go_test.go</code> for an example. You import the generated code, read a FlatBuffer binary file into a <code>[]byte</code>, which you pass to the <code>GetRootAsMonster</code> function:</p>
+<div class="fragment"><div class="line"><span class="keyword">import</span> (</div>
+<div class="line"> example <span class="stringliteral">"MyGame/Example"</span></div>
+<div class="line"> flatbuffers <span class="stringliteral">"github.com/google/flatbuffers/go"</span></div>
+<div class="line"></div>
+<div class="line"> io/ioutil</div>
+<div class="line">)</div>
+<div class="line"></div>
+<div class="line">buf, err := ioutil.ReadFile(<span class="stringliteral">"monster.dat"</span>)</div>
+<div class="line"><span class="comment">// handle err</span></div>
+<div class="line">monster := example.GetRootAsMonster(buf, 0)</div>
+</div><!-- fragment --><p>Now you can access values like this:</p>
+<div class="fragment"><div class="line">hp := monster.Hp()</div>
+<div class="line">pos := monster.Pos(nil)</div>
+</div><!-- fragment --><p>Note that whenever you access a new object like in the <code>Pos</code> example above, a new temporary accessor object gets created. If your code is very performance sensitive (you iterate through a lot of objects), you can replace nil with a pointer to a <code>Vec3</code> object you've already created. This allows you to reuse it across many calls and reduce the amount of object allocation (and thus garbage collection) your program does.</p>
+<p>To access vectors you pass an extra index to the vector field accessor. Then a second method with the same name suffixed by <code>Length</code> let's you know the number of elements you can access:</p>
+<div class="fragment"><div class="line"><span class="keywordflow">for</span> i := 0; i < monster.InventoryLength(); i++ {</div>
+<div class="line"> monster.Inventory(i) <span class="comment">// do something here</span></div>
+<div class="line">}</div>
+</div><!-- fragment --><p>You can also construct these buffers in Go using the functions found in the generated code, and the FlatBufferBuilder class:</p>
+<div class="fragment"><div class="line">builder := flatbuffers.NewBuilder(0)</div>
+</div><!-- fragment --><p>Create strings:</p>
+<div class="fragment"><div class="line">str := builder.CreateString(<span class="stringliteral">"MyMonster"</span>)</div>
+</div><!-- fragment --><p>Create a table with a struct contained therein:</p>
+<div class="fragment"><div class="line">example.MonsterStart(builder)</div>
+<div class="line">example.MonsterAddPos(builder, example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, 4, 5, 6))</div>
+<div class="line">example.MonsterAddHp(builder, 80)</div>
+<div class="line">example.MonsterAddName(builder, str)</div>
+<div class="line">example.MonsterAddInventory(builder, inv)</div>
+<div class="line">example.MonsterAddTest_Type(builder, 1)</div>
+<div class="line">example.MonsterAddTest(builder, mon2)</div>
+<div class="line">example.MonsterAddTest4(builder, test4s)</div>
+<div class="line">mon := example.MonsterEnd(builder)</div>
+</div><!-- fragment --><p>Unlike C++, Go does not support table creation functions like 'createMonster()'. This is to create the buffer without using temporary object allocation (since the <code>Vec3</code> is an inline component of <code>Monster</code>, it has to be created right where it is added, whereas the name and the inventory are not inline). Structs do have convenient methods that allow you to construct them in one call. These also have arguments for nested structs, e.g. if a struct has a field <code>a</code> and a nested struct field <code>b</code> (which has fields <code>c</code> and <code>d</code>), then the arguments will be <code>a</code>, <code>c</code> and <code>d</code>.</p>
+<p>Vectors also use this start/end pattern to allow vectors of both scalar types and structs:</p>
+<div class="fragment"><div class="line">example.MonsterStartInventoryVector(builder, 5)</div>
+<div class="line"><span class="keywordflow">for</span> i := 4; i >= 0; i-- {</div>
+<div class="line"> builder.PrependByte(byte(i))</div>
+<div class="line">}</div>
+<div class="line">inv := builder.EndVector(5)</div>
+</div><!-- fragment --><p>The generated method 'StartInventoryVector' is provided as a convenience function which calls 'StartVector' with the correct element size of the vector type which in this case is 'ubyte' or 1 byte per vector element. You pass the number of elements you want to write. You write the elements backwards since the buffer is being constructed back to front.</p>
<p>There are <code>Prepend</code> functions for all the scalar types. You use <code>PrependUOffset</code> for any previously constructed objects (such as other tables, strings, vectors). For structs, you use the appropriate <code>create</code> function in-line, as shown above in the <code>Monster</code> example.</p>
<h2>Text Parsing</h2>
<p>There currently is no support for parsing text (Schema's and JSON) directly from Go, though you could use the C++ parser through cgo. Please see the C++ documentation for more on text parsing. </p>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>FlatBuffers supports reading and writing binary FlatBuffers in Java. Generate code for Java with the <code>-j</code> option to <code>flatc</code>.</p>
-<p>See <code>javaTest.java</code> for an example. Essentially, you read a FlatBuffer binary file into a <code>byte[]</code>, which you then turn into a <code>ByteBuffer</code>, which you pass to the <code>getRootAsMyRootType</code> function: </p><pre class="fragment">ByteBuffer bb = ByteBuffer.wrap(data);
-Monster monster = Monster.getRootAsMonster(bb);
-</pre><p>Now you can access values much like C++: </p><pre class="fragment">short hp = monster.hp();
-Vec3 pos = monster.pos();
-</pre><p>Note that whenever you access a new object like in the <code>pos</code> example above, a new temporary accessor object gets created. If your code is very performance sensitive (you iterate through a lot of objects), there's a second <code>pos()</code> method to which you can pass a <code>Vec3</code> object you've already created. This allows you to reuse it across many calls and reduce the amount of object allocation (and thus garbage collection) your program does.</p>
+<p>See <code>javaTest.java</code> for an example. Essentially, you read a FlatBuffer binary file into a <code>byte[]</code>, which you then turn into a <code>ByteBuffer</code>, which you pass to the <code>getRootAsMyRootType</code> function:</p>
+<div class="fragment"><div class="line">ByteBuffer bb = ByteBuffer.wrap(data);</div>
+<div class="line">Monster monster = Monster.getRootAsMonster(bb);</div>
+</div><!-- fragment --><p>Now you can access values much like C++:</p>
+<div class="fragment"><div class="line"><span class="keywordtype">short</span> hp = monster.hp();</div>
+<div class="line">Vec3 pos = monster.pos();</div>
+</div><!-- fragment --><p>Note that whenever you access a new object like in the <code>pos</code> example above, a new temporary accessor object gets created. If your code is very performance sensitive (you iterate through a lot of objects), there's a second <code>pos()</code> method to which you can pass a <code>Vec3</code> object you've already created. This allows you to reuse it across many calls and reduce the amount of object allocation (and thus garbage collection) your program does.</p>
<p>Java does not support unsigned scalars. This means that any unsigned types you use in your schema will actually be represented as a signed value. This means all bits are still present, but may represent a negative value when used. For example, to read a <code>byte b</code> as an unsigned number, you can do: <code>(short)(b & 0xFF)</code></p>
<p>The default string accessor (e.g. <code>monster.name()</code>) currently always create a new Java <code>String</code> when accessed, since FlatBuffer's UTF-8 strings can't be used in-place by <code>String</code>. Alternatively, use <code>monster.nameAsByteBuffer()</code> which returns a <code>ByteBuffer</code> referring to the UTF-8 data in the original <code>ByteBuffer</code>, which is much more efficient. The <code>ByteBuffer</code>'s <code>position</code> points to the first character, and its <code>limit</code> to just after the last.</p>
-<p>Vector access is also a bit different from C++: you pass an extra index to the vector field accessor. Then a second method with the same name suffixed by <code>Length</code> let's you know the number of elements you can access: </p><pre class="fragment">for (int i = 0; i < monster.inventoryLength(); i++)
- monster.inventory(i); // do something here
-</pre><p>Alternatively, much like strings, you can use <code>monster.inventoryAsByteBuffer()</code> to get a <code>ByteBuffer</code> referring to the whole vector. Use <code>ByteBuffer</code> methods like <code>asFloatBuffer</code> to get specific views if needed.</p>
-<p>If you specified a file_indentifier in the schema, you can query if the buffer is of the desired type before accessing it using: </p><pre class="fragment">if (Monster.MonsterBufferHasIdentifier(bb)) ...
-</pre><h2>Buffer construction in Java</h2>
-<p>You can also construct these buffers in Java using the static methods found in the generated code, and the FlatBufferBuilder class: </p><pre class="fragment">FlatBufferBuilder fbb = new FlatBufferBuilder();
-</pre><p>Create strings: </p><pre class="fragment">int str = fbb.createString("MyMonster");
-</pre><p>Create a table with a struct contained therein: </p><pre class="fragment">Monster.startMonster(fbb);
-Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, (byte)4, (short)5, (byte)6));
-Monster.addHp(fbb, (short)80);
-Monster.addName(fbb, str);
-Monster.addInventory(fbb, inv);
-Monster.addTest_type(fbb, (byte)1);
-Monster.addTest(fbb, mon2);
-Monster.addTest4(fbb, test4s);
-int mon = Monster.endMonster(fbb);
-</pre><p>For some simpler types, you can use a convenient <code>create</code> function call that allows you to construct tables in one function call. This example definition however contains an inline struct field, so we have to create the table manually. This is to create the buffer without using temporary object allocation.</p>
+<p>Vector access is also a bit different from C++: you pass an extra index to the vector field accessor. Then a second method with the same name suffixed by <code>Length</code> let's you know the number of elements you can access:</p>
+<div class="fragment"><div class="line"><span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i < monster.inventoryLength(); i++)</div>
+<div class="line"> monster.inventory(i); <span class="comment">// do something here</span></div>
+</div><!-- fragment --><p>Alternatively, much like strings, you can use <code>monster.inventoryAsByteBuffer()</code> to get a <code>ByteBuffer</code> referring to the whole vector. Use <code>ByteBuffer</code> methods like <code>asFloatBuffer</code> to get specific views if needed.</p>
+<p>If you specified a file_indentifier in the schema, you can query if the buffer is of the desired type before accessing it using:</p>
+<div class="fragment"><div class="line"><span class="keywordflow">if</span> (Monster.MonsterBufferHasIdentifier(bb)) ...</div>
+</div><!-- fragment --><h2>Buffer construction in Java</h2>
+<p>You can also construct these buffers in Java using the static methods found in the generated code, and the FlatBufferBuilder class:</p>
+<div class="fragment"><div class="line">FlatBufferBuilder fbb = <span class="keyword">new</span> FlatBufferBuilder();</div>
+</div><!-- fragment --><p>Create strings:</p>
+<div class="fragment"><div class="line"><span class="keywordtype">int</span> str = fbb.createString(<span class="stringliteral">"MyMonster"</span>);</div>
+</div><!-- fragment --><p>Create a table with a struct contained therein:</p>
+<div class="fragment"><div class="line">Monster.startMonster(fbb);</div>
+<div class="line">Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, (byte)4, (<span class="keywordtype">short</span>)5, (byte)6));</div>
+<div class="line">Monster.addHp(fbb, (short)80);</div>
+<div class="line">Monster.addName(fbb, str);</div>
+<div class="line">Monster.addInventory(fbb, inv);</div>
+<div class="line">Monster.addTest_type(fbb, (byte)1);</div>
+<div class="line">Monster.addTest(fbb, mon2);</div>
+<div class="line">Monster.addTest4(fbb, test4s);</div>
+<div class="line"><span class="keywordtype">int</span> mon = Monster.endMonster(fbb);</div>
+</div><!-- fragment --><p>For some simpler types, you can use a convenient <code>create</code> function call that allows you to construct tables in one function call. This example definition however contains an inline struct field, so we have to create the table manually. This is to create the buffer without using temporary object allocation.</p>
<p>It's important to understand that fields that are structs are inline (like <code>Vec3</code> above), and MUST thus be created between the start and end calls of a table. Everything else (other tables, strings, vectors) MUST be created before the start of the table they are referenced in.</p>
<p>Structs do have convenient methods that even have arguments for nested structs.</p>
<p>As you can see, references to other objects (e.g. the string above) are simple ints, and thus do not have the type-safety of the Offset type in C++. Extra case must thus be taken that you set the right offset on the right field.</p>
-<p>Vectors can be created from the corresponding Java array like so: </p><pre class="fragment">int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
-</pre><p>This works for arrays of scalars and (int) offsets to strings/tables, but not structs. If you want to write structs, or what you want to write does not sit in an array, you can also use the start/end pattern: </p><pre class="fragment">Monster.startInventoryVector(fbb, 5);
-for (byte i = 4; i >=0; i--) fbb.addByte(i);
-int inv = fbb.endVector();
-</pre><p>You can use the generated method <code>startInventoryVector</code> to conveniently call <code>startVector</code> with the right element size. You pass the number of elements you want to write. Note how you write the elements backwards since the buffer is being constructed back to front.</p>
+<p>Vectors can be created from the corresponding Java array like so:</p>
+<div class="fragment"><div class="line"><span class="keywordtype">int</span> inv = Monster.createInventoryVector(fbb, <span class="keyword">new</span> byte[] { 0, 1, 2, 3, 4 });</div>
+</div><!-- fragment --><p>This works for arrays of scalars and (int) offsets to strings/tables, but not structs. If you want to write structs, or what you want to write does not sit in an array, you can also use the start/end pattern:</p>
+<div class="fragment"><div class="line">Monster.startInventoryVector(fbb, 5);</div>
+<div class="line"><span class="keywordflow">for</span> (byte i = 4; i >=0; i--) fbb.addByte(i);</div>
+<div class="line"><span class="keywordtype">int</span> inv = fbb.endVector();</div>
+</div><!-- fragment --><p>You can use the generated method <code>startInventoryVector</code> to conveniently call <code>startVector</code> with the right element size. You pass the number of elements you want to write. Note how you write the elements backwards since the buffer is being constructed back to front.</p>
<p>There are <code>add</code> functions for all the scalar types. You use <code>addOffset</code> for any previously constructed objects (such as other tables, strings, vectors). For structs, you use the appropriate <code>create</code> function in-line, as shown above in the <code>Monster</code> example.</p>
-<p>To finish the buffer, call: </p><pre class="fragment">Monster.finishMonsterBuffer(fbb, mon);
-</pre><p>The buffer is now ready to be transmitted. It is contained in the <code>ByteBuffer</code> which you can obtain from <code>fbb.dataBuffer()</code>. Importantly, the valid data does not start from offset 0 in this buffer, but from <code>fbb.dataBuffer().position()</code> (this is because the data was built backwards in memory). It ends at <code>fbb.capacity()</code>.</p>
+<p>To finish the buffer, call:</p>
+<div class="fragment"><div class="line">Monster.finishMonsterBuffer(fbb, mon);</div>
+</div><!-- fragment --><p>The buffer is now ready to be transmitted. It is contained in the <code>ByteBuffer</code> which you can obtain from <code>fbb.dataBuffer()</code>. Importantly, the valid data does not start from offset 0 in this buffer, but from <code>fbb.dataBuffer().position()</code> (this is because the data was built backwards in memory). It ends at <code>fbb.capacity()</code>.</p>
<h2>Text Parsing</h2>
<p>There currently is no support for parsing text (Schema's and JSON) directly from Java, though you could use the C++ parser through JNI. Please see the C++ documentation for more on text parsing. </p>
</div></div><!-- contents -->
To start creating a buffer, create an instance of `FlatBufferBuilder`
which will contain the buffer as it grows:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
FlatBufferBuilder fbb;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before we serialize a Monster, we need to first serialize any objects
that are contained there-in, i.e. we serialize the data tree using
depth first, pre-order traversal. This is generally easy to do on
any tree structures. For example:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto name = fbb.CreateString("MyMonster");
unsigned char inv[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
auto inventory = fbb.CreateVector(inv, 10);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`CreateString` and `CreateVector` serialize these two built-in
datatypes, and return offsets into the serialized data indicating where
be stored as contiguous memory in the buffer, use `CreateVectorOfStructs`
instead.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
Vec3 vec(1, 2, 3);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Vec3` is the first example of code from our generated
header. Structs (unlike tables) translate to simple structs in C++, so
We have now serialized the non-scalar components of of the monster
example, so we could create the monster something like this:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto mloc = CreateMonster(fbb, &vec, 150, 80, name, inventory, Color_Red, 0, Any_NONE);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that we're passing `150` for the `mana` field, which happens to be the
default value: this means the field will not actually be written to the buffer,
not default), instead of the convenient `CreateMonster` call we can also
build the object field-by-field manually:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
MonsterBuilder mb(fbb);
mb.add_pos(&vec);
mb.add_hp(80);
mb.add_name(name);
mb.add_inventory(inventory);
auto mloc = mb.Finish();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We start with a temporary helper class `MonsterBuilder` (which is
defined in our generated code also), then call the various `add_`
now have an offset to the root of your data, and you can finish the
buffer using:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
FinishMonsterBuffer(fbb, mloc);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The buffer is now ready to be stored somewhere, sent over the network,
be compressed, or whatever you'd like to do with it. You can access the
If you've received a buffer from somewhere (disk, network, etc.) you can
directly start traversing it using:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto monster = GetMonster(buffer_pointer);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`monster` is of type `Monster *`, and points to somewhere inside your
buffer. If you look in your generated header, you'll see it has
convenient accessors for all fields, e.g.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
assert(monster->hp() == 80);
assert(monster->mana() == 150); // default
assert(strcmp(monster->name()->c_str(), "MyMonster") == 0);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These should all be true. Note that we never stored a `mana` value, so
it will return the default.
To access sub-objects, in this case the `Vec3`:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto pos = monster->pos();
assert(pos);
assert(pos->z() == 3);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If we had not set the `pos` field during serialization, it would be
`NULL`.
Similarly, we can access elements of the inventory array:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto inv = monster->inventory();
assert(inv);
assert(inv->Get(9) == 9);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Direct memory access
Each root type will have a verification function generated for it,
e.g. for `Monster`, you can call:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
bool ok = VerifyMonsterBuffer(Verifier(buf, len));
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if `ok` is true, the buffer is safe to read.
convenient `LoadFile()` utility function in `flatbuffers/util.h` if you
wish). Construct a parser:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
flatbuffers::Parser parser;
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can parse any number of text files in sequence:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
parser.Parse(text_file.c_str());
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This works similarly to how the command-line compiler works: a sequence
of files parsed by the same `Parser` object allow later files to
FlatBuffer binary file into a `[]byte`, which you pass to the
`GetRootAsMonster` function:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
import (
example "MyGame/Example"
flatbuffers "github.com/google/flatbuffers/go"
buf, err := ioutil.ReadFile("monster.dat")
// handle err
monster := example.GetRootAsMonster(buf, 0)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
hp := monster.Hp()
pos := monster.Pos(nil)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that whenever you access a new object like in the `Pos` example above,
a new temporary accessor object gets created. If your code is very performance
vector field accessor. Then a second method with the same name suffixed
by `Length` let's you know the number of elements you can access:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
for i := 0; i < monster.InventoryLength(); i++ {
monster.Inventory(i) // do something here
}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can also construct these buffers in Go using the functions found in the
generated code, and the FlatBufferBuilder class:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
builder := flatbuffers.NewBuilder(0)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create strings:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
str := builder.CreateString("MyMonster")
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a table with a struct contained therein:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
example.MonsterStart(builder)
example.MonsterAddPos(builder, example.CreateVec3(builder, 1.0, 2.0, 3.0, 3.0, 4, 5, 6))
example.MonsterAddHp(builder, 80)
example.MonsterAddTest(builder, mon2)
example.MonsterAddTest4(builder, test4s)
mon := example.MonsterEnd(builder)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlike C++, Go does not support table creation functions like 'createMonster()'.
This is to create the buffer without
Vectors also use this start/end pattern to allow vectors of both scalar types
and structs:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go}
example.MonsterStartInventoryVector(builder, 5)
for i := 4; i >= 0; i-- {
builder.PrependByte(byte(i))
}
inv := builder.EndVector(5)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The generated method 'StartInventoryVector' is provided as a convenience
function which calls 'StartVector' with the correct element size of the vector
file into a `byte[]`, which you then turn into a `ByteBuffer`, which you pass to
the `getRootAsMyRootType` function:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
ByteBuffer bb = ByteBuffer.wrap(data);
Monster monster = Monster.getRootAsMonster(bb);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values much like C++:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
short hp = monster.hp();
Vec3 pos = monster.pos();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Note that whenever you access a new object like in the `pos` example above,
a new temporary accessor object gets created. If your code is very performance
to the vector field accessor. Then a second method with the same name
suffixed by `Length` let's you know the number of elements you can access:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
for (int i = 0; i < monster.inventoryLength(); i++)
monster.inventory(i); // do something here
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, much like strings, you can use `monster.inventoryAsByteBuffer()`
to get a `ByteBuffer` referring to the whole vector. Use `ByteBuffer` methods
If you specified a file_indentifier in the schema, you can query if the
buffer is of the desired type before accessing it using:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
if (Monster.MonsterBufferHasIdentifier(bb)) ...
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Buffer construction in Java
You can also construct these buffers in Java using the static methods found
in the generated code, and the FlatBufferBuilder class:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
FlatBufferBuilder fbb = new FlatBufferBuilder();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create strings:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
int str = fbb.createString("MyMonster");
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a table with a struct contained therein:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
Monster.startMonster(fbb);
Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0, (byte)4, (short)5, (byte)6));
Monster.addHp(fbb, (short)80);
Monster.addTest(fbb, mon2);
Monster.addTest4(fbb, test4s);
int mon = Monster.endMonster(fbb);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For some simpler types, you can use a convenient `create` function call that
allows you to construct tables in one function call. This example definition
Vectors can be created from the corresponding Java array like so:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This works for arrays of scalars and (int) offsets to strings/tables,
but not structs. If you want to write structs, or what you want to write
does not sit in an array, you can also use the start/end pattern:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
Monster.startInventoryVector(fbb, 5);
for (byte i = 4; i >=0; i--) fbb.addByte(i);
int inv = fbb.endVector();
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can use the generated method `startInventoryVector` to conveniently call
`startVector` with the right element size. You pass the number of
To finish the buffer, call:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
Monster.finishMonsterBuffer(fbb, mon);
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The buffer is now ready to be transmitted. It is contained in the `ByteBuffer`
which you can obtain from `fbb.dataBuffer()`. Importantly, the valid data does