From 4898809eca4c01a0bc51f31044ab2ffd1408350b Mon Sep 17 00:00:00 2001 From: aardappel Date: Mon, 23 Jul 2018 19:03:11 -0700 Subject: [PATCH] FlatBuffers implementation for the Lobster programming language Language, see: http://strlen.com/lobster/ and https://github.com/aardappel/lobster --- .gitignore | 1 + BUILD | 1 + CMakeLists.txt | 1 + docs/source/Compiler.md | 6 + docs/source/FlatBuffers.md | 4 +- docs/source/LobsterUsage.md | 85 +++ docs/source/Support.md | 36 +- docs/source/Tutorial.md | 165 +++++- docs/source/doxyfile | 1 + docs/source/doxygen_layout.xml | 2 + include/flatbuffers/idl.h | 7 + lobster/flatbuffers.lobster | 278 +++++++++ samples/monster_generated.lobster | 115 ++++ samples/monsterdata.json | 21 +- samples/sample_binary.lobster | 98 ++++ samples/sample_text.lobster | 43 ++ src/flatc_main.cpp | 4 + src/idl_gen_lobster.cpp | 369 ++++++++++++ tests/TestAll.sh | 5 + tests/generate_code.bat | 6 +- tests/generate_code.sh | 6 +- tests/lobstertest.lobster | 134 +++++ tests/monster_test_generated.lobster | 554 ++++++++++++++++++ .../namespace_test1_generated.lobster | 40 ++ .../namespace_test2_generated.lobster | 76 +++ 25 files changed, 2017 insertions(+), 41 deletions(-) create mode 100644 docs/source/LobsterUsage.md create mode 100644 lobster/flatbuffers.lobster create mode 100644 samples/monster_generated.lobster create mode 100644 samples/sample_binary.lobster create mode 100644 samples/sample_text.lobster create mode 100644 src/idl_gen_lobster.cpp create mode 100644 tests/lobstertest.lobster create mode 100644 tests/monster_test_generated.lobster create mode 100644 tests/namespace_test/namespace_test1_generated.lobster create mode 100644 tests/namespace_test/namespace_test2_generated.lobster diff --git a/.gitignore b/.gitignore index 77731612c..b45308aba 100644 --- a/.gitignore +++ b/.gitignore @@ -55,6 +55,7 @@ tests/monsterdata_java_wire.mon tests/monsterdata_java_wire_sp.mon tests/monsterdata_go_wire.mon tests/monsterdata_javascript_wire.mon +tests/monsterdata_lobster_wire.mon tests/unicode_test.mon tests/ts/ tests/php/ diff --git a/BUILD b/BUILD index 27dbb45e9..0b940e502 100644 --- a/BUILD +++ b/BUILD @@ -94,6 +94,7 @@ cc_binary( "src/idl_gen_js.cpp", "src/idl_gen_json_schema.cpp", "src/idl_gen_lua.cpp", + "src/idl_gen_lobster.cpp", "src/idl_gen_php.cpp", "src/idl_gen_python.cpp", "src/idl_gen_text.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c5605a38..dee2c39a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_js.cpp src/idl_gen_php.cpp src/idl_gen_python.cpp + src/idl_gen_lobster.cpp src/idl_gen_lua.cpp src/idl_gen_fbs.cpp src/idl_gen_grpc.cpp diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index e7676bf8f..60494049c 100644 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -31,12 +31,18 @@ For any schema input files, one or more generators can be specified: - `--js`, `-s`: Generate JavaScript code. +- `--ts`: Generate TypeScript code. + - `--php`: Generate PHP code. - `--grpc`: Generate RPC stub code for GRPC. - `--dart`: Generate Dart code. +- `--lua`: Generate Lua code. + +- `--lobster`: Generate Lobster code. + For any data input files: - `--binary`, `-b` : If data is contained in this file, generate a diff --git a/docs/source/FlatBuffers.md b/docs/source/FlatBuffers.md index 351c38ede..98042214d 100644 --- a/docs/source/FlatBuffers.md +++ b/docs/source/FlatBuffers.md @@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index} # Overview {#flatbuffers_overview} [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 performance-critical applications. @@ -142,6 +142,8 @@ sections provide a more in-depth usage guide. own programs. - How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your 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. - Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of using FlatBuffers. diff --git a/docs/source/LobsterUsage.md b/docs/source/LobsterUsage.md new file mode 100644 index 000000000..9d69caf85 --- /dev/null +++ b/docs/source/LobsterUsage.md @@ -0,0 +1,85 @@ +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. + +
diff --git a/docs/source/Support.md b/docs/source/Support.md index d41a8dd8c..e4c66cd60 100644 --- a/docs/source/Support.md +++ b/docs/source/Support.md @@ -18,25 +18,25 @@ In general: NOTE: this table is a start, it needs to be extended. -Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby | Dart ------------------------------- | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ---- | ---- -Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP | Yes -JSON parsing | Yes | No | No | No | No | No | No | Yes | 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 -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: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ? | No -Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | ? -Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ? | Yes -Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ? | Yes -Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ? | Yes -Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ? | Flutter -Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter -Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | ? -Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw | dnfield - +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 | Yes | Yes +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 +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 +Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes +Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No +Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great +Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes +Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes +Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes +Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes +Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes +Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No +Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* + * aard = aardappel (previously: gwvo) * ev = evolutional * js = jonsimantov * mik = mikkelfj diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md index 11fe4c8c6..8cb1ab173 100644 --- a/docs/source/Tutorial.md +++ b/docs/source/Tutorial.md @@ -32,6 +32,7 @@ Please select your desired language for our quest: C Dart Lua + Lobster \endhtmlonly @@ -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)
-[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) +
+
+[sample_binary.lobster](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.lobster)
@@ -333,6 +337,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools. ./../flatc --lua monster.fbs ~~~ +
+~~~{.sh} + cd flatbuffers/sample + ./../flatc --lobster monster.fbs +~~~ +
For a more complete guide to using the `flatc` compiler, please read the [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. local weapon = require("MyGame.Sample.Weapon") ~~~ +
+~~~{.lobster} + include from "../lobster/" // Where to find flatbuffers.lobster + include "monster_generated.lobster" +~~~ +
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 @@ -548,6 +564,12 @@ which will grow automatically if needed: local builder = flatbuffers.Builder(1024) ~~~ +
+~~~{.lobster} + -- get access to the builder + let builder = flatbuffers_builder {} +~~~ +
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`. @@ -753,6 +775,19 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`. local axe = weapon.End(builder) ~~~ +
+~~~{.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() +~~~ +
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 @@ -915,6 +950,15 @@ traversal. This is generally easy to do on any tree structures. local inv = builder:EndVector(10) ~~~ +
+~~~{.lobster} + // Name of the monster. + let name = builder.CreateString("Orc") + + // Inventory. + let inv = builder.MyGame_Sample_MonsterCreateInventoryVector(map(10): _) +~~~ +
We serialized two built-in data types (`string` and `vector`) and captured their return values. These values are offsets into the serialized data, @@ -1037,6 +1081,11 @@ offsets. local weapons = builder:EndVector(2) ~~~ +
+~~~{.lobster} + let weapons = builder.MyGame_Sample_MonsterCreateWeaponsVector(weapon_offsets) +~~~ +

@@ -1146,6 +1195,14 @@ for the `path` field above: local path = builder:EndVector(2) ~~~
+
+~~~{.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) +~~~ +
We have now serialized the non-scalar components of the orc, so we can serialize the monster itself: @@ -1366,6 +1423,21 @@ can serialize the monster itself: local orc = monster.End(builder) ~~~ +
+~~~{.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() +~~~ +
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 @@ -1514,6 +1586,12 @@ Here is a repetition these lines, to help highlight them more clearly: monster.AddEquipped(builder, axe) -- Union data ~~~ +
+~~~{.lobster} + builder.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon) + builder.MyGame_Sample_MonsterAddEquipped(axe) +~~~ +
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 @@ -1591,7 +1669,12 @@ appropriate `finish` method. builder:Finish(orc) ~~~ - +
+~~~{.lobster} + // Call `Finish()` to instruct the builder that this monster is complete. + builder.Finish(orc) +~~~ +
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 @@ -1695,6 +1778,12 @@ like so: local bufAsString = builder:Output() ~~~ +
+~~~{.lobster} + // This must be called after `Finish()`. + let buf = builder.SizedCopy() // Of type `string`. +~~~ +
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. 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 -deserialize a FlatBuffer. +access a FlatBuffer. This section requires the same import/include, namespace, etc. requirements as before: @@ -1822,6 +1911,12 @@ import './monster_my_game.sample_generated.dart' as myGame; local weapon = require("MyGame.Sample.Weapon") ~~~ +
+~~~{.lobster} + include from "../lobster/" // Where to find flatbuffers.lobster + include "monster_generated.lobster" +~~~ +
Then, assuming you have a buffer of bytes received from disk, network, etc., you can create start accessing the buffer like so: @@ -1941,6 +2036,14 @@ myGame.Monster monster = new myGame.Monster(data); local mon = monster.GetRootAsMonster(buf, 0) ~~~ +
+~~~{.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) +~~~ +
If you look in the generated files from the schema compiler, you will see it generated accessors for all non-`deprecated` fields. For example: @@ -2026,6 +2129,13 @@ accessors for all non-`deprecated` fields. For example: local name = mon:Name() ~~~ +
+~~~{.lobster} + let hp = monster.hp + let mana = monster.mana + let name = monster.name +~~~ +
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`: local z = pos:Z() ~~~ - +
+~~~{.lobster} + let pos = monster.pos + let x = pos.x + let y = pos.y + let z = pos.z +~~~ +
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively. @@ -2206,6 +2323,12 @@ FlatBuffers `vector`. local thirdItem = mon:Inventory(3) -- Lua is 1-based ~~~ +
+~~~{.lobster} + let inv_len = monster.inventory_length + let third_item = monster.inventory(2) +~~~ +
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`: @@ -2294,6 +2417,13 @@ except your need to handle the result as a FlatBuffer `table`: local secondWeaponDamage = mon:Weapon(2):Damage() ~~~ +
+~~~{.lobster} + let weapons_length = monster.weapons_length + let second_weapon_name = monster.weapons(1).name + let second_weapon_damage = monster.weapons(1).damage +~~~ +
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. @@ -2442,6 +2572,19 @@ We can access the type to dynamically cast the data as needed (since the end ~~~ +
+~~~{.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 +~~~ +
## Mutating FlatBuffers @@ -2527,6 +2670,11 @@ mutators like so: ~~~ +
+~~~{.lobster} + +~~~ +
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 @@ -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 for `flatcc` to support this.* +
+*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.* +
## Advanced Features for Each Language @@ -2642,6 +2795,8 @@ For your chosen language, see:
[Use in Lua](@ref flatbuffers_guide_use_lua)
- +
+[Use in Lobster](@ref flatbuffers_guide_use_lobster) +

diff --git a/docs/source/doxyfile b/docs/source/doxyfile index 8cc46cc66..19a2ec943 100644 --- a/docs/source/doxyfile +++ b/docs/source/doxyfile @@ -759,6 +759,7 @@ INPUT = "FlatBuffers.md" \ "PHPUsage.md" \ "PythonUsage.md" \ "LuaUsage.md" \ + "LobsterUsage.md" \ "Support.md" \ "Benchmarks.md" \ "WhitePaper.md" \ diff --git a/docs/source/doxygen_layout.xml b/docs/source/doxygen_layout.xml index c00229563..3800932f1 100644 --- a/docs/source/doxygen_layout.xml +++ b/docs/source/doxygen_layout.xml @@ -43,6 +43,8 @@ title="Use in Dart"/> + diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 9d50a94e1..e544b0df8 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -409,6 +409,7 @@ struct IDLOptions { kJsonSchema = 1 << 10, kDart = 1 << 11, kLua = 1 << 12, + kLobster = 1 << 13, kMAX }; @@ -820,6 +821,12 @@ extern bool GeneratePython(const Parser &parser, const std::string &path, 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. // See idl_gen_lua.cpp. extern bool GenerateLua(const Parser &parser, diff --git a/lobster/flatbuffers.lobster b/lobster/flatbuffers.lobster new file mode 100644 index 000000000..09105e762 --- /dev/null +++ b/lobster/flatbuffers.lobster @@ -0,0 +1,278 @@ +// 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) + diff --git a/samples/monster_generated.lobster b/samples/monster_generated.lobster new file mode 100644 index 000000000..c1a319966 --- /dev/null +++ b/samples/monster_generated.lobster @@ -0,0 +1,115 @@ +// 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() + diff --git a/samples/monsterdata.json b/samples/monsterdata.json index 0db1d295f..fa60b350a 100644 --- a/samples/monsterdata.json +++ b/samples/monsterdata.json @@ -1,25 +1,24 @@ { pos: { - x: 1, - y: 2, - z: 3 + x: 1.0, + y: 2.0, + z: 3.0 }, hp: 300, name: "Orc", - weapons:[ + weapons: [ { name: "axe", - damage:100 + damage: 100 }, { name: "bow", - damage:90 + damage: 90 } ], equipped_type: "Weapon", - equipped: - { - name: "bow", - damage:90 - } + equipped: { + name: "bow", + damage: 90 + } } diff --git a/samples/sample_binary.lobster b/samples/sample_binary.lobster new file mode 100644 index 000000000..0434af064 --- /dev/null +++ b/samples/sample_binary.lobster @@ -0,0 +1,98 @@ +// 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!" diff --git a/samples/sample_text.lobster b/samples/sample_text.lobster new file mode 100644 index 000000000..9da4fa25e --- /dev/null +++ b/samples/sample_text.lobster @@ -0,0 +1,43 @@ +// 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 diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 09efe7955..2a3bc9808 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -71,6 +71,10 @@ int main(int argc, const char *argv[]) { flatbuffers::IDLOptions::kPython, "Generate Python files for tables/structs", 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::IDLOptions::kLua, "Generate Lua files for tables/structs", diff --git a/src/idl_gen_lobster.cpp b/src/idl_gen_lobster.cpp new file mode 100644 index 000000000..6f1ce5653 --- /dev/null +++ b/src/idl_gen_lobster.cpp @@ -0,0 +1,369 @@ +/* + * 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 +#include + +#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 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 diff --git a/tests/TestAll.sh b/tests/TestAll.sh index d2de3e903..d1fe4944e 100644 --- a/tests/TestAll.sh +++ b/tests/TestAll.sh @@ -40,6 +40,11 @@ echo "************************ Dart:" sh DartTest.sh +echo "************************ Lobster:" + +# TODO: test if available. +# lobster lobstertest.lobster + echo "************************ C:" echo "(in a different repo)" diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 26362255a..eaadc5ab9 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -15,13 +15,13 @@ set buildtype=Release 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 --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 --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 --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 -b --schema --bfbs-comments -I include_test monster_test.fbs ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs 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 ../tests \ No newline at end of file diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 32a59e837..8e060dbd7 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -14,11 +14,11 @@ # See the License for the specific language governing permissions and # 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 --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 --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 --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 -b --schema --bfbs-comments -I include_test monster_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs 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 diff --git a/tests/lobstertest.lobster b/tests/lobstertest.lobster new file mode 100644 index 000000000..e4f08087b --- /dev/null +++ b/tests/lobstertest.lobster @@ -0,0 +1,134 @@ +// 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 diff --git a/tests/monster_test_generated.lobster b/tests/monster_test_generated.lobster new file mode 100644 index 000000000..d20a1b222 --- /dev/null +++ b/tests/monster_test_generated.lobster @@ -0,0 +1,554 @@ +// 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() + diff --git a/tests/namespace_test/namespace_test1_generated.lobster b/tests/namespace_test/namespace_test1_generated.lobster new file mode 100644 index 000000000..7c1924f41 --- /dev/null +++ b/tests/namespace_test/namespace_test1_generated.lobster @@ -0,0 +1,40 @@ +// 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() + diff --git a/tests/namespace_test/namespace_test2_generated.lobster b/tests/namespace_test/namespace_test2_generated.lobster new file mode 100644 index 000000000..8b9809bc4 --- /dev/null +++ b/tests/namespace_test/namespace_test2_generated.lobster @@ -0,0 +1,76 @@ +// 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() +