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)
@@ -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)
~~~
+
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)
~~~
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)
~~~
+
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
~~~
+
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()
+