Commit 4898809e authored by aardappel's avatar aardappel

FlatBuffers implementation for the Lobster programming language

Language, see: http://strlen.com/lobster/ and https://github.com/aardappel/lobster
parent ca5aaf62
...@@ -55,6 +55,7 @@ tests/monsterdata_java_wire.mon ...@@ -55,6 +55,7 @@ tests/monsterdata_java_wire.mon
tests/monsterdata_java_wire_sp.mon tests/monsterdata_java_wire_sp.mon
tests/monsterdata_go_wire.mon tests/monsterdata_go_wire.mon
tests/monsterdata_javascript_wire.mon tests/monsterdata_javascript_wire.mon
tests/monsterdata_lobster_wire.mon
tests/unicode_test.mon tests/unicode_test.mon
tests/ts/ tests/ts/
tests/php/ tests/php/
......
...@@ -94,6 +94,7 @@ cc_binary( ...@@ -94,6 +94,7 @@ cc_binary(
"src/idl_gen_js.cpp", "src/idl_gen_js.cpp",
"src/idl_gen_json_schema.cpp", "src/idl_gen_json_schema.cpp",
"src/idl_gen_lua.cpp", "src/idl_gen_lua.cpp",
"src/idl_gen_lobster.cpp",
"src/idl_gen_php.cpp", "src/idl_gen_php.cpp",
"src/idl_gen_python.cpp", "src/idl_gen_python.cpp",
"src/idl_gen_text.cpp", "src/idl_gen_text.cpp",
......
...@@ -52,6 +52,7 @@ set(FlatBuffers_Compiler_SRCS ...@@ -52,6 +52,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_js.cpp src/idl_gen_js.cpp
src/idl_gen_php.cpp src/idl_gen_php.cpp
src/idl_gen_python.cpp src/idl_gen_python.cpp
src/idl_gen_lobster.cpp
src/idl_gen_lua.cpp src/idl_gen_lua.cpp
src/idl_gen_fbs.cpp src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp src/idl_gen_grpc.cpp
......
...@@ -31,12 +31,18 @@ For any schema input files, one or more generators can be specified: ...@@ -31,12 +31,18 @@ For any schema input files, one or more generators can be specified:
- `--js`, `-s`: Generate JavaScript code. - `--js`, `-s`: Generate JavaScript code.
- `--ts`: Generate TypeScript code.
- `--php`: Generate PHP code. - `--php`: Generate PHP code.
- `--grpc`: Generate RPC stub code for GRPC. - `--grpc`: Generate RPC stub code for GRPC.
- `--dart`: Generate Dart code. - `--dart`: Generate Dart code.
- `--lua`: Generate Lua code.
- `--lobster`: Generate Lobster code.
For any data input files: For any data input files:
- `--binary`, `-b` : If data is contained in this file, generate a - `--binary`, `-b` : If data is contained in this file, generate a
......
...@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index} ...@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
# Overview {#flatbuffers_overview} # Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform [FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
serialization library for C++, C#, C, Go, Java, JavaScript, Lua, TypeScript, PHP, and Python. serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, and Python.
It was originally created at Google for game development and other It was originally created at Google for game development and other
performance-critical applications. performance-critical applications.
...@@ -142,6 +142,8 @@ sections provide a more in-depth usage guide. ...@@ -142,6 +142,8 @@ sections provide a more in-depth usage guide.
own programs. own programs.
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your - How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
own programs. own programs.
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
own programs.
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features. - [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of - Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
using FlatBuffers. using FlatBuffers.
......
Use in Lobster {#flatbuffers_guide_use_lobster}
==============
## Before you get started
Before diving into the FlatBuffers usage in Lobster, it should be noted that the
[Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to general
FlatBuffers usage in all of the supported languages (including Lobster). This
page is designed to cover the nuances of FlatBuffers usage, specific to
Lobster.
You should also have read the [Building](@ref flatbuffers_guide_building)
documentation to build `flatc` and should be familiar with
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
[Writing a schema](@ref flatbuffers_guide_writing_schema).
## FlatBuffers Lobster library code location
The code for the FlatBuffers Lobster library can be found at
`flatbuffers/lobster`. You can browse the library code on the
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
lobster).
## Testing the FlatBuffers Lobster library
The code to test the Lobster library can be found at `flatbuffers/tests`.
The test code itself is located in [lobstertest.lobster](https://github.com/google/
flatbuffers/blob/master/tests/lobstertest.lobster).
To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself,
go to the [Lobster homepage](http://strlen.com/lobster) or
[github](https://github.com/aardappel/lobster) to learn how to build it for your
platform.
## Using the FlatBuffers Lobster library
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in Lobster.*
There is support for both reading and writing FlatBuffers in Lobster.
To use FlatBuffers in your own code, first generate Lobster classes from your
schema with the `--lobster` option to `flatc`. Then you can include both
FlatBuffers and the generated code to read or write a FlatBuffer.
For example, here is how you would read a FlatBuffer binary file in Lobster:
First, import the library and the generated code. Then read a FlatBuffer binary
file into a string, which you pass to the `GetRootAsMonster` function:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
include "monster_generated.lobster"
let fb = read_file("monsterdata_test.mon")
assert fb
let monster = MyGame_Example_GetRootAsMonster(fb)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now you can access values like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
let hp = monster.hp
let pos = monster.pos
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As you can see, even though `hp` and `pos` are functions that access FlatBuffer
data in-place in the string buffer, they appear as field accesses.
## Speed
Using FlatBuffers in Lobster should be relatively fast, as the implementation
makes use of native support for writing binary values, and access of vtables.
Both generated code and the runtime library are therefore small and fast.
Actual speed will depend on wether you use Lobster as bytecode VM or compiled to
C++.
## Text Parsing
Lobster has full support for parsing JSON into FlatBuffers, or generating
JSON from FlatBuffers. See `samples/sample_test.lobster` for an example.
This uses the C++ parser and generator underneath, so should be both fast and
conformant.
<br>
...@@ -18,25 +18,25 @@ In general: ...@@ -18,25 +18,25 @@ In general:
NOTE: this table is a start, it needs to be extended. NOTE: this table is a start, it needs to be extended.
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby | Dart Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ---- | ---- ------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | -------
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP | Yes Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | No JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ? | Yes Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ? | No Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | ? Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ? | Yes Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ? | Yes Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ? | Yes Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ? | Flutter Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | ? Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw | dnfield Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard*
* aard = aardappel (previously: gwvo)
* ev = evolutional * ev = evolutional
* js = jonsimantov * js = jonsimantov
* mik = mikkelfj * mik = mikkelfj
......
...@@ -32,6 +32,7 @@ Please select your desired language for our quest: ...@@ -32,6 +32,7 @@ Please select your desired language for our quest:
<input type="radio" name="language" value="c">C</input> <input type="radio" name="language" value="c">C</input>
<input type="radio" name="language" value="dart">Dart</input> <input type="radio" name="language" value="dart">Dart</input>
<input type="radio" name="language" value="lua">Lua</input> <input type="radio" name="language" value="lua">Lua</input>
<input type="radio" name="language" value="lobster">Lobster</input>
</form> </form>
\endhtmlonly \endhtmlonly
...@@ -138,7 +139,10 @@ For your chosen language, please cross-reference with: ...@@ -138,7 +139,10 @@ For your chosen language, please cross-reference with:
[example.dart](https://github.com/google/flatbuffers/blob/master/dart/example/example.dart) [example.dart](https://github.com/google/flatbuffers/blob/master/dart/example/example.dart)
</div> </div>
<div class="language-lua"> <div class="language-lua">
[sample_binary.lua](https://github.com/google/flatbuffers/blob/master/dart/example/sample_binary.lua) [sample_binary.lua](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.lua)
</div>
<div class="language-lobster">
[sample_binary.lobster](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.lobster)
</div> </div>
...@@ -333,6 +337,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools. ...@@ -333,6 +337,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
./../flatc --lua monster.fbs ./../flatc --lua monster.fbs
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.sh}
cd flatbuffers/sample
./../flatc --lobster monster.fbs
~~~
</div>
For a more complete guide to using the `flatc` compiler, please read the For a more complete guide to using the `flatc` compiler, please read the
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) [Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
...@@ -463,6 +473,12 @@ The first step is to import/include the library, generated files, etc. ...@@ -463,6 +473,12 @@ The first step is to import/include the library, generated files, etc.
local weapon = require("MyGame.Sample.Weapon") local weapon = require("MyGame.Sample.Weapon")
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
include from "../lobster/" // Where to find flatbuffers.lobster
include "monster_generated.lobster"
~~~
</div>
Now we are ready to start building some buffers. In order to start, we need Now we are ready to start building some buffers. In order to start, we need
to create an instance of the `FlatBufferBuilder`, which will contain the buffer to create an instance of the `FlatBufferBuilder`, which will contain the buffer
...@@ -548,6 +564,12 @@ which will grow automatically if needed: ...@@ -548,6 +564,12 @@ which will grow automatically if needed:
local builder = flatbuffers.Builder(1024) local builder = flatbuffers.Builder(1024)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
-- get access to the builder
let builder = flatbuffers_builder {}
~~~
</div>
After creating the `builder`, we can start serializing our data. Before we make After creating the `builder`, we can start serializing our data. Before we make
our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`. our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
...@@ -753,6 +775,19 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`. ...@@ -753,6 +775,19 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
local axe = weapon.End(builder) local axe = weapon.End(builder)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let weapon_names = [ "Sword", "Axe" ]
let weapon_damages = [ 3, 5 ]
weapon_offsets := map(weapon_names) name, i:
let ns = builder.CreateString(name)
builder.MyGame_Sample_WeaponStart()
builder.MyGame_Sample_WeaponAddName(ns)
builder.MyGame_Sample_WeaponAddDamage(weapon_damages[i])
builder.MyGame_Sample_WeaponEnd()
~~~
</div>
Now let's create our monster, the `orc`. For this `orc`, lets make him Now let's create our monster, the `orc`. For this `orc`, lets make him
`red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him `red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
...@@ -915,6 +950,15 @@ traversal. This is generally easy to do on any tree structures. ...@@ -915,6 +950,15 @@ traversal. This is generally easy to do on any tree structures.
local inv = builder:EndVector(10) local inv = builder:EndVector(10)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
// Name of the monster.
let name = builder.CreateString("Orc")
// Inventory.
let inv = builder.MyGame_Sample_MonsterCreateInventoryVector(map(10): _)
~~~
</div>
We serialized two built-in data types (`string` and `vector`) and captured We serialized two built-in data types (`string` and `vector`) and captured
their return values. These values are offsets into the serialized data, their return values. These values are offsets into the serialized data,
...@@ -1037,6 +1081,11 @@ offsets. ...@@ -1037,6 +1081,11 @@ offsets.
local weapons = builder:EndVector(2) local weapons = builder:EndVector(2)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let weapons = builder.MyGame_Sample_MonsterCreateWeaponsVector(weapon_offsets)
~~~
</div>
<div class="language-cpp"> <div class="language-cpp">
<br> <br>
...@@ -1146,6 +1195,14 @@ for the `path` field above: ...@@ -1146,6 +1195,14 @@ for the `path` field above:
local path = builder:EndVector(2) local path = builder:EndVector(2)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
builder.MyGame_Sample_MonsterStartPathVector(2)
builder.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0)
builder.MyGame_Sample_CreateVec3(4.0, 5.0, 6.0)
let path = builder.EndVector(2)
~~~
</div>
We have now serialized the non-scalar components of the orc, so we We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself: can serialize the monster itself:
...@@ -1366,6 +1423,21 @@ can serialize the monster itself: ...@@ -1366,6 +1423,21 @@ can serialize the monster itself:
local orc = monster.End(builder) local orc = monster.End(builder)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
builder.MyGame_Sample_MonsterStart()
builder.MyGame_Sample_MonsterAddPos(builder.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0))
builder.MyGame_Sample_MonsterAddHp(300)
builder.MyGame_Sample_MonsterAddName(name)
builder.MyGame_Sample_MonsterAddInventory(inv)
builder.MyGame_Sample_MonsterAddColor(MyGame_Sample_Color_Red)
builder.MyGame_Sample_MonsterAddWeapons(weapons)
builder.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon)
builder.MyGame_Sample_MonsterAddEquipped(weapon_offsets[1])
builder.MyGame_Sample_MonsterAddPath(path)
let orc = builder.MyGame_Sample_MonsterEnd()
~~~
</div>
Note how we create `Vec3` struct in-line in the table. Unlike tables, structs Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like are simple combinations of scalars that are always stored inline, just like
...@@ -1514,6 +1586,12 @@ Here is a repetition these lines, to help highlight them more clearly: ...@@ -1514,6 +1586,12 @@ Here is a repetition these lines, to help highlight them more clearly:
monster.AddEquipped(builder, axe) -- Union data monster.AddEquipped(builder, axe) -- Union data
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
builder.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon)
builder.MyGame_Sample_MonsterAddEquipped(axe)
~~~
</div>
After you have created your buffer, you will have the offset to the root of the After you have created your buffer, you will have the offset to the root of the
data in the `orc` variable, so you can finish the buffer by calling the data in the `orc` variable, so you can finish the buffer by calling the
...@@ -1591,7 +1669,12 @@ appropriate `finish` method. ...@@ -1591,7 +1669,12 @@ appropriate `finish` method.
builder:Finish(orc) builder:Finish(orc)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
// Call `Finish()` to instruct the builder that this monster is complete.
builder.Finish(orc)
~~~
</div>
The buffer is now ready to be stored somewhere, sent over the network, be 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 buffer compressed, or whatever you'd like to do with it. You can access the buffer
...@@ -1695,6 +1778,12 @@ like so: ...@@ -1695,6 +1778,12 @@ like so:
local bufAsString = builder:Output() local bufAsString = builder:Output()
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
// This must be called after `Finish()`.
let buf = builder.SizedCopy() // Of type `string`.
~~~
</div>
Now you can write the bytes to a file, send them over the network.. Now you can write the bytes to a file, send them over the network..
...@@ -1706,7 +1795,7 @@ which will lead to hard to find problems when you read the buffer. ...@@ -1706,7 +1795,7 @@ which will lead to hard to find problems when you read the buffer.
Now that we have successfully created an `Orc` FlatBuffer, the monster data can Now that we have successfully created an `Orc` FlatBuffer, the monster data can
be saved, sent over a network, etc. Let's now adventure into the inverse, and be saved, sent over a network, etc. Let's now adventure into the inverse, and
deserialize a FlatBuffer. access a FlatBuffer.
This section requires the same import/include, namespace, etc. requirements as This section requires the same import/include, namespace, etc. requirements as
before: before:
...@@ -1822,6 +1911,12 @@ import './monster_my_game.sample_generated.dart' as myGame; ...@@ -1822,6 +1911,12 @@ import './monster_my_game.sample_generated.dart' as myGame;
local weapon = require("MyGame.Sample.Weapon") local weapon = require("MyGame.Sample.Weapon")
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
include from "../lobster/" // Where to find flatbuffers.lobster
include "monster_generated.lobster"
~~~
</div>
Then, assuming you have a buffer of bytes received from disk, Then, assuming you have a buffer of bytes received from disk,
network, etc., you can create start accessing the buffer like so: network, etc., you can create start accessing the buffer like so:
...@@ -1941,6 +2036,14 @@ myGame.Monster monster = new myGame.Monster(data); ...@@ -1941,6 +2036,14 @@ myGame.Monster monster = new myGame.Monster(data);
local mon = monster.GetRootAsMonster(buf, 0) local mon = monster.GetRootAsMonster(buf, 0)
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
buf = /* the data you just read, in a string */
// Get an accessor to the root object inside the buffer.
let monster = MyGame_Sample_GetRootAsMonster(buf)
~~~
</div>
If you look in the generated files from the schema compiler, you will see it generated If you look in the generated files from the schema compiler, you will see it generated
accessors for all non-`deprecated` fields. For example: accessors for all non-`deprecated` fields. For example:
...@@ -2026,6 +2129,13 @@ accessors for all non-`deprecated` fields. For example: ...@@ -2026,6 +2129,13 @@ accessors for all non-`deprecated` fields. For example:
local name = mon:Name() local name = mon:Name()
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let hp = monster.hp
let mana = monster.mana
let name = monster.name
~~~
</div>
These should hold `300`, `150`, and `"Orc"` respectively. These should hold `300`, `150`, and `"Orc"` respectively.
...@@ -2127,7 +2237,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`: ...@@ -2127,7 +2237,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
local z = pos:Z() local z = pos:Z()
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let pos = monster.pos
let x = pos.x
let y = pos.y
let z = pos.z
~~~
</div>
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively. `x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
...@@ -2206,6 +2323,12 @@ FlatBuffers `vector`. ...@@ -2206,6 +2323,12 @@ FlatBuffers `vector`.
local thirdItem = mon:Inventory(3) -- Lua is 1-based local thirdItem = mon:Inventory(3) -- Lua is 1-based
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let inv_len = monster.inventory_length
let third_item = monster.inventory(2)
~~~
</div>
For `vector`s of `table`s, you can access the elements like any other vector, For `vector`s of `table`s, you can access the elements like any other vector,
except your need to handle the result as a FlatBuffer `table`: except your need to handle the result as a FlatBuffer `table`:
...@@ -2294,6 +2417,13 @@ except your need to handle the result as a FlatBuffer `table`: ...@@ -2294,6 +2417,13 @@ except your need to handle the result as a FlatBuffer `table`:
local secondWeaponDamage = mon:Weapon(2):Damage() local secondWeaponDamage = mon:Weapon(2):Damage()
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
let weapons_length = monster.weapons_length
let second_weapon_name = monster.weapons(1).name
let second_weapon_damage = monster.weapons(1).damage
~~~
</div>
Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
the `union`, we need to get both parts of the `union`: the type and the data. the `union`, we need to get both parts of the `union`: the type and the data.
...@@ -2442,6 +2572,19 @@ We can access the type to dynamically cast the data as needed (since the ...@@ -2442,6 +2572,19 @@ We can access the type to dynamically cast the data as needed (since the
end end
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
union_type = monster.equipped_type
if union_type == MyGame_Sample_Equipment_Weapon:
// `monster.equipped_as_Weapon` returns a FlatBuffer handle much like normal table fields,
// but this is only valid to call if we already know it is the correct type.
let union_weapon = monster.equipped_as_Weapon
let weapon_name = union_weapon.name // "Axe"
let weapon_damage = union_weapon.damage // 5
~~~
</div>
## Mutating FlatBuffers ## Mutating FlatBuffers
...@@ -2527,6 +2670,11 @@ mutators like so: ...@@ -2527,6 +2670,11 @@ mutators like so:
<API for mutating FlatBuffers is not yet available in Lua.> <API for mutating FlatBuffers is not yet available in Lua.>
~~~ ~~~
</div> </div>
<div class="language-lobster">
~~~{.lobster}
<API for mutating FlatBuffers is not yet available in Lobster.>
~~~
</div>
We use the somewhat verbose term `mutate` instead of `set` to indicate that this We use the somewhat verbose term `mutate` instead of `set` to indicate that this
is a special use case, not to be confused with the default way of constructing is a special use case, not to be confused with the default way of constructing
...@@ -2601,6 +2749,11 @@ printers that you can compile and use at runtime. The `flatc` compiler (not ...@@ -2601,6 +2749,11 @@ printers that you can compile and use at runtime. The `flatc` compiler (not
flatbuffer conversion from a given schema. There are no current plans flatbuffer conversion from a given schema. There are no current plans
for `flatcc` to support this.* for `flatcc` to support this.*
</div> </div>
<div class="language-lobster">
*Note: If you're working in Lobster, you can also parse JSON at runtime. See the
[Use in Lobster](@ref flatbuffers_guide_use_lobster) section of the Programmer's
Guide for more information.*
</div>
## Advanced Features for Each Language ## Advanced Features for Each Language
...@@ -2642,6 +2795,8 @@ For your chosen language, see: ...@@ -2642,6 +2795,8 @@ For your chosen language, see:
<div class="language-lua"> <div class="language-lua">
[Use in Lua](@ref flatbuffers_guide_use_lua) [Use in Lua](@ref flatbuffers_guide_use_lua)
</div> </div>
<div class="language-lobster">
[Use in Lobster](@ref flatbuffers_guide_use_lobster)
</div>
<br> <br>
...@@ -759,6 +759,7 @@ INPUT = "FlatBuffers.md" \ ...@@ -759,6 +759,7 @@ INPUT = "FlatBuffers.md" \
"PHPUsage.md" \ "PHPUsage.md" \
"PythonUsage.md" \ "PythonUsage.md" \
"LuaUsage.md" \ "LuaUsage.md" \
"LobsterUsage.md" \
"Support.md" \ "Support.md" \
"Benchmarks.md" \ "Benchmarks.md" \
"WhitePaper.md" \ "WhitePaper.md" \
......
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
title="Use in Dart"/> title="Use in Dart"/>
<tab type="user" url="@ref flatbuffers_guide_use_lua" <tab type="user" url="@ref flatbuffers_guide_use_lua"
title="Use in Lua"/> title="Use in Lua"/>
<tab type="user" url="@ref flatbuffers_guide_use_lobster"
title="Use in Lobster"/>
<tab type="user" url="@ref flexbuffers" <tab type="user" url="@ref flexbuffers"
title="Schema-less version"/> title="Schema-less version"/>
<tab type="usergroup" url="" title="gRPC"> <tab type="usergroup" url="" title="gRPC">
......
...@@ -409,6 +409,7 @@ struct IDLOptions { ...@@ -409,6 +409,7 @@ struct IDLOptions {
kJsonSchema = 1 << 10, kJsonSchema = 1 << 10,
kDart = 1 << 11, kDart = 1 << 11,
kLua = 1 << 12, kLua = 1 << 12,
kLobster = 1 << 13,
kMAX kMAX
}; };
...@@ -820,6 +821,12 @@ extern bool GeneratePython(const Parser &parser, ...@@ -820,6 +821,12 @@ extern bool GeneratePython(const Parser &parser,
const std::string &path, const std::string &path,
const std::string &file_name); const std::string &file_name);
// Generate Lobster files from the definitions in the Parser object.
// See idl_gen_lobster.cpp.
extern bool GenerateLobster(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate Lua files from the definitions in the Parser object. // Generate Lua files from the definitions in the Parser object.
// See idl_gen_lua.cpp. // See idl_gen_lua.cpp.
extern bool GenerateLua(const Parser &parser, extern bool GenerateLua(const Parser &parser,
......
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
include "std.lobster"
namespace flatbuffers
struct handle:
buf_:string
pos_:int
enum + sz_8 = 1,
sz_16 = 2,
sz_32 = 4,
sz_64 = 8,
sz_voffset = 2,
sz_uoffset = 4,
sz_soffset = 4,
sz_metadata_fields = 2
struct builder:
buf:string = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
current_vtable:[int] = []
head:int = 0
minalign:int = 1
object_end:int = 0
vtables:[int] = []
nested:int = false
finished:int = false
// Optionally call this right after creating the builder for a larger initial buffer.
def Initial(initial_size:int):
buf = "\x00".repeat_string(initial_size)
def Start():
// Get the start of useful data in the underlying byte buffer.
return buf.length - head
def Offset():
// Offset relative to the end of the buffer.
return head
// Returns a copy of the part of the buffer containing only the finished FlatBuffer
def SizedCopy():
assert finished
return buf.substring(Start(), -1)
def StartNesting():
assert not nested
nested = true
def EndNesting():
assert nested
nested = false
def StartObject(numfields):
StartNesting()
current_vtable = map(numfields): 0
object_end = head
minalign = 1
def EndObject():
EndNesting()
// Prepend a zero scalar to the object. Later in this function we'll
// write an offset here that points to the object's vtable:
PrependInt32(0)
object_offset := head
// Write out new vtable speculatively.
vtable_size := (current_vtable.length + sz_metadata_fields) * sz_voffset
while current_vtable.length:
o := current_vtable.pop()
PrependVOffsetT(if o: object_offset - o else: 0)
// The two metadata fields are written last.
// First, store the object bytesize:
PrependVOffsetT(object_offset - object_end)
// Second, store the vtable bytesize:
PrependVOffsetT(vtable_size)
// Search backwards through existing vtables, because similar vtables
// are likely to have been recently appended. See
// BenchmarkVtableDeduplication for a case in which this heuristic
// saves about 30% of the time used in writing objects with duplicate
// tables.
existing_vtable := do():
reverse(vtables) vt2_offset:
// Find the other vtable:
vt2_start := buf.length - vt2_offset
vt2_len := buf.read_int16_le(vt2_start)
// Compare the other vtable to the one under consideration.
// If they are equal, return the offset:
if vtable_size == vt2_len and
not compare_substring(buf, Start(), buf, vt2_start, vtable_size):
return vt2_offset from do
0
if existing_vtable:
// Found a duplicate vtable, remove the one we wrote.
head = object_offset
// Write the offset to the found vtable in the
// already-allocated offset at the beginning of this object:
buf.write_int32_le(Start(), existing_vtable - object_offset)
else:
// Did not find a vtable, so keep the one we wrote.
// Next, write the offset to the new vtable in the
// already-allocated offset at the beginning of this object:
buf.write_int32_le(buf.length - object_offset, head - object_offset)
// Finally, store this vtable in memory for future
// deduplication:
vtables.push(head)
return object_offset
def Pad(n):
for(n): buf, head = buf.write_int8_le_back(head, 0)
def Prep(size, additional_bytes):
// Track the biggest thing we've ever aligned to.
if size > minalign:
minalign = size
// Find the amount of alignment needed such that `size` is properly
// aligned after `additionalBytes`:
align_size := ((~(head + additional_bytes)) + 1) & (size - 1)
Pad(align_size)
def PrependUOffsetTRelative(off):
// Prepends an unsigned offset into vector data, relative to where it will be written.
Prep(sz_uoffset, 0)
assert off <= head
PlaceUOffsetT(head - off + sz_uoffset)
def StartVector(elem_size, num_elems, alignment):
// Initializes bookkeeping for writing a new vector.
StartNesting()
Prep(sz_32, elem_size * num_elems)
Prep(alignment, elem_size * num_elems) // In case alignment > int.
return head
def EndVector(vector_num_elems):
EndNesting()
// we already made space for this, so write without PrependUint32
PlaceUOffsetT(vector_num_elems)
return head
def CreateString(s:string):
// writes a null-terminated byte string.
StartNesting()
Prep(sz_32, s.length + 1)
buf, head = buf.write_substring_back(head, s, true)
return EndVector(s.length)
def CreateByteVector(s:string):
// writes a non-null-terminated byte string.
StartNesting()
Prep(sz_32, s.length)
buf, head = buf.write_substring_back(head, s, false)
return EndVector(s.length)
def Slot(slotnum):
assert nested
while current_vtable.length <= slotnum: current_vtable.push(0)
current_vtable[slotnum] = head
def __Finish(root_table:int, size_prefix:int):
// Finish finalizes a buffer, pointing to the given root_table
assert not finished
assert not nested
prep_size := sz_32
if size_prefix:
prep_size += sz_32
Prep(minalign, prep_size)
PrependUOffsetTRelative(root_table)
if size_prefix:
PrependInt32(head)
finished = true
return Start()
def Finish(root_table:int):
return __Finish(root_table, false)
def FinishSizePrefixed(root_table:int):
return __Finish(root_table, true)
def PrependBool(x):
buf, head = buf.write_int8_le_back(head, x)
def PrependByte(x):
buf, head = buf.write_int8_le_back(head, x)
def PrependUint8(x):
buf, head = buf.write_int8_le_back(head, x)
def PrependUint16(x):
Prep(sz_16, 0)
buf, head = buf.write_int16_le_back(head, x)
def PrependUint32(x):
Prep(sz_32, 0)
buf, head = buf.write_int32_le_back(head, x)
def PrependUint64(x):
Prep(sz_64, 0)
buf, head = buf.write_int64_le_back(head, x)
def PrependInt8(x):
buf, head = buf.write_int8_le_back(head, x)
def PrependInt16(x):
Prep(sz_16, 0)
buf, head = buf.write_int16_le_back(head, x)
def PrependInt32(x):
Prep(sz_32, 0)
buf, head = buf.write_int32_le_back(head, x)
def PrependInt64(x):
Prep(sz_64, 0)
buf, head = buf.write_int64_le_back(head, x)
def PrependFloat32(x):
Prep(sz_32, 0)
buf, head = buf.write_float32_le_back(head, x)
def PrependFloat64(x):
Prep(sz_64, 0)
buf, head = buf.write_float64_le_back(head, x)
def PrependVOffsetT(x):
Prep(sz_voffset, 0)
buf, head = buf.write_int16_le_back(head, x)
def PlaceVOffsetT(x):
buf, head = buf.write_int16_le_back(head, x)
def PlaceSOffsetT(x):
buf, head = buf.write_int32_le_back(head, x)
def PlaceUOffsetT(x):
buf, head = buf.write_int32_le_back(head, x)
def PrependSlot(o:int, x, d, f):
if x != d:
f(x)
Slot(o)
def PrependBoolSlot(o, x, d): PrependSlot(o, x, d): PrependBool(_)
def PrependByteSlot(o, x, d): PrependSlot(o, x, d): PrependByte(_)
def PrependUint8Slot(o, x, d): PrependSlot(o, x, d): PrependUint8(_)
def PrependUint16Slot(o, x, d): PrependSlot(o, x, d): PrependUint16(_)
def PrependUint32Slot(o, x, d): PrependSlot(o, x, d): PrependUint32(_)
def PrependUint64Slot(o, x, d): PrependSlot(o, x, d): PrependUint64(_)
def PrependInt8Slot(o, x, d): PrependSlot(o, x, d): PrependInt8(_)
def PrependInt16Slot(o, x, d): PrependSlot(o, x, d): PrependInt16(_)
def PrependInt32Slot(o, x, d): PrependSlot(o, x, d): PrependInt32(_)
def PrependInt64Slot(o, x, d): PrependSlot(o, x, d): PrependInt64(_)
def PrependFloat32Slot(o, x, d): PrependSlot(o, x, d): PrependFloat32(_)
def PrependFloat64Slot(o, x, d): PrependSlot(o, x, d): PrependFloat64(_)
def PrependUOffsetTRelativeSlot(o, x, d):
if x != d:
PrependUOffsetTRelative(x)
Slot(o)
def PrependStructSlot(v, x, d):
if x != d:
// Structs are always stored inline, so need to be created right
// where they are used. You'll get this error if you created it
//elsewhere.
assert x == head
Slot(v)
// automatically generated by the FlatBuffers compiler, do not modify
include "flatbuffers.lobster"
namespace MyGame_Sample
enum +
Color_Red = 0,
Color_Green = 1,
Color_Blue = 2
enum +
Equipment_NONE = 0,
Equipment_Weapon = 1
struct Vec3
struct Monster
struct Weapon
struct Vec3 : flatbuffers_handle
def x():
buf_.read_float32_le(pos_ + 0)
def y():
buf_.read_float32_le(pos_ + 4)
def z():
buf_.read_float32_le(pos_ + 8)
def CreateVec3(b_:flatbuffers_builder, x:float, y:float, z:float):
b_.Prep(4, 12)
b_.PrependFloat32(z)
b_.PrependFloat32(y)
b_.PrependFloat32(x)
return b_.Offset()
struct Monster : flatbuffers_handle
def pos():
o := buf_.flatbuffers_field_struct(pos_, 4)
if o: MyGame_Sample_Vec3 { buf_, o } else: nil
def mana():
buf_.flatbuffers_field_int16(pos_, 6, 150)
def hp():
buf_.flatbuffers_field_int16(pos_, 8, 100)
def name():
buf_.flatbuffers_field_string(pos_, 10)
def inventory(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 14) + i * 1)
def inventory_length():
buf_.flatbuffers_field_vector_len(pos_, 14)
def color():
buf_.flatbuffers_field_int8(pos_, 16, 2)
def weapons(i:int):
MyGame_Sample_Weapon { buf_, buf_.flatbuffers_indirect(buf_.flatbuffers_field_vector(pos_, 18) + i * 4) }
def weapons_length():
buf_.flatbuffers_field_vector_len(pos_, 18)
def equipped_type():
buf_.flatbuffers_field_int8(pos_, 20, 0)
def equipped_as_Weapon():
MyGame_Sample_Weapon { buf_, buf_.flatbuffers_field_table(pos_, 22) }
def GetRootAsMonster(buf:string): Monster { buf, buf.flatbuffers_indirect(0) }
def MonsterStart(b_:flatbuffers_builder):
b_.StartObject(10)
def MonsterAddPos(b_:flatbuffers_builder, pos:int):
b_.PrependStructSlot(0, pos, 0)
def MonsterAddMana(b_:flatbuffers_builder, mana:int):
b_.PrependInt16Slot(1, mana, 150)
def MonsterAddHp(b_:flatbuffers_builder, hp:int):
b_.PrependInt16Slot(2, hp, 100)
def MonsterAddName(b_:flatbuffers_builder, name:int):
b_.PrependUOffsetTRelativeSlot(3, name, 0)
def MonsterAddInventory(b_:flatbuffers_builder, inventory:int):
b_.PrependUOffsetTRelativeSlot(5, inventory, 0)
def MonsterStartInventoryVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def MonsterCreateInventoryVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependUint8(e_)
b_.EndVector(v_.length)
def MonsterAddColor(b_:flatbuffers_builder, color:int):
b_.PrependInt8Slot(6, color, 2)
def MonsterAddWeapons(b_:flatbuffers_builder, weapons:int):
b_.PrependUOffsetTRelativeSlot(7, weapons, 0)
def MonsterStartWeaponsVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateWeaponsVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddEquippedType(b_:flatbuffers_builder, equipped_type:int):
b_.PrependUint8Slot(8, equipped_type, 0)
def MonsterAddEquipped(b_:flatbuffers_builder, equipped:int):
b_.PrependUOffsetTRelativeSlot(9, equipped, 0)
def MonsterEnd(b_:flatbuffers_builder):
b_.EndObject()
struct Weapon : flatbuffers_handle
def name():
buf_.flatbuffers_field_string(pos_, 4)
def damage():
buf_.flatbuffers_field_int16(pos_, 6, 0)
def GetRootAsWeapon(buf:string): Weapon { buf, buf.flatbuffers_indirect(0) }
def WeaponStart(b_:flatbuffers_builder):
b_.StartObject(2)
def WeaponAddName(b_:flatbuffers_builder, name:int):
b_.PrependUOffsetTRelativeSlot(0, name, 0)
def WeaponAddDamage(b_:flatbuffers_builder, damage:int):
b_.PrependInt16Slot(1, damage, 0)
def WeaponEnd(b_:flatbuffers_builder):
b_.EndObject()
{ {
pos: { pos: {
x: 1, x: 1.0,
y: 2, y: 2.0,
z: 3 z: 3.0
}, },
hp: 300, hp: 300,
name: "Orc", name: "Orc",
weapons:[ weapons: [
{ {
name: "axe", name: "axe",
damage:100 damage: 100
}, },
{ {
name: "bow", name: "bow",
damage:90 damage: 90
} }
], ],
equipped_type: "Weapon", equipped_type: "Weapon",
equipped: equipped: {
{ name: "bow",
name: "bow", damage: 90
damage:90 }
}
} }
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
include from "../lobster/"
include "monster_generated.lobster"
// Example of how to use FlatBuffers to create and read binary buffers.
// Create a builder.
let b = flatbuffers_builder {}
// Create some weapons for our monster.
let weapon_names = [ "Sword", "Axe" ]
let weapon_damages = [ 3, 5 ]
weapon_offsets := map(weapon_names) name, i:
let ns = b.CreateString(name)
b.MyGame_Sample_WeaponStart()
b.MyGame_Sample_WeaponAddName(ns)
b.MyGame_Sample_WeaponAddDamage(weapon_damages[i])
b.MyGame_Sample_WeaponEnd()
let weapons = b.MyGame_Sample_MonsterCreateWeaponsVector(weapon_offsets)
// Name of the monster.
let name = b.CreateString("Orc")
// Inventory.
let inv = b.MyGame_Sample_MonsterCreateInventoryVector(map(10): _)
// Now pack it all together in our root monster object.
b.MyGame_Sample_MonsterStart()
b.MyGame_Sample_MonsterAddPos(b.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0))
b.MyGame_Sample_MonsterAddHp(300)
b.MyGame_Sample_MonsterAddName(name)
b.MyGame_Sample_MonsterAddInventory(inv)
b.MyGame_Sample_MonsterAddColor(MyGame_Sample_Color_Red)
b.MyGame_Sample_MonsterAddWeapons(weapons)
b.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon)
b.MyGame_Sample_MonsterAddEquipped(weapon_offsets[1])
let orc = b.MyGame_Sample_MonsterEnd()
// Finish the buffer!
b.Finish(orc)
// We now have a FlatBuffer that we could store on disk or send over a network.
let buf = b.SizedCopy()
// ...Saving to file or sending over a network code goes here...
// Instead, we are going to access this buffer right away (as if we just
// received it).
// Get the root object accessor.
let monster = MyGame_Sample_GetRootAsMonster(buf)
// Note: We did not set the `mana` field explicitly, so we get a default value.
assert monster.mana == 150
assert monster.hp == 300
assert monster.name == "Orc"
assert monster.color == MyGame_Sample_Color_Red
let pos = monster.pos
assert pos
assert pos.x == 1.0
assert pos.y == 2.0
assert pos.z == 3.0
// Get and test the `inventory` FlatBuffer vector.
for(monster.inventory_length) e, i:
assert monster.inventory(i) == e
// Get and test the `weapons` FlatBuffer vector of tables.
for(monster.weapons_length) i:
assert monster.weapons(i).name == weapon_names[i]
assert monster.weapons(i).damage == weapon_damages[i]
// Get and test the `equipped` FlatBuffer union.
assert monster.equipped_type() == MyGame_Sample_Equipment_Weapon
// Now that we know the union value is a weapon, we can safely call as_Weapon:
let union_weapon = monster.equipped_as_Weapon
assert union_weapon.name == "Axe"
assert union_weapon.damage == 5
print "The FlatBuffer was successfully created and verified!"
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
include from "../lobster/"
include "monster_generated.lobster"
// Example how to interop with JSON.
// Test loading some JSON, converting it to a binary FlatBuffer and back again.
// First read the schema and JSON data.
schema := read_file("monster.fbs", true)
json := read_file("monsterdata.json", true)
assert schema and json
// Parse JSON to binary:
fb, err1 := flatbuffers_json_to_binary(schema, json, [])
assert not err1
// Access one field in it, just to check:
let monster = MyGame_Sample_GetRootAsMonster(fb)
assert monster.name == "Orc"
// Convert binary back to JSON:
json2, err2 := flatbuffers_binary_to_json(schema, fb, [])
assert not err2
// The generated JSON should be exactly equal to the original!
assert json == json2
// Print what we've been converting for good measure:
print json
...@@ -71,6 +71,10 @@ int main(int argc, const char *argv[]) { ...@@ -71,6 +71,10 @@ int main(int argc, const char *argv[]) {
flatbuffers::IDLOptions::kPython, flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs", "Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule }, flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true, nullptr,
flatbuffers::IDLOptions::kLobster,
"Generate Lobster files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr, { flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr,
flatbuffers::IDLOptions::kLua, flatbuffers::IDLOptions::kLua,
"Generate Lua files for tables/structs", "Generate Lua files for tables/structs",
......
/*
* Copyright 2018 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <unordered_set>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
namespace lobster {
class LobsterGenerator : public BaseGenerator {
public:
LobsterGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "" /* not used */, "_") {
static const char * const keywords[] = {
"nil", "true", "false", "return", "struct", "value", "include", "int",
"float", "string", "any", "def", "is", "from", "program", "private",
"coroutine", "resource", "enum", "typeof", "var", "let", "pakfile",
"switch", "case", "default", "namespace", "not", "and", "or", "bool",
};
keywords_.insert(std::begin(keywords), std::end(keywords));
}
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : name + "_";
}
std::string NormalizedName(const Definition &definition) const {
return EscapeKeyword(definition.name);
}
std::string NormalizedName(const EnumVal &ev) const {
return EscapeKeyword(ev.name);
}
std::string NamespacedName(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, NormalizedName(def));
}
std::string GenTypeName(const Type &type) {
auto bits = NumToString(SizeOf(type.base_type) * 8);
if (IsInteger(type.base_type)) return "int" + bits;
if (IsFloat(type.base_type)) return "float" + bits;
if (type.base_type == BASE_TYPE_STRING) return "string";
if (type.base_type == BASE_TYPE_STRUCT) return "table";
return "none";
}
std::string LobsterType(const Type &type) {
if (IsFloat(type.base_type)) return "float";
return "int";
}
// Returns the method name for use with add/put calls.
std::string GenMethod(const Type &type) {
return IsScalar(type.base_type)
? MakeCamel(GenTypeBasic(type))
: (IsStruct(type) ? "Struct" : "UOffsetTRelative");
}
// This uses Python names for now..
std::string GenTypeBasic(const Type &type) {
static const char *ctypename[] = {
// clang-format off
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#PTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
// clang-format on
};
return ctypename[type.base_type];
}
// Generate a struct field, conditioned on its child type(s).
void GenStructAccessor(const StructDef &struct_def,
const FieldDef &field, std::string *code_ptr) {
GenComment(field.doc_comment, code_ptr, nullptr, " ");
std::string &code = *code_ptr;
auto offsets = NumToString(field.value.offset);
auto def = " def " + NormalizedName(field);
if (IsScalar(field.value.type.base_type)) {
if (struct_def.fixed) {
code += def + "():\n buf_.read_" +
GenTypeName(field.value.type) + "_le(pos_ + " + offsets +
")\n";
} else {
code += def + "():\n buf_.flatbuffers_field_" +
GenTypeName(field.value.type) + "(pos_, " + offsets + ", " +
field.value.constant + ")\n";
}
return;
}
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
auto name = NamespacedName(*field.value.type.struct_def);
code += def + "():\n ";
if (struct_def.fixed) {
code += name + "{ buf_, pos_ + " + offsets + " }\n";
} else {
code += std::string("o := buf_.flatbuffers_field_") +
(field.value.type.struct_def->fixed ? "struct" : "table") +
"(pos_, " + offsets + ")\n if o: " + name +
" { buf_, o } else: nil\n";
}
break;
}
case BASE_TYPE_STRING:
code += def + "():\n buf_.flatbuffers_field_string(pos_, " +
offsets + ")\n";
break;
case BASE_TYPE_VECTOR: {
auto vectortype = field.value.type.VectorType();
code += def + "(i:int):\n ";
if (vectortype.base_type == BASE_TYPE_STRUCT) {
auto start = "buf_.flatbuffers_field_vector(pos_, " + offsets +
") + i * " + NumToString(InlineSize(vectortype));
if (!(vectortype.struct_def->fixed)) {
start = "buf_.flatbuffers_indirect(" + start + ")";
}
code += NamespacedName(*field.value.type.struct_def) + " { buf_, " +
start + " }\n";
} else {
if (vectortype.base_type == BASE_TYPE_STRING)
code += "buf_.flatbuffers_string";
else
code += "buf_.read_" + GenTypeName(vectortype) + "_le";
code += "(buf_.flatbuffers_field_vector(pos_, " + offsets +
") + i * " + NumToString(InlineSize(vectortype)) + ")\n";
}
break;
}
case BASE_TYPE_UNION: {
for (auto &ev : field.value.type.enum_def->vals.vec) if (ev->value) {
code += def + "_as_" + ev->name + "():\n " +
NamespacedName(*ev->union_type.struct_def) +
" { buf_, buf_.flatbuffers_field_table(pos_, " + offsets +
") }\n";
}
break;
}
default: FLATBUFFERS_ASSERT(0);
}
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += def +
"_length():\n buf_.flatbuffers_field_vector_len(pos_, " +
offsets + ")\n";
}
}
// Generate table constructors, conditioned on its members' types.
void GenTableBuilders(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "def " + NormalizedName(struct_def) +
"Start(b_:flatbuffers_builder):\n b_.StartObject(" +
NumToString(struct_def.fields.vec.size()) + ")\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
code += "def " + NormalizedName(struct_def) + "Add" +
MakeCamel(NormalizedName(field)) + "(b_:flatbuffers_builder, " +
NormalizedName(field) + ":" + LobsterType(field.value.type) +
"):\n b_.Prepend" + GenMethod(field.value.type) + "Slot(" +
NumToString(offset) + ", " + NormalizedName(field) + ", " +
field.value.constant + ")\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += "def " + NormalizedName(struct_def) + "Start" +
MakeCamel(NormalizedName(field)) +
"Vector(b_:flatbuffers_builder, n_:int):\n b_.StartVector(";
auto vector_type = field.value.type.VectorType();
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
code += NumToString(elem_size) + ", n_, " + NumToString(alignment) +
")\n";
if (vector_type.base_type != BASE_TYPE_STRUCT ||
!vector_type.struct_def->fixed) {
code += "def " + NormalizedName(struct_def) + "Create" +
MakeCamel(NormalizedName(field)) +
"Vector(b_:flatbuffers_builder, v_:[" +
LobsterType(vector_type) + "]):\n b_.StartVector(" +
NumToString(elem_size) + ", v_.length, " +
NumToString(alignment) +
")\n reverse(v_) e_: b_.Prepend" +
GenMethod(vector_type) +
"(e_)\n b_.EndVector(v_.length)\n";
}
}
}
code += "def " + NormalizedName(struct_def) +
"End(b_:flatbuffers_builder):\n b_.EndObject()\n\n";
}
void GenStructPreDecl(const StructDef &struct_def, std::string *code_ptr) {
if (struct_def.generated) return;
std::string &code = *code_ptr;
CheckNameSpace(struct_def, &code);
code += "struct " + NormalizedName(struct_def) + "\n\n";
}
// Generate struct or table methods.
void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
if (struct_def.generated) return;
std::string &code = *code_ptr;
CheckNameSpace(struct_def, &code);
GenComment(struct_def.doc_comment, code_ptr, nullptr, "");
code += "struct " + NormalizedName(struct_def) + " : flatbuffers_handle\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
GenStructAccessor(struct_def, field, code_ptr);
}
code += "\n";
if (!struct_def.fixed) {
// Generate a special accessor for the table that has been declared as
// the root type.
code += "def GetRootAs" + NormalizedName(struct_def) + "(buf:string): " +
NormalizedName(struct_def) +
" { buf, buf.flatbuffers_indirect(0) }\n\n";
}
if (struct_def.fixed) {
// create a struct constructor function
GenStructBuilder(struct_def, code_ptr);
} else {
// Create a set of functions that allow table construction.
GenTableBuilders(struct_def, code_ptr);
}
}
// Generate enum declarations.
void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
if (enum_def.generated) return;
std::string &code = *code_ptr;
CheckNameSpace(enum_def, &code);
GenComment(enum_def.doc_comment, code_ptr, nullptr, "");
code += "enum + \n";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, nullptr, " ");
code += " " + enum_def.name + "_" + NormalizedName(ev) + " = " +
NumToString(ev.value);
if (it + 1 != enum_def.vals.vec.end()) code += ",";
code += "\n";
}
code += "\n";
}
// Recursively generate arguments for a constructor, to deal with nested
// structs.
void StructBuilderArgs(const StructDef &struct_def,
const char *nameprefix, std::string *code_ptr) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (IsStruct(field.value.type)) {
// Generate arguments for a struct inside a struct. To ensure names
// don't clash, and to make it obvious these arguments are constructing
// a nested struct, prefix the name with the field name.
StructBuilderArgs(*field.value.type.struct_def,
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
} else {
std::string &code = *code_ptr;
code += ", " + (nameprefix + NormalizedName(field)) + ":" +
LobsterType(field.value.type);
}
}
}
// Recursively generate struct construction statements and instert manual
// padding.
void StructBuilderBody(const StructDef &struct_def,
const char *nameprefix, std::string *code_ptr) {
std::string &code = *code_ptr;
code += " b_.Prep(" + NumToString(struct_def.minalign) + ", " +
NumToString(struct_def.bytesize) + ")\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.padding)
code += " b_.Pad(" + NumToString(field.padding) + ")\n";
if (IsStruct(field.value.type)) {
StructBuilderBody(*field.value.type.struct_def,
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
} else {
code += " b_.Prepend" + GenMethod(field.value.type) + "(" +
nameprefix + NormalizedName(field) + ")\n";
}
}
}
// Create a struct with a builder and the struct's arguments.
void GenStructBuilder(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
code += "def Create" + NormalizedName(struct_def) +
"(b_:flatbuffers_builder";
StructBuilderArgs(struct_def, "", code_ptr);
code += "):\n";
StructBuilderBody(struct_def, "", code_ptr);
code += " return b_.Offset()\n\n";
}
void CheckNameSpace(const Definition &def, std::string *code_ptr) {
auto ns = GetNameSpace(def);
if (ns == current_namespace_) return;
current_namespace_ = ns;
std::string &code = *code_ptr;
code += "namespace " + ns + "\n\n";
}
bool generate() {
std::string code;
code += std::string("// ") + FlatBuffersGeneratedWarning() +
"\n\ninclude \"flatbuffers.lobster\"\n\n";
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
GenEnum(enum_def, &code);
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
GenStructPreDecl(struct_def, &code);
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
GenStruct(struct_def, &code);
}
return SaveFile((path_ + file_name_ + "_generated.lobster").c_str(),
code, false);
}
private:
std::unordered_set<std::string> keywords_;
std::string current_namespace_;
};
} // namespace lobster
bool GenerateLobster(const Parser &parser, const std::string &path,
const std::string &file_name) {
lobster::LobsterGenerator generator(parser, path, file_name);
return generator.generate();
}
} // namespace flatbuffers
...@@ -40,6 +40,11 @@ echo "************************ Dart:" ...@@ -40,6 +40,11 @@ echo "************************ Dart:"
sh DartTest.sh sh DartTest.sh
echo "************************ Lobster:"
# TODO: test if available.
# lobster lobstertest.lobster
echo "************************ C:" echo "************************ C:"
echo "(in a different repo)" echo "(in a different repo)"
......
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
set buildtype=Release set buildtype=Release
if "%1"=="-b" set buildtype=%2 if "%1"=="-b" set buildtype=%2
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lua --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json ..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lua --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
..\%buildtype%\flatc.exe --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs ..\%buildtype%\flatc.exe --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
..\%buildtype%\flatc.exe -b --schema --bfbs-comments -I include_test monster_test.fbs ..\%buildtype%\flatc.exe -b --schema --bfbs-comments -I include_test monster_test.fbs
..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs
cd ../samples cd ../samples
..\%buildtype%\flatc.exe --cpp --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs ..\%buildtype%\flatc.exe --cpp --lobster --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
cd ../reflection cd ../reflection
cd ../tests cd ../tests
\ No newline at end of file
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
../flatc --cpp --java --csharp --dart --go --binary --lua --python --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json ../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --dart --go --binary --lua --python --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs ../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs ../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs
../flatc --jsonschema --schema -I include_test monster_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs
cd ../samples cd ../samples
../flatc --cpp --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs ../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
cd ../reflection cd ../reflection
// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
include from "../lobster/"
include "monster_test_generated.lobster"
def check_read_buffer(buf):
// CheckReadBuffer checks that the given buffer is evaluated correctly as the example Monster.
let monster = MyGame_Example_GetRootAsMonster(buf)
assert monster.hp == 80
assert monster.mana == 150
assert monster.name == "MyMonster"
let vec = monster.pos
assert vec
assert vec.x == 1.0
assert vec.y == 2.0
assert vec.z == 3.0
assert vec.test1 == 3.0
assert vec.test2 == 2
let t = vec.test3
assert t
assert t.a == 5
assert t.b == 6
assert monster.test_type == MyGame_Example_Any_Monster
assert monster.test_as_Monster.name == "Fred"
assert monster.inventory_length == 5
assert sum(map(monster.inventory_length) i: monster.inventory(i)) == 10
for(5) i:
assert monster.vector_of_longs(i) == pow(10, i * 2)
assert equal([-1.7976931348623157e+308, 0, 1.7976931348623157e+308],
(map(monster.vector_of_doubles_length) i: monster.vector_of_doubles(i)))
assert monster.test4_length == 2
let test0 = monster.test4(0)
let test1 = monster.test4(1)
assert test0.a + test0.b + test1.a + test1.b == 100
assert monster.testarrayofstring_length == 2
assert monster.testarrayofstring(0) == "test1"
assert monster.testarrayofstring(1) == "test2"
assert monster.testarrayoftables_length == 0
assert monster.testnestedflatbuffer_length == 0
assert not monster.testempty()
def make_monster_from_generated_code():
// Use generated code to build the example Monster.
let b = flatbuffers_builder {}
let name = b.CreateString("MyMonster")
let fred = b.CreateString("Fred")
let inv = b.MyGame_Example_MonsterCreateInventoryVector([ 0, 1, 2, 3, 4 ])
b.MyGame_Example_MonsterStart()
b.MyGame_Example_MonsterAddName(fred)
let mon2 = b.MyGame_Example_MonsterEnd()
b.MyGame_Example_MonsterStartTest4Vector(2)
b.MyGame_Example_CreateTest(10, 20)
b.MyGame_Example_CreateTest(30, 40)
let test4 = b.EndVector(2)
let test_array_of_string = b.MyGame_Example_MonsterCreateTestarrayofstringVector(
[ b.CreateString("test1"), b.CreateString("test2") ])
let vector_of_longs = b.MyGame_Example_MonsterCreateVectorOfLongsVector(
[ 1, 100, 10000, 1000000, 100000000 ])
let vector_of_doubles = b.MyGame_Example_MonsterCreateVectorOfDoublesVector(
[ -1.7976931348623157e+308, 0, 1.7976931348623157e+308 ])
b.MyGame_Example_MonsterStart()
b.MyGame_Example_MonsterAddPos(b.MyGame_Example_CreateVec3(1.0, 2.0, 3.0, 3.0, 2, 5, 6))
b.MyGame_Example_MonsterAddHp(80)
b.MyGame_Example_MonsterAddName(name)
b.MyGame_Example_MonsterAddInventory(inv)
b.MyGame_Example_MonsterAddTestType(MyGame_Example_Any_Monster)
b.MyGame_Example_MonsterAddTest(mon2)
b.MyGame_Example_MonsterAddTest4(test4)
b.MyGame_Example_MonsterAddTestarrayofstring(test_array_of_string)
b.MyGame_Example_MonsterAddVectorOfLongs(vector_of_longs)
b.MyGame_Example_MonsterAddVectorOfDoubles(vector_of_doubles)
let mon = b.MyGame_Example_MonsterEnd()
b.Finish(mon)
return b.SizedCopy()
// Verify that the canonical flatbuffer file (produced by the C++ implementation)
// is readable by the generated Lobster code.
let fb2 = read_file("monsterdata_test.mon")
assert fb2
check_read_buffer(fb2)
// Verify that using the generated Lobster code builds a buffer without
// returning errors, and is interpreted correctly.
let fb1 = make_monster_from_generated_code()
check_read_buffer(fb1)
// Write the result to file for no good reason.
write_file("monsterdata_lobster_wire.mon", fb1)
// Test converting the buffer to JSON and parsing the JSON back again.
schema := read_file("monster_test.fbs")
assert schema
includedirs := [ "include_test" ]
// Convert binary to JSON:
json, err1 := flatbuffers_binary_to_json(schema, fb1, includedirs)
assert not err1
// Parse JSON back to binary:
fb3, err2 := flatbuffers_json_to_binary(schema, json, includedirs)
assert not err2
// Check the resulting binary again (full roundtrip test):
check_read_buffer(fb3)
print "Lobster test succesful!"
\ No newline at end of file
// automatically generated by the FlatBuffers compiler, do not modify
include "flatbuffers.lobster"
namespace MyGame_Example
enum +
Color_Red = 1,
Color_Green = 2,
Color_Blue = 8
enum +
Any_NONE = 0,
Any_Monster = 1,
Any_TestSimpleTableWithEnum = 2,
Any_MyGame_Example2_Monster = 3
namespace MyGame
struct InParentNamespace
namespace MyGame_Example2
struct Monster
namespace MyGame_Example
struct Test
struct TestSimpleTableWithEnum
struct Vec3
struct Ability
struct Stat
struct Referrable
struct Monster
struct TypeAliases
namespace MyGame
struct InParentNamespace : flatbuffers_handle
def GetRootAsInParentNamespace(buf:string): InParentNamespace { buf, buf.flatbuffers_indirect(0) }
def InParentNamespaceStart(b_:flatbuffers_builder):
b_.StartObject(0)
def InParentNamespaceEnd(b_:flatbuffers_builder):
b_.EndObject()
namespace MyGame_Example2
struct Monster : flatbuffers_handle
def GetRootAsMonster(buf:string): Monster { buf, buf.flatbuffers_indirect(0) }
def MonsterStart(b_:flatbuffers_builder):
b_.StartObject(0)
def MonsterEnd(b_:flatbuffers_builder):
b_.EndObject()
namespace MyGame_Example
struct Test : flatbuffers_handle
def a():
buf_.read_int16_le(pos_ + 0)
def b():
buf_.read_int8_le(pos_ + 2)
def CreateTest(b_:flatbuffers_builder, a:int, b:int):
b_.Prep(2, 4)
b_.Pad(1)
b_.PrependInt8(b)
b_.PrependInt16(a)
return b_.Offset()
struct TestSimpleTableWithEnum : flatbuffers_handle
def color():
buf_.flatbuffers_field_int8(pos_, 4, 2)
def GetRootAsTestSimpleTableWithEnum(buf:string): TestSimpleTableWithEnum { buf, buf.flatbuffers_indirect(0) }
def TestSimpleTableWithEnumStart(b_:flatbuffers_builder):
b_.StartObject(1)
def TestSimpleTableWithEnumAddColor(b_:flatbuffers_builder, color:int):
b_.PrependInt8Slot(0, color, 2)
def TestSimpleTableWithEnumEnd(b_:flatbuffers_builder):
b_.EndObject()
struct Vec3 : flatbuffers_handle
def x():
buf_.read_float32_le(pos_ + 0)
def y():
buf_.read_float32_le(pos_ + 4)
def z():
buf_.read_float32_le(pos_ + 8)
def test1():
buf_.read_float64_le(pos_ + 16)
def test2():
buf_.read_int8_le(pos_ + 24)
def test3():
MyGame_Example_Test{ buf_, pos_ + 26 }
def CreateVec3(b_:flatbuffers_builder, x:float, y:float, z:float, test1:float, test2:int, test3_a:int, test3_b:int):
b_.Prep(16, 32)
b_.Pad(2)
b_.Prep(2, 4)
b_.Pad(1)
b_.PrependInt8(test3_b)
b_.PrependInt16(test3_a)
b_.Pad(1)
b_.PrependInt8(test2)
b_.PrependFloat64(test1)
b_.Pad(4)
b_.PrependFloat32(z)
b_.PrependFloat32(y)
b_.PrependFloat32(x)
return b_.Offset()
struct Ability : flatbuffers_handle
def id():
buf_.read_int32_le(pos_ + 0)
def distance():
buf_.read_int32_le(pos_ + 4)
def CreateAbility(b_:flatbuffers_builder, id:int, distance:int):
b_.Prep(4, 8)
b_.PrependUint32(distance)
b_.PrependUint32(id)
return b_.Offset()
struct Stat : flatbuffers_handle
def id():
buf_.flatbuffers_field_string(pos_, 4)
def val():
buf_.flatbuffers_field_int64(pos_, 6, 0)
def count():
buf_.flatbuffers_field_int16(pos_, 8, 0)
def GetRootAsStat(buf:string): Stat { buf, buf.flatbuffers_indirect(0) }
def StatStart(b_:flatbuffers_builder):
b_.StartObject(3)
def StatAddId(b_:flatbuffers_builder, id:int):
b_.PrependUOffsetTRelativeSlot(0, id, 0)
def StatAddVal(b_:flatbuffers_builder, val:int):
b_.PrependInt64Slot(1, val, 0)
def StatAddCount(b_:flatbuffers_builder, count:int):
b_.PrependUint16Slot(2, count, 0)
def StatEnd(b_:flatbuffers_builder):
b_.EndObject()
struct Referrable : flatbuffers_handle
def id():
buf_.flatbuffers_field_int64(pos_, 4, 0)
def GetRootAsReferrable(buf:string): Referrable { buf, buf.flatbuffers_indirect(0) }
def ReferrableStart(b_:flatbuffers_builder):
b_.StartObject(1)
def ReferrableAddId(b_:flatbuffers_builder, id:int):
b_.PrependUint64Slot(0, id, 0)
def ReferrableEnd(b_:flatbuffers_builder):
b_.EndObject()
/// an example documentation comment: monster object
struct Monster : flatbuffers_handle
def pos():
o := buf_.flatbuffers_field_struct(pos_, 4)
if o: MyGame_Example_Vec3 { buf_, o } else: nil
def mana():
buf_.flatbuffers_field_int16(pos_, 6, 150)
def hp():
buf_.flatbuffers_field_int16(pos_, 8, 100)
def name():
buf_.flatbuffers_field_string(pos_, 10)
def inventory(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 14) + i * 1)
def inventory_length():
buf_.flatbuffers_field_vector_len(pos_, 14)
def color():
buf_.flatbuffers_field_int8(pos_, 16, 8)
def test_type():
buf_.flatbuffers_field_int8(pos_, 18, 0)
def test_as_Monster():
MyGame_Example_Monster { buf_, buf_.flatbuffers_field_table(pos_, 20) }
def test_as_TestSimpleTableWithEnum():
MyGame_Example_TestSimpleTableWithEnum { buf_, buf_.flatbuffers_field_table(pos_, 20) }
def test_as_MyGame_Example2_Monster():
MyGame_Example2_Monster { buf_, buf_.flatbuffers_field_table(pos_, 20) }
def test4(i:int):
MyGame_Example_Test { buf_, buf_.flatbuffers_field_vector(pos_, 22) + i * 4 }
def test4_length():
buf_.flatbuffers_field_vector_len(pos_, 22)
def testarrayofstring(i:int):
buf_.flatbuffers_string(buf_.flatbuffers_field_vector(pos_, 24) + i * 4)
def testarrayofstring_length():
buf_.flatbuffers_field_vector_len(pos_, 24)
/// an example documentation comment: this will end up in the generated code
/// multiline too
def testarrayoftables(i:int):
MyGame_Example_Monster { buf_, buf_.flatbuffers_indirect(buf_.flatbuffers_field_vector(pos_, 26) + i * 4) }
def testarrayoftables_length():
buf_.flatbuffers_field_vector_len(pos_, 26)
def enemy():
o := buf_.flatbuffers_field_table(pos_, 28)
if o: MyGame_Example_Monster { buf_, o } else: nil
def testnestedflatbuffer(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 30) + i * 1)
def testnestedflatbuffer_length():
buf_.flatbuffers_field_vector_len(pos_, 30)
def testempty():
o := buf_.flatbuffers_field_table(pos_, 32)
if o: MyGame_Example_Stat { buf_, o } else: nil
def testbool():
buf_.flatbuffers_field_int8(pos_, 34, 0)
def testhashs32_fnv1():
buf_.flatbuffers_field_int32(pos_, 36, 0)
def testhashu32_fnv1():
buf_.flatbuffers_field_int32(pos_, 38, 0)
def testhashs64_fnv1():
buf_.flatbuffers_field_int64(pos_, 40, 0)
def testhashu64_fnv1():
buf_.flatbuffers_field_int64(pos_, 42, 0)
def testhashs32_fnv1a():
buf_.flatbuffers_field_int32(pos_, 44, 0)
def testhashu32_fnv1a():
buf_.flatbuffers_field_int32(pos_, 46, 0)
def testhashs64_fnv1a():
buf_.flatbuffers_field_int64(pos_, 48, 0)
def testhashu64_fnv1a():
buf_.flatbuffers_field_int64(pos_, 50, 0)
def testarrayofbools(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 52) + i * 1)
def testarrayofbools_length():
buf_.flatbuffers_field_vector_len(pos_, 52)
def testf():
buf_.flatbuffers_field_float32(pos_, 54, 3.14159)
def testf2():
buf_.flatbuffers_field_float32(pos_, 56, 3.0)
def testf3():
buf_.flatbuffers_field_float32(pos_, 58, 0.0)
def testarrayofstring2(i:int):
buf_.flatbuffers_string(buf_.flatbuffers_field_vector(pos_, 60) + i * 4)
def testarrayofstring2_length():
buf_.flatbuffers_field_vector_len(pos_, 60)
def testarrayofsortedstruct(i:int):
MyGame_Example_Ability { buf_, buf_.flatbuffers_field_vector(pos_, 62) + i * 8 }
def testarrayofsortedstruct_length():
buf_.flatbuffers_field_vector_len(pos_, 62)
def flex(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 64) + i * 1)
def flex_length():
buf_.flatbuffers_field_vector_len(pos_, 64)
def test5(i:int):
MyGame_Example_Test { buf_, buf_.flatbuffers_field_vector(pos_, 66) + i * 4 }
def test5_length():
buf_.flatbuffers_field_vector_len(pos_, 66)
def vector_of_longs(i:int):
buf_.read_int64_le(buf_.flatbuffers_field_vector(pos_, 68) + i * 8)
def vector_of_longs_length():
buf_.flatbuffers_field_vector_len(pos_, 68)
def vector_of_doubles(i:int):
buf_.read_float64_le(buf_.flatbuffers_field_vector(pos_, 70) + i * 8)
def vector_of_doubles_length():
buf_.flatbuffers_field_vector_len(pos_, 70)
def parent_namespace_test():
o := buf_.flatbuffers_field_table(pos_, 72)
if o: MyGame_InParentNamespace { buf_, o } else: nil
def vector_of_referrables(i:int):
MyGame_Example_Referrable { buf_, buf_.flatbuffers_indirect(buf_.flatbuffers_field_vector(pos_, 74) + i * 4) }
def vector_of_referrables_length():
buf_.flatbuffers_field_vector_len(pos_, 74)
def single_weak_reference():
buf_.flatbuffers_field_int64(pos_, 76, 0)
def vector_of_weak_references(i:int):
buf_.read_int64_le(buf_.flatbuffers_field_vector(pos_, 78) + i * 8)
def vector_of_weak_references_length():
buf_.flatbuffers_field_vector_len(pos_, 78)
def vector_of_strong_referrables(i:int):
MyGame_Example_Referrable { buf_, buf_.flatbuffers_indirect(buf_.flatbuffers_field_vector(pos_, 80) + i * 4) }
def vector_of_strong_referrables_length():
buf_.flatbuffers_field_vector_len(pos_, 80)
def co_owning_reference():
buf_.flatbuffers_field_int64(pos_, 82, 0)
def vector_of_co_owning_references(i:int):
buf_.read_int64_le(buf_.flatbuffers_field_vector(pos_, 84) + i * 8)
def vector_of_co_owning_references_length():
buf_.flatbuffers_field_vector_len(pos_, 84)
def non_owning_reference():
buf_.flatbuffers_field_int64(pos_, 86, 0)
def vector_of_non_owning_references(i:int):
buf_.read_int64_le(buf_.flatbuffers_field_vector(pos_, 88) + i * 8)
def vector_of_non_owning_references_length():
buf_.flatbuffers_field_vector_len(pos_, 88)
def GetRootAsMonster(buf:string): Monster { buf, buf.flatbuffers_indirect(0) }
def MonsterStart(b_:flatbuffers_builder):
b_.StartObject(43)
def MonsterAddPos(b_:flatbuffers_builder, pos:int):
b_.PrependStructSlot(0, pos, 0)
def MonsterAddMana(b_:flatbuffers_builder, mana:int):
b_.PrependInt16Slot(1, mana, 150)
def MonsterAddHp(b_:flatbuffers_builder, hp:int):
b_.PrependInt16Slot(2, hp, 100)
def MonsterAddName(b_:flatbuffers_builder, name:int):
b_.PrependUOffsetTRelativeSlot(3, name, 0)
def MonsterAddInventory(b_:flatbuffers_builder, inventory:int):
b_.PrependUOffsetTRelativeSlot(5, inventory, 0)
def MonsterStartInventoryVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def MonsterCreateInventoryVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependUint8(e_)
b_.EndVector(v_.length)
def MonsterAddColor(b_:flatbuffers_builder, color:int):
b_.PrependInt8Slot(6, color, 8)
def MonsterAddTestType(b_:flatbuffers_builder, test_type:int):
b_.PrependUint8Slot(7, test_type, 0)
def MonsterAddTest(b_:flatbuffers_builder, test:int):
b_.PrependUOffsetTRelativeSlot(8, test, 0)
def MonsterAddTest4(b_:flatbuffers_builder, test4:int):
b_.PrependUOffsetTRelativeSlot(9, test4, 0)
def MonsterStartTest4Vector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 2)
def MonsterAddTestarrayofstring(b_:flatbuffers_builder, testarrayofstring:int):
b_.PrependUOffsetTRelativeSlot(10, testarrayofstring, 0)
def MonsterStartTestarrayofstringVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateTestarrayofstringVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddTestarrayoftables(b_:flatbuffers_builder, testarrayoftables:int):
b_.PrependUOffsetTRelativeSlot(11, testarrayoftables, 0)
def MonsterStartTestarrayoftablesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateTestarrayoftablesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddEnemy(b_:flatbuffers_builder, enemy:int):
b_.PrependUOffsetTRelativeSlot(12, enemy, 0)
def MonsterAddTestnestedflatbuffer(b_:flatbuffers_builder, testnestedflatbuffer:int):
b_.PrependUOffsetTRelativeSlot(13, testnestedflatbuffer, 0)
def MonsterStartTestnestedflatbufferVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def MonsterCreateTestnestedflatbufferVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependUint8(e_)
b_.EndVector(v_.length)
def MonsterAddTestempty(b_:flatbuffers_builder, testempty:int):
b_.PrependUOffsetTRelativeSlot(14, testempty, 0)
def MonsterAddTestbool(b_:flatbuffers_builder, testbool:int):
b_.PrependBoolSlot(15, testbool, 0)
def MonsterAddTesthashs32Fnv1(b_:flatbuffers_builder, testhashs32_fnv1:int):
b_.PrependInt32Slot(16, testhashs32_fnv1, 0)
def MonsterAddTesthashu32Fnv1(b_:flatbuffers_builder, testhashu32_fnv1:int):
b_.PrependUint32Slot(17, testhashu32_fnv1, 0)
def MonsterAddTesthashs64Fnv1(b_:flatbuffers_builder, testhashs64_fnv1:int):
b_.PrependInt64Slot(18, testhashs64_fnv1, 0)
def MonsterAddTesthashu64Fnv1(b_:flatbuffers_builder, testhashu64_fnv1:int):
b_.PrependUint64Slot(19, testhashu64_fnv1, 0)
def MonsterAddTesthashs32Fnv1a(b_:flatbuffers_builder, testhashs32_fnv1a:int):
b_.PrependInt32Slot(20, testhashs32_fnv1a, 0)
def MonsterAddTesthashu32Fnv1a(b_:flatbuffers_builder, testhashu32_fnv1a:int):
b_.PrependUint32Slot(21, testhashu32_fnv1a, 0)
def MonsterAddTesthashs64Fnv1a(b_:flatbuffers_builder, testhashs64_fnv1a:int):
b_.PrependInt64Slot(22, testhashs64_fnv1a, 0)
def MonsterAddTesthashu64Fnv1a(b_:flatbuffers_builder, testhashu64_fnv1a:int):
b_.PrependUint64Slot(23, testhashu64_fnv1a, 0)
def MonsterAddTestarrayofbools(b_:flatbuffers_builder, testarrayofbools:int):
b_.PrependUOffsetTRelativeSlot(24, testarrayofbools, 0)
def MonsterStartTestarrayofboolsVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def MonsterCreateTestarrayofboolsVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependBool(e_)
b_.EndVector(v_.length)
def MonsterAddTestf(b_:flatbuffers_builder, testf:float):
b_.PrependFloat32Slot(25, testf, 3.14159)
def MonsterAddTestf2(b_:flatbuffers_builder, testf2:float):
b_.PrependFloat32Slot(26, testf2, 3.0)
def MonsterAddTestf3(b_:flatbuffers_builder, testf3:float):
b_.PrependFloat32Slot(27, testf3, 0.0)
def MonsterAddTestarrayofstring2(b_:flatbuffers_builder, testarrayofstring2:int):
b_.PrependUOffsetTRelativeSlot(28, testarrayofstring2, 0)
def MonsterStartTestarrayofstring2Vector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateTestarrayofstring2Vector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddTestarrayofsortedstruct(b_:flatbuffers_builder, testarrayofsortedstruct:int):
b_.PrependUOffsetTRelativeSlot(29, testarrayofsortedstruct, 0)
def MonsterStartTestarrayofsortedstructVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 4)
def MonsterAddFlex(b_:flatbuffers_builder, flex:int):
b_.PrependUOffsetTRelativeSlot(30, flex, 0)
def MonsterStartFlexVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def MonsterCreateFlexVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependUint8(e_)
b_.EndVector(v_.length)
def MonsterAddTest5(b_:flatbuffers_builder, test5:int):
b_.PrependUOffsetTRelativeSlot(31, test5, 0)
def MonsterStartTest5Vector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 2)
def MonsterAddVectorOfLongs(b_:flatbuffers_builder, vector_of_longs:int):
b_.PrependUOffsetTRelativeSlot(32, vector_of_longs, 0)
def MonsterStartVectorOfLongsVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def MonsterCreateVectorOfLongsVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependInt64(e_)
b_.EndVector(v_.length)
def MonsterAddVectorOfDoubles(b_:flatbuffers_builder, vector_of_doubles:int):
b_.PrependUOffsetTRelativeSlot(33, vector_of_doubles, 0)
def MonsterStartVectorOfDoublesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def MonsterCreateVectorOfDoublesVector(b_:flatbuffers_builder, v_:[float]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependFloat64(e_)
b_.EndVector(v_.length)
def MonsterAddParentNamespaceTest(b_:flatbuffers_builder, parent_namespace_test:int):
b_.PrependUOffsetTRelativeSlot(34, parent_namespace_test, 0)
def MonsterAddVectorOfReferrables(b_:flatbuffers_builder, vector_of_referrables:int):
b_.PrependUOffsetTRelativeSlot(35, vector_of_referrables, 0)
def MonsterStartVectorOfReferrablesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateVectorOfReferrablesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddSingleWeakReference(b_:flatbuffers_builder, single_weak_reference:int):
b_.PrependUint64Slot(36, single_weak_reference, 0)
def MonsterAddVectorOfWeakReferences(b_:flatbuffers_builder, vector_of_weak_references:int):
b_.PrependUOffsetTRelativeSlot(37, vector_of_weak_references, 0)
def MonsterStartVectorOfWeakReferencesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def MonsterCreateVectorOfWeakReferencesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependUint64(e_)
b_.EndVector(v_.length)
def MonsterAddVectorOfStrongReferrables(b_:flatbuffers_builder, vector_of_strong_referrables:int):
b_.PrependUOffsetTRelativeSlot(38, vector_of_strong_referrables, 0)
def MonsterStartVectorOfStrongReferrablesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(4, n_, 4)
def MonsterCreateVectorOfStrongReferrablesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(4, v_.length, 4)
reverse(v_) e_: b_.PrependUOffsetTRelative(e_)
b_.EndVector(v_.length)
def MonsterAddCoOwningReference(b_:flatbuffers_builder, co_owning_reference:int):
b_.PrependUint64Slot(39, co_owning_reference, 0)
def MonsterAddVectorOfCoOwningReferences(b_:flatbuffers_builder, vector_of_co_owning_references:int):
b_.PrependUOffsetTRelativeSlot(40, vector_of_co_owning_references, 0)
def MonsterStartVectorOfCoOwningReferencesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def MonsterCreateVectorOfCoOwningReferencesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependUint64(e_)
b_.EndVector(v_.length)
def MonsterAddNonOwningReference(b_:flatbuffers_builder, non_owning_reference:int):
b_.PrependUint64Slot(41, non_owning_reference, 0)
def MonsterAddVectorOfNonOwningReferences(b_:flatbuffers_builder, vector_of_non_owning_references:int):
b_.PrependUOffsetTRelativeSlot(42, vector_of_non_owning_references, 0)
def MonsterStartVectorOfNonOwningReferencesVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def MonsterCreateVectorOfNonOwningReferencesVector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependUint64(e_)
b_.EndVector(v_.length)
def MonsterEnd(b_:flatbuffers_builder):
b_.EndObject()
struct TypeAliases : flatbuffers_handle
def i8():
buf_.flatbuffers_field_int8(pos_, 4, 0)
def u8():
buf_.flatbuffers_field_int8(pos_, 6, 0)
def i16():
buf_.flatbuffers_field_int16(pos_, 8, 0)
def u16():
buf_.flatbuffers_field_int16(pos_, 10, 0)
def i32():
buf_.flatbuffers_field_int32(pos_, 12, 0)
def u32():
buf_.flatbuffers_field_int32(pos_, 14, 0)
def i64():
buf_.flatbuffers_field_int64(pos_, 16, 0)
def u64():
buf_.flatbuffers_field_int64(pos_, 18, 0)
def f32():
buf_.flatbuffers_field_float32(pos_, 20, 0.0)
def f64():
buf_.flatbuffers_field_float64(pos_, 22, 0.0)
def v8(i:int):
buf_.read_int8_le(buf_.flatbuffers_field_vector(pos_, 24) + i * 1)
def v8_length():
buf_.flatbuffers_field_vector_len(pos_, 24)
def vf64(i:int):
buf_.read_float64_le(buf_.flatbuffers_field_vector(pos_, 26) + i * 8)
def vf64_length():
buf_.flatbuffers_field_vector_len(pos_, 26)
def GetRootAsTypeAliases(buf:string): TypeAliases { buf, buf.flatbuffers_indirect(0) }
def TypeAliasesStart(b_:flatbuffers_builder):
b_.StartObject(12)
def TypeAliasesAddI8(b_:flatbuffers_builder, i8:int):
b_.PrependInt8Slot(0, i8, 0)
def TypeAliasesAddU8(b_:flatbuffers_builder, u8:int):
b_.PrependUint8Slot(1, u8, 0)
def TypeAliasesAddI16(b_:flatbuffers_builder, i16:int):
b_.PrependInt16Slot(2, i16, 0)
def TypeAliasesAddU16(b_:flatbuffers_builder, u16:int):
b_.PrependUint16Slot(3, u16, 0)
def TypeAliasesAddI32(b_:flatbuffers_builder, i32:int):
b_.PrependInt32Slot(4, i32, 0)
def TypeAliasesAddU32(b_:flatbuffers_builder, u32:int):
b_.PrependUint32Slot(5, u32, 0)
def TypeAliasesAddI64(b_:flatbuffers_builder, i64:int):
b_.PrependInt64Slot(6, i64, 0)
def TypeAliasesAddU64(b_:flatbuffers_builder, u64:int):
b_.PrependUint64Slot(7, u64, 0)
def TypeAliasesAddF32(b_:flatbuffers_builder, f32:float):
b_.PrependFloat32Slot(8, f32, 0.0)
def TypeAliasesAddF64(b_:flatbuffers_builder, f64:float):
b_.PrependFloat64Slot(9, f64, 0.0)
def TypeAliasesAddV8(b_:flatbuffers_builder, v8:int):
b_.PrependUOffsetTRelativeSlot(10, v8, 0)
def TypeAliasesStartV8Vector(b_:flatbuffers_builder, n_:int):
b_.StartVector(1, n_, 1)
def TypeAliasesCreateV8Vector(b_:flatbuffers_builder, v_:[int]):
b_.StartVector(1, v_.length, 1)
reverse(v_) e_: b_.PrependInt8(e_)
b_.EndVector(v_.length)
def TypeAliasesAddVf64(b_:flatbuffers_builder, vf64:int):
b_.PrependUOffsetTRelativeSlot(11, vf64, 0)
def TypeAliasesStartVf64Vector(b_:flatbuffers_builder, n_:int):
b_.StartVector(8, n_, 8)
def TypeAliasesCreateVf64Vector(b_:flatbuffers_builder, v_:[float]):
b_.StartVector(8, v_.length, 8)
reverse(v_) e_: b_.PrependFloat64(e_)
b_.EndVector(v_.length)
def TypeAliasesEnd(b_:flatbuffers_builder):
b_.EndObject()
// automatically generated by the FlatBuffers compiler, do not modify
include "flatbuffers.lobster"
namespace NamespaceA_NamespaceB
enum +
EnumInNestedNS_A = 0,
EnumInNestedNS_B = 1,
EnumInNestedNS_C = 2
struct TableInNestedNS
struct StructInNestedNS
struct TableInNestedNS : flatbuffers_handle
def foo():
buf_.flatbuffers_field_int32(pos_, 4, 0)
def GetRootAsTableInNestedNS(buf:string): TableInNestedNS { buf, buf.flatbuffers_indirect(0) }
def TableInNestedNSStart(b_:flatbuffers_builder):
b_.StartObject(1)
def TableInNestedNSAddFoo(b_:flatbuffers_builder, foo:int):
b_.PrependInt32Slot(0, foo, 0)
def TableInNestedNSEnd(b_:flatbuffers_builder):
b_.EndObject()
struct StructInNestedNS : flatbuffers_handle
def a():
buf_.read_int32_le(pos_ + 0)
def b():
buf_.read_int32_le(pos_ + 4)
def CreateStructInNestedNS(b_:flatbuffers_builder, a:int, b:int):
b_.Prep(4, 8)
b_.PrependInt32(b)
b_.PrependInt32(a)
return b_.Offset()
// automatically generated by the FlatBuffers compiler, do not modify
include "flatbuffers.lobster"
namespace NamespaceA
struct TableInFirstNS
namespace NamespaceC
struct TableInC
namespace NamespaceA
struct SecondTableInA
struct TableInFirstNS : flatbuffers_handle
def foo_table():
o := buf_.flatbuffers_field_table(pos_, 4)
if o: NamespaceA_NamespaceB_TableInNestedNS { buf_, o } else: nil
def foo_enum():
buf_.flatbuffers_field_int8(pos_, 6, 0)
def foo_struct():
o := buf_.flatbuffers_field_struct(pos_, 8)
if o: NamespaceA_NamespaceB_StructInNestedNS { buf_, o } else: nil
def GetRootAsTableInFirstNS(buf:string): TableInFirstNS { buf, buf.flatbuffers_indirect(0) }
def TableInFirstNSStart(b_:flatbuffers_builder):
b_.StartObject(3)
def TableInFirstNSAddFooTable(b_:flatbuffers_builder, foo_table:int):
b_.PrependUOffsetTRelativeSlot(0, foo_table, 0)
def TableInFirstNSAddFooEnum(b_:flatbuffers_builder, foo_enum:int):
b_.PrependInt8Slot(1, foo_enum, 0)
def TableInFirstNSAddFooStruct(b_:flatbuffers_builder, foo_struct:int):
b_.PrependStructSlot(2, foo_struct, 0)
def TableInFirstNSEnd(b_:flatbuffers_builder):
b_.EndObject()
namespace NamespaceC
struct TableInC : flatbuffers_handle
def refer_to_a1():
o := buf_.flatbuffers_field_table(pos_, 4)
if o: NamespaceA_TableInFirstNS { buf_, o } else: nil
def refer_to_a2():
o := buf_.flatbuffers_field_table(pos_, 6)
if o: NamespaceA_SecondTableInA { buf_, o } else: nil
def GetRootAsTableInC(buf:string): TableInC { buf, buf.flatbuffers_indirect(0) }
def TableInCStart(b_:flatbuffers_builder):
b_.StartObject(2)
def TableInCAddReferToA1(b_:flatbuffers_builder, refer_to_a1:int):
b_.PrependUOffsetTRelativeSlot(0, refer_to_a1, 0)
def TableInCAddReferToA2(b_:flatbuffers_builder, refer_to_a2:int):
b_.PrependUOffsetTRelativeSlot(1, refer_to_a2, 0)
def TableInCEnd(b_:flatbuffers_builder):
b_.EndObject()
namespace NamespaceA
struct SecondTableInA : flatbuffers_handle
def refer_to_c():
o := buf_.flatbuffers_field_table(pos_, 4)
if o: NamespaceC_TableInC { buf_, o } else: nil
def GetRootAsSecondTableInA(buf:string): SecondTableInA { buf, buf.flatbuffers_indirect(0) }
def SecondTableInAStart(b_:flatbuffers_builder):
b_.StartObject(1)
def SecondTableInAAddReferToC(b_:flatbuffers_builder, refer_to_c:int):
b_.PrependUOffsetTRelativeSlot(0, refer_to_c, 0)
def SecondTableInAEnd(b_:flatbuffers_builder):
b_.EndObject()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment