*.vcxproj.user
*.sln
*.suo
+*.opendb
*.keystore
+**/.vs/**
**/bin/**
**/gen/**
**/libs/**
**/CMakeTestfile.cmake
**/Debug/**
**/Release/**
+**/RelWithDebInfo/**
+**/x64/ #build artifacts from VS
build.xml
local.properties
project.properties
src/idl_gen_js.cpp
src/idl_gen_php.cpp
src/idl_gen_python.cpp
+ src/idl_gen_lua.cpp
src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp
src/idl_gen_json_schema.cpp
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
-serialization library for C++, C#, C, Go, Java, JavaScript, TypeScript, PHP, and Python.
+serialization library for C++, C#, C, Go, Java, JavaScript, Lua, TypeScript, PHP, and Python.
It was originally created at Google for game development and other
performance-critical applications.
in your own programs.
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
own programs.
+- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
+ own programs.
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
own programs.
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
--- /dev/null
+Use in Lua {#flatbuffers_guide_use_lua}
+=============
+
+## Before you get started
+
+Before diving into the FlatBuffers usage in Lua, 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 Lua). This
+page is designed to cover the nuances of FlatBuffers usage, specific to
+Lua.
+
+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 Lua library code location
+
+The code for the FlatBuffers Lua library can be found at
+`flatbuffers/lua`. You can browse the library code on the
+[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua).
+
+## Testing the FlatBuffers Lua library
+
+The code to test the Lua library can be found at `flatbuffers/tests`.
+The test code itself is located in [luatest.lua](https://github.com/google/
+flatbuffers/blob/master/tests/luatest.lua).
+
+To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/
+blob/master/tests/LuaTest.sh) shell script.
+
+*Note: This script requires [Lua 5.3](https://www.lua.org/) to be
+installed.*
+
+## Using the FlatBuffers Lua library
+
+*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
+example of how to use FlatBuffers in Lua.*
+
+There is support for both reading and writing FlatBuffers in Lua.
+
+To use FlatBuffers in your own code, first generate Lua classes from your
+schema with the `--lua` 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 Lua:
+First, require the module and the generated code. Then read a FlatBuffer binary
+file into a `string`, which you pass to the `GetRootAsMonster` function:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
+ -- require the library
+ local flatbuffers = require("flatbuffers")
+
+ -- require the generated code
+ local monster = require("MyGame.Sample.Monster")
+
+ -- read the flatbuffer from a file into a string
+ local f = io.open('monster.dat', 'rb')
+ local buf = f:read('*a')
+ f:close()
+
+ -- parse the flatbuffer to get an instance to the root monster
+ local monster1 = monster.GetRootAsMonster(buf, 0)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now you can access values like this:
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
+ -- use the : notation to access member data
+ local hp = monster1:Hp()
+ local pos = monster1:Pos()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+## Text Parsing
+
+There currently is no support for parsing text (Schema's and JSON) directly
+from Lua, though you could use the C++ parser through SWIG or ctypes. Please
+see the C++ documentation for more on text parsing.
+
+<br>
<input type="radio" name="language" value="php">PHP</input>
<input type="radio" name="language" value="c">C</input>
<input type="radio" name="language" value="dart">Dart</input>
+ <input type="radio" name="language" value="lua">Lua</input>
</form>
\endhtmlonly
<div class="language-dart">
[example.dart](https://github.com/google/flatbuffers/blob/master/dart/example/example.dart)
</div>
+<div class="language-lua">
+[sample_binary.lua](https://github.com/google/flatbuffers/blob/master/dart/example/sample_binary.lua)
+</div>
+
## Writing the Monsters' FlatBuffer Schema
./../flatc --dart monster.fbs
~~~
</div>
+<div class="language-lua">
+~~~{.sh}
+ cd flatbuffers/sample
+ ./../flatc --lua monster.fbs
+~~~
+</div>
For a more complete guide to using the `flatc` compiler, please read the
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
import 'monster_my_game.sample_generated.dart' as myGame;
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- require the flatbuffers module
+ local flatbuffers = require("flatbuffers")
+
+ -- require the generated files from `flatc`.
+ local color = require("MyGame.Sample.Color")
+ local equipment = require("MyGame.Sample.Equipment")
+ local monster = require("MyGame.Sample.Monster")
+ local vec3 = require("MyGame.Sample.Vec3")
+ local weapon = require("MyGame.Sample.Weapon")
+~~~
+</div>
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
var builder = new fb.Builder(initialSize: 1024);
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- get access to the builder, providing an array of size 1024
+ local builder = flatbuffers.Builder(1024)
+~~~
+</div>
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`.
);
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local weaponOne = builder:CreateString("Sword")
+ local weaponTwo = builder:CreateString("Axe")
+
+ -- Create the first 'Weapon'
+ weapon.Start(builder)
+ weapon.AddName(builder, weaponOne)
+ weapon.AddDamage(builder, 3)
+ local sword = weapon.End(builder)
+
+ -- Create the second 'Weapon'
+ weapon.Start(builder)
+ weapon.AddName(builder, weaponTwo)
+ weapon.AddDamage(builder, 5)
+ local axe = weapon.End(builder)
+~~~
+</div>
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
final List<int> treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
~~~
</div>
+<div class="language-lua">
+~~~{.py}
+ -- Serialize a name for our mosnter, called 'orc'
+ local name = builder:CreateString("Orc")
+
+ -- Create a `vector` representing the inventory of the Orc. Each number
+ -- could correspond to an item that can be claimed after he is slain.
+ -- Note: Since we prepend the bytes, this loop iterates in reverse.
+ monster.StartInventoryVector(builder, 10)
+ for i=10,1,-1 do
+ builder:PrependByte(i)
+ end
+ local inv = builder:EndVector(10)
+~~~
+</div>
We serialized two built-in data types (`string` and `vector`) and captured
their return values. These values are offsets into the serialized data,
final List<myGame.WeaponBuilder> weaps = [sword, axe];
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- Create a FlatBuffer vector and prepend the weapons.
+ -- Note: Since we prepend the data, prepend them in reverse order.
+ monster.StartWeaponsVector(builder, 2)
+ builder:PrependUOffsetTRelative(axe)
+ builder:PrependUOffsetTRelative(sword)
+ local weapons = builder:EndVector(2)
+~~~
+</div>
<div class="language-cpp">
<br>
];
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- Create a FlatBuffer vector and prepend the path locations.
+ -- Note: Since we prepend the data, prepend them in reverse order.
+ monster.StartPathVector(builder, 2)
+ vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
+ vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
+ local path = builder:EndVector(2)
+~~~
+</div>
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
final int orc = orcBuilder.finish(builder);
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- Create our monster by using Start() andEnd()
+ monster.Start(builder)
+ monster.AddPos(builder, vec3.CreateVec3(builder, 1.0, 2.0, 3.0))
+ monster.AddHp(builder, 300)
+ monster.AddName(builder, name)
+ monster.AddInventory(builder, inv)
+ monster.AddColor(builder, color.Red)
+ monster.AddWeapons(builder, weapons)
+ monster.AddEquippedType(builder, equipment.Weapon)
+ monster.AddEquipped(builder, axe)
+ monster.AddPath(builder, path)
+ local orc = monster.End(builder)
+~~~
+</div>
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
equipped: axe, // Union data
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ monster.AddEquippedType(builder, equipment.Weapon) -- Union type
+ monster.AddEquipped(builder, axe) -- Union data
+~~~
+</div>
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
// See the next code section, as in Dart `finish` will also return the byte array.
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- Call 'Finish()' to instruct the builder that this monster is complete.
+ builder:Finish(orc)
+~~~
+</div>
+
The buffer is now ready to be stored somewhere, sent over the network, be
compressed, or whatever you'd like to do with it. You can access the buffer
final Uint8List buf = builder.finish(orc);
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- Get the flatbuffer as a string containing the binary data
+ local bufAsString = builder:Output()
+~~~
+</div>
+
Now you can write the bytes to a file, send them over the network..
**Make sure your file mode (or tranfer protocol) is set to BINARY, not text.**
import './monster_my_game.sample_generated.dart' as myGame;
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ -- require the flatbuffers module
+ local flatbuffers = require("flatbuffers")
+
+ -- require the generated files from `flatc`.
+ local color = require("MyGame.Sample.Color")
+ local equipment = require("MyGame.Sample.Equipment")
+ local monster = require("MyGame.Sample.Monster")
+ local vec3 = require("MyGame.Sample.Vec3")
+ local weapon = require("MyGame.Sample.Weapon")
+~~~
+</div>
Then, assuming you have a buffer of bytes received from disk,
network, etc., you can create start accessing the buffer like so:
myGame.Monster monster = new myGame.Monster(data);
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local bufAsString = -- The data you just read in
+
+ -- Convert the string representation into binary array Lua structure
+ local buf = flatbuffers.binaryArray.New(bufAsString)
+
+ -- Get an accessor to the root object insert the buffer
+ local mon = monster.GetRootAsMonster(buf, 0)
+~~~
+</div>
If you look in the generated files from the schema compiler, you will see it generated
accessors for all non-`deprecated` fields. For example:
var name = monster.name;
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local hp = mon:Hp()
+ local mana = mon:Mana()
+ local name = mon:Name()
+~~~
+</div>
These should hold `300`, `150`, and `"Orc"` respectively.
double z = pos.z;
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local pos = mon:Pos()
+ local x = pos:X()
+ local y = pos:Y()
+ local z = pos:Z()
+~~~
+</div>
+
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
var thirdItem = monster.inventory[2];
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local invLength = mon:InventoryLength()
+ local thirdItem = mon:Inventory(3) -- Lua is 1-based
+~~~
+</div>
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`:
var secondWeaponDamage = monster.Weapons[1].damage;
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local weaponsLength = mon:WeaponsLength()
+ local secondWeaponName = mon:Weapon(2):Name()
+ local secondWeaponDamage = mon:Weapon(2):Damage()
+~~~
+</div>
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.
}
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ local unionType = mon:EquippedType()
+
+ if unionType == equipment.Weapon then
+ local unionWeapon = weapon.New()
+ unionWeapon:Init(mon:Equipped().bytes, mon:Equipped().pos)
+
+ local weaponName = unionWeapon:Name() -- 'Axe'
+ local weaponDamage = unionWeapon:Damage() -- 5
+ end
+~~~
+</div>
## Mutating FlatBuffers
<API for mutating FlatBuffers not yet available in Dart.>
~~~
</div>
+<div class="language-lua">
+~~~{.lua}
+ <API for mutating FlatBuffers is not yet available in Lua.>
+~~~
+</div>
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
<div class="language-dart">
[Use in Dart](@ref flatbuffers_guide_use_dart)
</div>
+<div class="language-lua">
+[Use in Lua](@ref flatbuffers_guide_use_lua)
+</div>
+
<br>
"TypeScriptUsage.md" \
"PHPUsage.md" \
"PythonUsage.md" \
+ "LuaUsage.md" \
"Support.md" \
"Benchmarks.md" \
"WhitePaper.md" \
title="Use in Python"/>
<tab type="user" url="@ref flatbuffers_guide_use_dart"
title="Use in Dart"/>
+ <tab type="user" url="@ref flatbuffers_guide_use_lua"
+ title="Use in Lua"/>
<tab type="user" url="@ref flexbuffers"
title="Schema-less version"/>
<tab type="usergroup" url="" title="gRPC">
kTs = 1 << 9,
kJsonSchema = 1 << 10,
kDart = 1 << 11,
+ kLua = 1 << 12,
kMAX
};
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,
+ const std::string &path,
+ const std::string &file_name);
+
// Generate Json schema file
// See idl_gen_json_schema.cpp.
extern bool GenerateJsonSchema(const Parser &parser,
--- /dev/null
+local m = {}
+
+m.Builder = require("flatbuffers.builder").New
+m.N = require("flatbuffers.numTypes")
+m.view = require("flatbuffers.view")
+m.binaryArray = require("flatbuffers.binaryarray")
+
+return m
\ No newline at end of file
--- /dev/null
+local m = {} -- the module table
+
+local mt = {} -- the module metatable
+
+-- given a binary array, set a metamethod to return its length
+-- (e.g., #binaryArray, calls this)
+function mt:__len()
+ return self.size
+end
+
+-- Create a new binary array of an initial size
+function m.New(sizeOrString)
+ -- the array storage itself
+ local o = {}
+
+ if type(sizeOrString) == "string" then
+ o.str = sizeOrString
+ o.size = #sizeOrString
+ elseif type(sizeOrString) == "number" then
+ o.data = {}
+ o.size = sizeOrString
+ else
+ error("Expect a integer size value or string to construct a binary array")
+ end
+ -- set the inheritance
+ setmetatable(o, {__index = mt, __len = mt.__len})
+ return o
+end
+
+-- Get a slice of the binary array from start to end position
+function mt:Slice(startPos, endPos)
+ startPos = startPos or 0
+ endPos = endPos or self.size
+ local d = self.data
+ if d then
+ -- if the self.data is defined, we are building the buffer
+ -- in a Lua table
+
+ -- new table to store the slice components
+ local b = {}
+
+ -- starting with the startPos, put all
+ -- values into the new table to be concat later
+ -- updated the startPos based on the size of the
+ -- value
+ while startPos < endPos do
+ local v = d[startPos] or '/0'
+ table.insert(b, v)
+ startPos = startPos + #v
+ end
+
+ -- combine the table of strings into one string
+ -- this is faster than doing a bunch of concats by themselves
+ return table.concat(b)
+ else
+ -- n.b start/endPos are 0-based incoming, so need to convert
+ -- correctly. in python a slice includes start -> end - 1
+ return self.str:sub(startPos+1, endPos)
+ end
+end
+
+-- Grow the binary array to a new size, placing the exisiting data
+-- at then end of the new array
+function mt:Grow(newsize)
+ -- the new table to store the data
+ local newT = {}
+
+ -- the offset to be applied to existing entries
+ local offset = newsize - self.size
+
+ -- loop over all the current entries and
+ -- add them to the new table at the correct
+ -- offset location
+ local d = self.data
+ for i,data in pairs(d) do
+ newT[i + offset] = data
+ end
+
+ -- update this storage with the new table and size
+ self.data = newT
+ self.size = newsize
+end
+
+-- memorization for padding strings
+local pads = {}
+
+-- pad the binary with n \0 bytes at the starting position
+function mt:Pad(n, startPos)
+ -- use memorization to avoid creating a bunch of strings
+ -- all the time
+ local s = pads[n]
+ if not s then
+ s = string.rep('\0', n)
+ pads[n] = s
+ end
+
+ -- store the padding string at the start position in the
+ -- Lua table
+ self.data[startPos] = s
+end
+
+-- Sets the binary array value at the specified position
+function mt:Set(value, position)
+ self.data[position] = value
+end
+
+-- locals for slightly faster access
+local sunpack = string.unpack
+local spack = string.pack
+
+-- Pack the data into a binary representation
+function m.Pack(fmt, ...)
+ return spack(fmt, ...)
+end
+
+-- Unpack the data from a binary representation in
+-- a Lua value
+function m.Unpack(fmt, s, pos)
+ return sunpack(fmt, s.str, pos + 1)
+end
+
+-- Return the binary array module
+return m
\ No newline at end of file
--- /dev/null
+local N = require("flatbuffers.numTypes")
+local ba = require("flatbuffers.binaryarray")
+local compat = require("flatbuffers.compat")
+
+local m = {}
+
+local mt = {}
+
+-- get locals for faster access
+local VOffsetT = N.VOffsetT
+local UOffsetT = N.UOffsetT
+local SOffsetT = N.SOffsetT
+local Bool = N.Bool
+local Uint8 = N.Uint8
+local Uint16 = N.Uint16
+local Uint32 = N.Uint32
+local Uint64 = N.Uint64
+local Int8 = N.Int8
+local Int16 = N.Int16
+local Int32 = N.Int32
+local Int64 = N.Int64
+local Float32 = N.Float32
+local Float64 = N.Float64
+
+local MAX_BUFFER_SIZE = 0x80000000 -- 2 GB
+local VtableMetadataFields = 2
+
+local getAlignSize = compat.GetAlignSize
+
+local function vtableEqual(a, objectStart, b)
+ UOffsetT:EnforceNumber(objectStart)
+ if (#a * VOffsetT.bytewidth) ~= #b then
+ return false
+ end
+
+ for i, elem in ipairs(a) do
+ local x = VOffsetT:Unpack(b, i * VOffsetT.bytewidth)
+ if x ~= 0 or elem ~= 0 then
+ local y = objectStart - elem
+ if x ~= y then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+function m.New(initialSize)
+ assert(0 <= initialSize and initialSize < MAX_BUFFER_SIZE)
+ local o =
+ {
+ finished = false,
+ bytes = ba.New(initialSize),
+ nested = false,
+ head = initialSize,
+ minalign = 1,
+ vtables = {}
+ }
+ setmetatable(o, {__index = mt})
+ return o
+end
+
+function mt:Output(full)
+ assert(self.finished, "Builder Not Finished")
+ if full then
+ return self.bytes:Slice()
+ else
+ return self.bytes:Slice(self.head)
+ end
+end
+
+function mt:StartObject(numFields)
+ assert(not self.nested)
+
+ local vtable = {}
+
+ for _=1,numFields do
+ table.insert(vtable, 0)
+ end
+
+ self.currentVTable = vtable
+ self.objectEnd = self:Offset()
+ self.minalign = 1
+ self.nested = true
+end
+
+function mt:WriteVtable()
+ self:PrependSOffsetTRelative(0)
+ local objectOffset = self:Offset()
+
+ local exisitingVTable
+ local i = #self.vtables
+ while i >= 1 do
+ if self.vtables[i] == 0 then
+ table.remove(self.vtables,i)
+ end
+ i = i - 1
+ end
+
+ while i >= 1 do
+
+ local vt2Offset = self.vtables[i]
+ local vt2Start = #self.bytes - vt2Offset
+ local vt2len = VOffsetT:Unpack(self.bytes, vt2Start)
+
+ local metadata = VtableMetadataFields * VOffsetT.bytewidth
+ local vt2End = vt2Start + vt2Len
+ local vt2 = self.bytes:Slice(vt2Start+metadata,vt2End)
+
+ if vtableEqual(self.currentVTable, objectOffset, vt2) then
+ exisitingVTable = vt2Offset
+ break
+ end
+
+ i = i - 1
+ end
+
+ if not exisitingVTable then
+ i = #self.currentVTable
+ while i >= 1 do
+ local off = 0
+ local a = self.currentVTable[i]
+ if a and a ~= 0 then
+ off = objectOffset - a
+ end
+ self:PrependVOffsetT(off)
+
+ i = i - 1
+ end
+
+ local objectSize = objectOffset - self.objectEnd
+ self:PrependVOffsetT(objectSize)
+
+ local vBytes = #self.currentVTable + VtableMetadataFields
+ vBytes = vBytes * VOffsetT.bytewidth
+ self:PrependVOffsetT(vBytes)
+
+ local objectStart = #self.bytes - objectOffset
+ self.bytes:Set(SOffsetT:Pack(self:Offset() - objectOffset),objectStart)
+
+ table.insert(self.vtables, self:Offset())
+ else
+ local objectStart = #self.bytes - objectOffset
+ self.head = objectStart
+ self.bytes:Set(SOffsetT:Pack(exisitingVTable - objectOffset),self.head)
+ end
+
+ self.currentVTable = nil
+ return objectOffset
+end
+
+function mt:EndObject()
+ assert(self.nested)
+ self.nested = false
+ return self:WriteVtable()
+end
+
+local function growByteBuffer(self, desiredSize)
+ local s = #self.bytes
+ assert(s < MAX_BUFFER_SIZE, "Flat Buffers cannot grow buffer beyond 2 gigabytes")
+ local newsize = s
+ repeat
+ newsize = math.min(newsize * 2, MAX_BUFFER_SIZE)
+ if newsize == 0 then newsize = 1 end
+ until newsize > desiredSize
+
+ self.bytes:Grow(newsize)
+end
+
+function mt:Head()
+ return self.head
+end
+
+function mt:Offset()
+ return #self.bytes - self.head
+end
+
+function mt:Pad(n)
+ if n > 0 then
+ -- pads are 8-bit, so skip the bytewidth lookup
+ local h = self.head - n -- UInt8
+ self.head = h
+ self.bytes:Pad(n, h)
+ end
+end
+
+function mt:Prep(size, additionalBytes)
+ if size > self.minalign then
+ self.minalign = size
+ end
+
+ local h = self.head
+
+ local k = #self.bytes - h + additionalBytes
+ local alignsize = ((~k) + 1) & (size - 1) -- getAlignSize(k, size)
+
+ local desiredSize = alignsize + size + additionalBytes
+
+ while self.head < desiredSize do
+ local oldBufSize = #self.bytes
+ growByteBuffer(self, desiredSize)
+ local updatedHead = self.head + #self.bytes - oldBufSize
+ self.head = updatedHead
+ end
+
+ self:Pad(alignsize)
+end
+
+function mt:PrependSOffsetTRelative(off)
+ self:Prep(SOffsetT.bytewidth, 0)
+ assert(off <= self:Offset(), "Offset arithmetic error")
+ local off2 = self:Offset() - off + SOffsetT.bytewidth
+ self:Place(off2, SOffsetT)
+end
+
+function mt:PrependUOffsetTRelative(off)
+ self:Prep(UOffsetT.bytewidth, 0)
+ local soffset = self:Offset()
+ if off <= soffset then
+ local off2 = soffset - off + UOffsetT.bytewidth
+ self:Place(off2, UOffsetT)
+ else
+ error("Offset arithmetic error")
+ end
+end
+
+function mt:StartVector(elemSize, numElements, alignment)
+ assert(not self.nested)
+ self.nested = true
+ self:Prep(Uint32.bytewidth, elemSize * numElements)
+ self:Prep(alignment, elemSize * numElements)
+ return self:Offset()
+end
+
+function mt:EndVector(vectorNumElements)
+ assert(self.nested)
+ self.nested = false
+ self:Place(vectorNumElements, UOffsetT)
+ return self:Offset()
+end
+
+function mt:CreateString(s)
+ assert(not self.nested)
+ self.nested = true
+
+ assert(type(s) == "string")
+
+ self:Prep(UOffsetT.bytewidth, (#s + 1)*Uint8.bytewidth)
+ self:Place(0, Uint8)
+
+ local l = #s
+ self.head = self.head - l
+
+ self.bytes:Set(s, self.head, self.head + l)
+
+ return self:EndVector(#s)
+end
+
+function mt:CreateByteVector(x)
+ assert(not self.nested)
+ self.nested = true
+ self:Prep(UOffsetT.bytewidth, #x*Uint8.bytewidth)
+
+ local l = #x
+ self.head = self.head - l
+
+ self.bytes:Set(x, self.head, self.head + l)
+
+ return self:EndVector(#x)
+end
+
+function mt:Slot(slotnum)
+ assert(self.nested)
+ -- n.b. slot number is 0-based
+ self.currentVTable[slotnum + 1] = self:Offset()
+end
+
+local function finish(self, rootTable, sizePrefix)
+ UOffsetT:EnforceNumber(rootTable)
+ local prepSize = UOffsetT.bytewidth
+ if sizePrefix then
+ prepSize = prepSize + Int32.bytewidth
+ end
+
+ self:Prep(self.minalign, prepSize)
+ self:PrependUOffsetTRelative(rootTable)
+ if sizePrefix then
+ local size = #self.bytes - self.head
+ Int32:EnforceNumber(size)
+ self:PrependInt32(size)
+ end
+ self.finished = true
+ return self.head
+end
+
+function mt:Finish(rootTable)
+ return finish(self, rootTable, false)
+end
+
+function mt:FinishSizePrefixed(rootTable)
+ return finish(self, rootTable, true)
+end
+
+function mt:Prepend(flags, off)
+ self:Prep(flags.bytewidth, 0)
+ self:Place(off, flags)
+end
+
+function mt:PrependSlot(flags, o, x, d)
+ flags:EnforceNumber(x)
+ flags:EnforceNumber(d)
+ if x ~= d then
+ self:Prepend(flags, x)
+ self:Slot(o)
+ end
+end
+
+function mt:PrependBoolSlot(...) self:PrependSlot(Bool, ...) end
+function mt:PrependByteSlot(...) self:PrependSlot(Uint8, ...) end
+function mt:PrependUint8Slot(...) self:PrependSlot(Uint8, ...) end
+function mt:PrependUint16Slot(...) self:PrependSlot(Uint16, ...) end
+function mt:PrependUint32Slot(...) self:PrependSlot(Uint32, ...) end
+function mt:PrependUint64Slot(...) self:PrependSlot(Uint64, ...) end
+function mt:PrependInt8Slot(...) self:PrependSlot(Int8, ...) end
+function mt:PrependInt16Slot(...) self:PrependSlot(Int16, ...) end
+function mt:PrependInt32Slot(...) self:PrependSlot(Int32, ...) end
+function mt:PrependInt64Slot(...) self:PrependSlot(Int64, ...) end
+function mt:PrependFloat32Slot(...) self:PrependSlot(Float32, ...) end
+function mt:PrependFloat64Slot(...) self:PrependSlot(Float64, ...) end
+
+function mt:PrependUOffsetTRelativeSlot(o,x,d)
+ if x~=d then
+ self:PrependUOffsetTRelative(x)
+ self:Slot(o)
+ end
+end
+
+function mt:PrependStructSlot(v,x,d)
+ UOffsetT:EnforceNumber(d)
+ if x~=d then
+ UOffsetT:EnforceNumber(x)
+ assert(x == self:Offset(), "Tried to write a Struct at an Offset that is different from the current Offset of the Builder.")
+ self:Slot(v)
+ end
+end
+
+function mt:PrependBool(x) self:Prepend(Bool, x) end
+function mt:PrependByte(x) self:Prepend(Uint8, x) end
+function mt:PrependUint8(x) self:Prepend(Uint8, x) end
+function mt:PrependUint16(x) self:Prepend(Uint16, x) end
+function mt:PrependUint32(x) self:Prepend(Uint32, x) end
+function mt:PrependUint64(x) self:Prepend(Uint64, x) end
+function mt:PrependInt8(x) self:Prepend(Int8, x) end
+function mt:PrependInt16(x) self:Prepend(Int16, x) end
+function mt:PrependInt32(x) self:Prepend(Int32, x) end
+function mt:PrependInt64(x) self:Prepend(Int64, x) end
+function mt:PrependFloat32(x) self:Prepend(Float32, x) end
+function mt:PrependFloat64(x) self:Prepend(Float64, x) end
+function mt:PrependVOffsetT(x) self:Prepend(VOffsetT, x) end
+
+function mt:Place(x, flags)
+ local d = flags:EnforceNumberAndPack(x)
+ local h = self.head - flags.bytewidth
+ self.head = h
+ self.bytes:Set(d, h)
+end
+
+return m
\ No newline at end of file
--- /dev/null
+local m = {}
+
+local getAlignSize
+if _VERSION == "Lua 5.3" then
+ getAlignSize = function(k, size)
+ return ((~k) + 1) & (size - 1)
+ end
+else
+ getAlignSize = function(self, size, additionalBytes)
+ local alignsize = bit32.bnot(#self.bytes-self:Head() + additionalBytes) + 1
+ return bit32.band(alignsize,(size - 1))
+ end
+end
+
+m.GetAlignSize = getAlignSize
+
+return m
\ No newline at end of file
--- /dev/null
+local m = {}
+
+local ba = require("flatbuffers.binaryarray")
+
+local bpack = ba.Pack
+local bunpack = ba.Unpack
+
+local type_mt = {}
+
+function type_mt:Pack(value)
+ return bpack(self.packFmt, value)
+end
+
+function type_mt:Unpack(buf, pos)
+ return bunpack(self.packFmt, buf, pos)
+end
+
+function type_mt:ValidNumber(n)
+ if not self.min_value and not self.max_value then return true end
+ return self.min_value <= n and n <= self.max_value
+end
+
+function type_mt:EnforceNumber(n)
+ -- duplicate code since the overhead of function calls
+ -- for such a popular method is time consuming
+ if not self.min_value and not self.max_value then
+ return
+ end
+
+ if self.min_value <= n and n <= self.max_value then
+ return
+ end
+
+ error("Number is not in the valid range")
+end
+
+function type_mt:EnforceNumberAndPack(n)
+ return bpack(self.packFmt, n)
+end
+
+function type_mt:ConvertType(n, otherType)
+ assert(self.bytewidth == otherType.bytewidth, "Cannot convert between types of different widths")
+ if self == otherType then
+ return n
+ end
+ return otherType:Unpack(self:Pack(n))
+end
+
+local bool_mt =
+{
+ bytewidth = 1,
+ min_value = false,
+ max_value = true,
+ lua_type = type(true),
+ name = "bool",
+ packFmt = "<b"
+}
+
+local uint8_mt =
+{
+ bytewidth = 1,
+ min_value = 0,
+ max_value = 2^8-1,
+ lua_type = type(1),
+ name = "uint8",
+ packFmt = "<I1"
+}
+
+local uint16_mt =
+{
+ bytewidth = 2,
+ min_value = 0,
+ max_value = 2^16-1,
+ lua_type = type(1),
+ name = "uint16",
+ packFmt = "<I2"
+}
+
+local uint32_mt =
+{
+ bytewidth = 4,
+ min_value = 0,
+ max_value = 2^32-1,
+ lua_type = type(1),
+ name = "uint32",
+ packFmt = "<I4"
+}
+
+local uint64_mt =
+{
+ bytewidth = 8,
+ min_value = 0,
+ max_value = 2^64-1,
+ lua_type = type(1),
+ name = "uint64",
+ packFmt = "<I8"
+}
+
+local int8_mt =
+{
+ bytewidth = 1,
+ min_value = -2^7,
+ max_value = 2^7-1,
+ lua_type = type(1),
+ name = "int8",
+ packFmt = "<i1"
+}
+
+local int16_mt =
+{
+ bytewidth = 2,
+ min_value = -2^15,
+ max_value = 2^15-1,
+ lua_type = type(1),
+ name = "int16",
+ packFmt = "<i2"
+}
+
+local int32_mt =
+{
+ bytewidth = 4,
+ min_value = -2^15,
+ max_value = 2^15-1,
+ lua_type = type(1),
+ name = "int32",
+ packFmt = "<i4"
+}
+
+local int64_mt =
+{
+ bytewidth = 8,
+ min_value = -2^63,
+ max_value = 2^63-1,
+ lua_type = type(1),
+ name = "int64",
+ packFmt = "<i8"
+}
+
+local float32_mt =
+{
+ bytewidth = 4,
+ min_value = nil,
+ max_value = nil,
+ lua_type = type(1.0),
+ name = "float32",
+ packFmt = "<f"
+}
+
+local float64_mt =
+{
+ bytewidth = 8,
+ min_value = nil,
+ max_value = nil,
+ lua_type = type(1.0),
+ name = "float64",
+ packFmt = "<d"
+}
+
+-- register the base class
+setmetatable(bool_mt, {__index = type_mt})
+setmetatable(uint8_mt, {__index = type_mt})
+setmetatable(uint16_mt, {__index = type_mt})
+setmetatable(uint32_mt, {__index = type_mt})
+setmetatable(uint64_mt, {__index = type_mt})
+setmetatable(int8_mt, {__index = type_mt})
+setmetatable(int16_mt, {__index = type_mt})
+setmetatable(int32_mt, {__index = type_mt})
+setmetatable(int64_mt, {__index = type_mt})
+setmetatable(float32_mt, {__index = type_mt})
+setmetatable(float64_mt, {__index = type_mt})
+
+
+m.Bool = bool_mt
+m.Uint8 = uint8_mt
+m.Uint16 = uint16_mt
+m.Uint32 = uint32_mt
+m.Uint64 = uint64_mt
+m.Int8 = int8_mt
+m.Int16 = int16_mt
+m.Int32 = int32_mt
+m.Int64 = int64_mt
+m.Float32 = float32_mt
+m.Float64 = float64_mt
+
+m.UOffsetT = uint32_mt
+m.VOffsetT = uint16_mt
+m.SOffsetT = int32_mt
+
+function GenerateTypes(listOfTypes)
+ for _,t in pairs(listOfTypes) do
+ t.Pack = function(self, value) return bpack(self.packFmt, value) end
+ t.Unpack = function(self, buf, pos) return bunpack(self.packFmt, buf, pos) end
+ end
+end
+
+GenerateTypes(m)
+
+return m
\ No newline at end of file
--- /dev/null
+local m = {}
+local mt = {}
+
+local mt_name = "flatbuffers.view.mt"
+
+local N = require("flatbuffers.numTypes")
+local binaryarray = require("flatbuffers.binaryarray")
+
+function m.New(buf, pos)
+ N.UOffsetT:EnforceNumber(pos)
+
+ -- need to convert from a string buffer into
+ -- a binary array
+
+ local o = {
+ bytes = type(buf) == "string" and binaryarray.New(buf) or buf,
+ pos = pos
+ }
+ setmetatable(o, {__index = mt, __metatable = mt_name})
+ return o
+end
+
+function mt:Offset(vtableOffset)
+ local vtable = self.pos - self:Get(N.SOffsetT, self.pos)
+ local vtableEnd = self:Get(N.VOffsetT, vtable)
+ if vtableOffset < vtableEnd then
+ return self:Get(N.VOffsetT, vtable + vtableOffset)
+ end
+ return 0
+end
+
+function mt:Indirect(off)
+ N.UOffsetT:EnforceNumber(off)
+ return off + N.UOffsetT:Unpack(self.bytes, off)
+end
+
+function mt:String(off)
+ N.UOffsetT:EnforceNumber(off)
+ off = off + N.UOffsetT:Unpack(self.bytes, off)
+ local start = off + N.UOffsetT.bytewidth
+ local length = N.UOffsetT:Unpack(self.bytes, off)
+ return self.bytes:Slice(start, start+length)
+end
+
+function mt:VectorLen(off)
+ N.UOffsetT:EnforceNumber(off)
+ off = off + self.pos
+ off = off + N.UOffsetT:Unpack(self.bytes, off)
+ return N.UOffsetT:Unpack(self.bytes, off)
+end
+
+function mt:Vector(off)
+ N.UOffsetT:EnforceNumber(off)
+
+ off = off + self.pos
+ local x = off + self:Get(N.UOffsetT, off)
+ x = x + N.UOffsetT.bytewidth
+ return x
+end
+
+function mt:Union(t2, off)
+ assert(getmetatable(t2) == mt_name)
+ N.UOffsetT:EnforceNumber(off)
+
+ off = off + self.pos
+ t2.pos = off + self:Get(N.UOffsetT, off)
+ t2.bytes = self.bytes
+end
+
+function mt:Get(flags, off)
+ N.UOffsetT:EnforceNumber(off)
+ return flags:Unpack(self.bytes, off)
+end
+
+function mt:GetSlot(slot, d, validatorFlags)
+ N.VOffsetT:EnforceNumber(slot)
+ if validatorFlags then
+ validatorFlags:EnforceNumber(d)
+ end
+ local off = self:Offset(slot)
+ if off == 0 then
+ return d
+ end
+ return self:Get(validatorFlags, self.pos + off)
+end
+
+function mt:GetVOffsetTSlot(slot, d)
+ N.VOffsetT:EnforceNumber(slot)
+ N.VOffsetT:EnforceNumber(d)
+ local off = self:Offset(slot)
+ if off == 0 then
+ return d
+ end
+ return off
+end
+
+return m
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Sample
+
+local Color = {
+ Red = 0,
+ Green = 1,
+ Blue = 2,
+}
+
+return Color -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Sample
+
+local Equipment = {
+ NONE = 0,
+ Weapon = 1,
+}
+
+return Equipment -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Sample
+
+local flatbuffers = require('flatbuffers')
+
+local Monster = {} -- the module
+local Monster_mt = {} -- the class metatable
+
+function Monster.New()
+ local o = {}
+ setmetatable(o, {__index = Monster_mt})
+ return o
+end
+function Monster.GetRootAsMonster(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Monster.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Monster_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Monster_mt:Pos()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ local x = o + self.view.pos
+ local obj = require('MyGame.Sample.Vec3').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Mana()
+ local o = self.view:Offset(6)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 150
+end
+function Monster_mt:Hp()
+ local o = self.view:Offset(8)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 100
+end
+function Monster_mt:Name()
+ local o = self.view:Offset(10)
+ if o ~= 0 then
+ return self.view:String(o + self.view.pos)
+ end
+end
+function Monster_mt:Inventory(j)
+ local o = self.view:Offset(14)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
+ end
+ return 0
+end
+function Monster_mt:InventoryLength()
+ local o = self.view:Offset(14)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Color()
+ local o = self.view:Offset(16)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int8, o + self.view.pos)
+ end
+ return 2
+end
+function Monster_mt:Weapons(j)
+ local o = self.view:Offset(18)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ x = self.view:Indirect(x)
+ local obj = require('MyGame.Sample.Weapon').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:WeaponsLength()
+ local o = self.view:Offset(18)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:EquippedType()
+ local o = self.view:Offset(20)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint8, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Equipped()
+ local o = self.view:Offset(22)
+ if o ~= 0 then
+ local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)
+ self.view:Union(obj, o)
+ return obj
+ end
+end
+function Monster.Start(builder) builder:StartObject(10) end
+function Monster.AddPos(builder, pos) builder:PrependStructSlot(0, pos, 0) end
+function Monster.AddMana(builder, mana) builder:PrependInt16Slot(1, mana, 150) end
+function Monster.AddHp(builder, hp) builder:PrependInt16Slot(2, hp, 100) end
+function Monster.AddName(builder, name) builder:PrependUOffsetTRelativeSlot(3, name, 0) end
+function Monster.AddInventory(builder, inventory) builder:PrependUOffsetTRelativeSlot(5, inventory, 0) end
+function Monster.StartInventoryVector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function Monster.AddColor(builder, color) builder:PrependInt8Slot(6, color, 2) end
+function Monster.AddWeapons(builder, weapons) builder:PrependUOffsetTRelativeSlot(7, weapons, 0) end
+function Monster.StartWeaponsVector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddEquippedType(builder, equippedType) builder:PrependUint8Slot(8, equippedType, 0) end
+function Monster.AddEquipped(builder, equipped) builder:PrependUOffsetTRelativeSlot(9, equipped, 0) end
+function Monster.End(builder) return builder:EndObject() end
+
+return Monster -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Sample
+
+local flatbuffers = require('flatbuffers')
+
+local Vec3 = {} -- the module
+local Vec3_mt = {} -- the class metatable
+
+function Vec3.New()
+ local o = {}
+ setmetatable(o, {__index = Vec3_mt})
+ return o
+end
+function Vec3_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Vec3_mt:X()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 0)
+end
+function Vec3_mt:Y()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 4)
+end
+function Vec3_mt:Z()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 8)
+end
+function Vec3.CreateVec3(builder, x, y, z)
+ builder:Prep(4, 12)
+ builder:PrependFloat32(z)
+ builder:PrependFloat32(y)
+ builder:PrependFloat32(x)
+ return builder:Offset()
+end
+
+return Vec3 -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Sample
+
+local flatbuffers = require('flatbuffers')
+
+local Weapon = {} -- the module
+local Weapon_mt = {} -- the class metatable
+
+function Weapon.New()
+ local o = {}
+ setmetatable(o, {__index = Weapon_mt})
+ return o
+end
+function Weapon.GetRootAsWeapon(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Weapon.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Weapon_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Weapon_mt:Name()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ return self.view:String(o + self.view.pos)
+ end
+end
+function Weapon_mt:Damage()
+ local o = self.view:Offset(6)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 0
+end
+function Weapon.Start(builder) builder:StartObject(2) end
+function Weapon.AddName(builder, name) builder:PrependUOffsetTRelativeSlot(0, name, 0) end
+function Weapon.AddDamage(builder, damage) builder:PrependInt16Slot(1, damage, 0) end
+function Weapon.End(builder) return builder:EndObject() end
+
+return Weapon -- return the module
\ No newline at end of file
--- /dev/null
+-- need to update the Lua path to point to the local flatbuffers implementation
+package.path = string.format("../lua/?.lua;%s",package.path)
+package.path = string.format("./lua/?.lua;%s",package.path)
+
+-- require the library
+local flatbuffers = require("flatbuffers")
+
+local binaryArray = flatbuffers.binaryArray-- for hex dump utility
+
+-- require the files generated from the schema
+local weapon = require("MyGame.Sample.Weapon")
+local monster = require("MyGame.Sample.Monster")
+local vec3 = require("MyGame.Sample.Vec3")
+local color = require("MyGame.Sample.Color")
+local equipment = require("MyGame.Sample.Equipment")
+
+-- get access to the builder, providing an array of size 1024
+local builder = flatbuffers.Builder(1024)
+
+local weaponOne = builder:CreateString("Sword")
+local weaponTwo = builder:CreateString("Axe")
+
+-- Create the first 'Weapon'
+weapon.Start(builder)
+weapon.AddName(builder, weaponOne)
+weapon.AddDamage(builder, 3)
+local sword = weapon.End(builder)
+
+-- Create the second 'Weapon'
+weapon.Start(builder)
+weapon.AddName(builder, weaponTwo)
+weapon.AddDamage(builder, 5)
+local axe = weapon.End(builder)
+
+-- Serialize a name for our mosnter, called 'orc'
+local name = builder:CreateString("Orc")
+
+-- Create a `vector` representing the inventory of the Orc. Each number
+-- could correspond to an item that can be claimed after he is slain.
+-- Note: Since we prepend the bytes, this loop iterates in reverse.
+monster.StartInventoryVector(builder, 10)
+for i=10,1,-1 do
+ builder:PrependByte(i)
+end
+local inv = builder:EndVector(10)
+
+-- Create a FlatBuffer vector and prepend the weapons.
+-- Note: Since we prepend the data, prepend them in reverse order.
+monster.StartWeaponsVector(builder, 2)
+builder:PrependUOffsetTRelative(axe)
+builder:PrependUOffsetTRelative(sword)
+local weapons = builder:EndVector(2)
+
+-- Create our monster by using Start() andEnd()
+monster.Start(builder)
+monster.AddPos(builder, vec3.CreateVec3(builder, 1.0, 2.0, 3.0))
+monster.AddHp(builder, 300)
+monster.AddName(builder, name)
+monster.AddInventory(builder, inv)
+monster.AddColor(builder, color.Red)
+monster.AddWeapons(builder, weapons)
+monster.AddEquippedType(builder, equipment.Weapon)
+monster.AddEquipped(builder, axe)
+local orc = monster.End(builder)
+
+-- Call 'Finish()' to instruct the builder that this monster is complete.
+builder:Finish(orc)
+
+-- Get the flatbuffer as a string containing the binary data
+local bufAsString = builder:Output()
+
+-- Convert the string representation into binary array Lua structure
+local buf = flatbuffers.binaryArray.New(bufAsString)
+
+-- Get an accessor to the root object insert the buffer
+local mon = monster.GetRootAsMonster(buf, 0)
+
+assert(mon:Mana() == 150)
+assert(mon:Hp() == 300)
+assert(mon:Name() == "Orc")
+assert(mon:Color() == color.Red)
+assert(mon:Pos():X() == 1.0)
+assert(mon:Pos():Y() == 2.0)
+assert(mon:Pos():Z() == 3.0)
+
+for i=1,mon:InventoryLength() do
+ assert(mon:Inventory(i) == i)
+end
+
+local expected = {
+ {w = 'Sword', d = 3},
+ {w = 'Axe', d = 5}
+}
+
+for i=1,mon:WeaponsLength() do
+ assert(mon:Weapons(i):Name() == expected[i].w)
+ assert(mon:Weapons(i):Damage() == expected[i].d)
+end
+
+assert(mon:EquippedType() == equipment.Weapon)
+
+local unionWeapon = weapon.New()
+unionWeapon:Init(mon:Equipped().bytes,mon:Equipped().pos)
+assert(unionWeapon:Name() == "Axe")
+assert(unionWeapon:Damage() == 5)
+
+print("The Lua FlatBuffer example was successfully created and verified!")
\ No newline at end of file
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
+ { flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr,
+ flatbuffers::IDLOptions::kLua,
+ "Generate Lua files for tables/structs",
+ flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, nullptr,
flatbuffers::IDLOptions::kPhp, "Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
--- /dev/null
+/*
+ * Copyright 2014 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.
+ */
+
+ // independent from idl_parser, since this code is not needed for most clients
+
+#include <string>
+
+#include "flatbuffers/code_generators.h"
+#include "flatbuffers/flatbuffers.h"
+#include "flatbuffers/idl.h"
+#include "flatbuffers/util.h"
+
+#include <unordered_set>
+
+namespace flatbuffers {
+namespace lua {
+
+ // Hardcode spaces per indentation.
+ const char * Indent = " ";
+ const char * Comment = "-- ";
+ const char * End = "end\n";
+ const char * EndFunc = "end\n";
+ const char * SelfData = "self.view";
+ const char * SelfDataPos = "self.view.pos";
+ const char * SelfDataBytes = "self.view.bytes";
+
+ class LuaGenerator : public BaseGenerator {
+ public:
+ LuaGenerator(const Parser &parser, const std::string &path,
+ const std::string &file_name)
+ : BaseGenerator(parser, path, file_name, "" /* not used */,
+ "" /* not used */) {
+ static const char * const keywords[] = {
+ "and",
+ "break",
+ "do",
+ "else",
+ "elseif",
+ "end",
+ "false",
+ "for",
+ "function",
+ "goto",
+ "if",
+ "in",
+ "local",
+ "nil",
+ "not",
+ "or",
+ "repeat",
+ "return",
+ "then",
+ "true",
+ "until",
+ "while"
+ };
+ keywords_.insert(std::begin(keywords), std::end(keywords));
+ }
+
+ // Most field accessors need to retrieve and test the field offset first,
+ // this is the prefix code for that.
+ std::string OffsetPrefix(const FieldDef &field) {
+ return std::string(Indent) +
+ "local o = " + SelfData + ":Offset(" + NumToString(field.value.offset) + ")\n" +
+ Indent + "if o ~= 0 then\n";
+ }
+
+ // Begin a class declaration.
+ void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "local " + NormalizedName(struct_def) + " = {} -- the module\n";
+ code += "local " + NormalizedMetaName(struct_def) + " = {} -- the class metatable\n";
+ code += "\n";
+ }
+
+ // Begin enum code with a class declaration.
+ void BeginEnum(const std::string class_name, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "local " + class_name + " = {\n";
+ }
+
+ 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 NormalizedMetaName(const Definition &definition) const {
+ return EscapeKeyword(definition.name) + "_mt";
+ }
+
+ // A single enum member.
+ void EnumMember(const EnumVal ev, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Indent) + NormalizedName(ev) + " = " + NumToString(ev.value) + ",\n";
+ }
+
+ // End enum code.
+ void EndEnum(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "}\n";
+ }
+
+ void GenerateNewObjectPrototype(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".New()\n";
+ code += std::string(Indent) + "local o = {}\n";
+ code += std::string(Indent) + "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) + "})\n";
+ code += std::string(Indent) + "return o\n";
+ code += EndFunc;
+ }
+
+ // Initialize a new struct or table from existing data.
+ void NewRootTypeFromBuffer(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".GetRootAs" + NormalizedName(struct_def) + "(buf, offset)\n";
+ code += std::string(Indent) + "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n";
+ code += std::string(Indent) + "local o = " + NormalizedName(struct_def) + ".New()\n";
+ code += std::string(Indent) + "o:Init(buf, n + offset)\n";
+ code += std::string(Indent) + "return o\n";
+ code += EndFunc;
+ }
+
+ // Initialize an existing object with other data, to avoid an allocation.
+ void InitializeExisting(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += "Init(buf, pos)\n";
+ code += std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n";
+ code += EndFunc;
+ }
+
+ // Get the length of a vector.
+ void GetVectorLen(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "Length()\n";
+ code += OffsetPrefix(field);
+ code += std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n";
+ code += std::string(Indent) + End;
+ code += std::string(Indent) + "return 0\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a struct's scalar.
+ void GetScalarFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += std::string(Indent) + "return " + getter;
+ code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) + ")\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a table's scalar.
+ void GetScalarFieldOfTable(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ std::string getter = GenGetter(field.value.type);
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ getter += std::string("o + ") + SelfDataPos + ")";
+ auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL;
+ if (is_bool) {
+ getter = "(" + getter + " ~= 0)";
+ }
+ code += std::string(Indent) + Indent + "return " + getter + "\n";
+ code += std::string(Indent) + End;
+ std::string default_value;
+ if (is_bool) {
+ default_value = field.value.constant == "0" ? "false" : "true";
+ }
+ else {
+ default_value = field.value.constant;
+ }
+ code += std::string(Indent) + "return " + default_value + "\n";
+ code += EndFunc;
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Struct.
+ void GetStructFieldOfStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(obj)\n";
+ code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " + SelfDataPos + " + ";
+ code += NumToString(field.value.offset) + ")\n";
+ code += std::string(Indent) + "return obj\n";
+ code += EndFunc;
+ }
+
+ // Get a struct by initializing an existing struct.
+ // Specific to Table.
+ void GetStructFieldOfTable(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ if (field.value.type.struct_def->fixed) {
+ code += std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n";
+ }
+ else {
+ code += std::string(Indent) + Indent + "local x = " + SelfData + ":Indirect(o + " + SelfDataPos + ")\n";
+ }
+ code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
+ code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a string.
+ void GetStringField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "()\n";
+ code += OffsetPrefix(field);
+ code += std::string(Indent) + Indent + "return " + GenGetter(field.value.type);
+ code += std::string("o + ") + SelfDataPos + ")\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a union from an object.
+ void GetUnionField(const StructDef &struct_def, const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field)) + "()\n";
+ code += OffsetPrefix(field);
+
+ // TODO(rw): this works and is not the good way to it:
+ //bool is_native_table = TypeName(field) == "*flatbuffers.Table";
+ //if (is_native_table) {
+ // code += std::string(Indent) + Indent + "from flatbuffers.table import Table\n";
+ //} else {
+ // code += std::string(Indent) + Indent +
+ // code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n";
+ //}
+ code += std::string(Indent) + Indent + "local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n";
+ code += std::string(Indent) + Indent + GenGetter(field.value.type) + "obj, o)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a vector's struct member.
+ void GetMemberOfVectorOfStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(j)\n";
+ code += OffsetPrefix(field);
+ code += std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n";
+ code += std::string(Indent) + Indent + "x = x + ((j-1) * ";
+ code += NumToString(InlineSize(vectortype)) + ")\n";
+ if (!(vectortype.struct_def->fixed)) {
+ code += std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n";
+ }
+ code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n";
+ code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n";
+ code += std::string(Indent) + Indent + "return obj\n";
+ code += std::string(Indent) + End;
+ code += EndFunc;
+ }
+
+ // Get the value of a vector's non-struct member. Uses a named return
+ // argument to conveniently set the zero value for the result.
+ void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
+ const FieldDef &field,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ auto vectortype = field.value.type.VectorType();
+
+ GenReceiver(struct_def, code_ptr);
+ code += MakeCamel(NormalizedName(field));
+ code += "(j)\n";
+ code += OffsetPrefix(field);
+ code += std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n";
+ code += std::string(Indent) + Indent;
+ code += "return " + GenGetter(field.value.type);
+ code += "a + ((j-1) * ";
+ code += NumToString(InlineSize(vectortype)) + "))\n";
+ code += std::string(Indent) + End;
+ if (vectortype.base_type == BASE_TYPE_STRING) {
+ code += std::string(Indent) + "return ''\n";
+ }
+ else {
+ code += std::string(Indent) + "return 0\n";
+ }
+ code += EndFunc;
+ }
+
+ // Begin the creator function signature.
+ void BeginBuilderArgs(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+
+ code += "function " + NormalizedName(struct_def) + ".Create" + NormalizedName(struct_def);
+ code += "(builder";
+ }
+
+ // 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 += (std::string) ", " + nameprefix;
+ code += MakeCamel(NormalizedName(field), false);
+ }
+ }
+ }
+
+ // End the creator function signature.
+ void EndBuilderArgs(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += ")\n";
+ }
+
+ // 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 += std::string(Indent) + "builder:Prep(" + NumToString(struct_def.minalign) + ", ";
+ code += 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 += std::string(Indent) + "builder: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 += std::string(Indent) + "builder:Prepend" + GenMethod(field) + "(";
+ code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
+ }
+ }
+ }
+
+ void EndBuilderBody(std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Indent) + "return builder:Offset()\n";
+ code += EndFunc;
+ }
+
+ // Get the value of a table's starting offset.
+ void GetStartOfTable(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Start";
+ code += "(builder) ";
+ code += "builder:StartObject(";
+ code += NumToString(struct_def.fields.vec.size());
+ code += ") end\n";
+ }
+
+ // Set the value of a table's field.
+ void BuildFieldOfTable(const StructDef &struct_def,
+ const FieldDef &field, const size_t offset,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Add" + MakeCamel(NormalizedName(field));
+ code += "(builder, ";
+ code += MakeCamel(NormalizedName(field), false);
+ code += ") ";
+ code += "builder:Prepend";
+ code += GenMethod(field) + "Slot(";
+ code += NumToString(offset) + ", ";
+ // todo: i don't need to cast in Lua, but am I missing something?
+ // if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
+ // code += "flatbuffers.N.UOffsetTFlags.py_type";
+ // code += "(";
+ // code += MakeCamel(NormalizedName(field), false) + ")";
+ // } else {
+ code += MakeCamel(NormalizedName(field), false);
+ // }
+ code += ", " + field.value.constant;
+ code += ") end\n";
+ }
+
+ // Set the value of one of the members of a table's vector.
+ void BuildVectorOfTable(const StructDef &struct_def,
+ const FieldDef &field, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".Start";
+ code += MakeCamel(NormalizedName(field));
+ code += "Vector(builder, numElems) return builder:StartVector(";
+ auto vector_type = field.value.type.VectorType();
+ auto alignment = InlineAlignment(vector_type);
+ auto elem_size = InlineSize(vector_type);
+ code += NumToString(elem_size);
+ code += ", numElems, " + NumToString(alignment);
+ code += ") end\n";
+ }
+
+ // Get the offset of the end of a table.
+ void GetEndOffsetOnTable(const StructDef &struct_def,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedName(struct_def) + ".End";
+ code += "(builder) ";
+ code += "return builder:EndObject() end\n";
+ }
+
+ // Generate the receiver for function signatures.
+ void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += "function " + NormalizedMetaName(struct_def) + ":";
+ }
+
+ // 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, Comment);
+ if (IsScalar(field.value.type.base_type)) {
+ if (struct_def.fixed) {
+ GetScalarFieldOfStruct(struct_def, field, code_ptr);
+ }
+ else {
+ GetScalarFieldOfTable(struct_def, field, code_ptr);
+ }
+ }
+ else {
+ switch (field.value.type.base_type) {
+ case BASE_TYPE_STRUCT:
+ if (struct_def.fixed) {
+ GetStructFieldOfStruct(struct_def, field, code_ptr);
+ }
+ else {
+ GetStructFieldOfTable(struct_def, field, code_ptr);
+ }
+ break;
+ case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break;
+ case BASE_TYPE_VECTOR: {
+ auto vectortype = field.value.type.VectorType();
+ if (vectortype.base_type == BASE_TYPE_STRUCT) {
+ GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
+ }
+ else {
+ GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
+ }
+ break;
+ }
+ case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break;
+ default: FLATBUFFERS_ASSERT(0);
+ }
+ }
+ if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+ GetVectorLen(struct_def, field, code_ptr);
+ }
+ }
+
+ // Generate table constructors, conditioned on its members' types.
+ void GenTableBuilders(const StructDef &struct_def,
+ std::string *code_ptr) {
+ GetStartOfTable(struct_def, code_ptr);
+
+ 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();
+ BuildFieldOfTable(struct_def, field, offset, code_ptr);
+ if (field.value.type.base_type == BASE_TYPE_VECTOR) {
+ BuildVectorOfTable(struct_def, field, code_ptr);
+ }
+ }
+
+ GetEndOffsetOnTable(struct_def, code_ptr);
+ }
+
+ // Generate struct or table methods.
+ void GenStruct(const StructDef &struct_def, std::string *code_ptr) {
+ if (struct_def.generated) return;
+
+ GenComment(struct_def.doc_comment, code_ptr, nullptr, Comment);
+ BeginClass(struct_def, code_ptr);
+
+ GenerateNewObjectPrototype(struct_def, code_ptr);
+
+ if (!struct_def.fixed) {
+ // Generate a special accessor for the table that has been declared as
+ // the root type.
+ NewRootTypeFromBuffer(struct_def, code_ptr);
+ }
+
+ // Generate the Init method that sets the field in a pre-existing
+ // accessor object. This is to allow object reuse.
+ InitializeExisting(struct_def, code_ptr);
+ 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);
+ }
+
+ 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;
+
+ GenComment(enum_def.doc_comment, code_ptr, nullptr, Comment);
+ BeginEnum(NormalizedName(enum_def), code_ptr);
+ 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, Comment);
+ EnumMember(ev, code_ptr);
+ }
+ EndEnum(code_ptr);
+ }
+
+ // Returns the function name that is able to read a value of the given type.
+ std::string GenGetter(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return std::string(SelfData) + ":String(";
+ case BASE_TYPE_UNION: return std::string(SelfData) + ":Union(";
+ case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
+ default:
+ return std::string(SelfData) + ":Get(flatbuffers.N." +
+ MakeCamel(GenTypeGet(type)) + ", ";
+ }
+ }
+
+ // Returns the method name for use with add/put calls.
+ std::string GenMethod(const FieldDef &field) {
+ return IsScalar(field.value.type.base_type)
+ ? MakeCamel(GenTypeBasic(field.value.type))
+ : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
+ }
+
+ 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];
+ }
+
+ std::string GenTypePointer(const Type &type) {
+ switch (type.base_type) {
+ case BASE_TYPE_STRING: return "string";
+ case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType());
+ case BASE_TYPE_STRUCT: return type.struct_def->name;
+ case BASE_TYPE_UNION:
+ // fall through
+ default: return "*flatbuffers.Table";
+ }
+ }
+
+ std::string GenTypeGet(const Type &type) {
+ return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
+ }
+
+ std::string GetNamespace(const Type &type) {
+ return type.struct_def->defined_namespace->GetFullyQualifiedName(type.struct_def->name);
+ }
+
+ std::string TypeName(const FieldDef &field) {
+ return GenTypeGet(field.value.type);
+ }
+
+ std::string TypeNameWithNamespace(const FieldDef &field) {
+ return GetNamespace(field.value.type);
+ }
+
+ // Create a struct with a builder and the struct's arguments.
+ void GenStructBuilder(const StructDef &struct_def,
+ std::string *code_ptr) {
+ BeginBuilderArgs(struct_def, code_ptr);
+ StructBuilderArgs(struct_def, "", code_ptr);
+ EndBuilderArgs(code_ptr);
+
+ StructBuilderBody(struct_def, "", code_ptr);
+ EndBuilderBody(code_ptr);
+ }
+
+ bool generate() {
+ if (!generateEnums()) return false;
+ if (!generateStructs()) return false;
+ return true;
+ }
+
+ private:
+ bool generateEnums() {
+ for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
+ ++it) {
+ auto &enum_def = **it;
+ std::string enumcode;
+ GenEnum(enum_def, &enumcode);
+ if (!SaveType(enum_def, enumcode, false)) return false;
+ }
+ return true;
+ }
+
+ bool generateStructs() {
+ for (auto it = parser_.structs_.vec.begin();
+ it != parser_.structs_.vec.end(); ++it) {
+ auto &struct_def = **it;
+ std::string declcode;
+ GenStruct(struct_def, &declcode);
+ if (!SaveType(struct_def, declcode, true)) return false;
+ }
+ return true;
+ }
+
+ // Begin by declaring namespace and imports.
+ void BeginFile(const std::string name_space_name, const bool needs_imports,
+ std::string *code_ptr) {
+ std::string &code = *code_ptr;
+ code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n";
+ code += std::string(Comment) + "namespace: " + name_space_name + "\n\n";
+ if (needs_imports) {
+ code += "local flatbuffers = require('flatbuffers')\n\n";
+ }
+ }
+
+ // Save out the generated code for a Lua Table type.
+ bool SaveType(const Definition &def, const std::string &classcode,
+ bool needs_imports) {
+ if (!classcode.length()) return true;
+
+ std::string namespace_dir = path_;
+ auto &namespaces = def.defined_namespace->components;
+ for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
+ if (it != namespaces.begin()) namespace_dir += kPathSeparator;
+ namespace_dir += *it;
+ //std::string init_py_filename = namespace_dir + "/__init__.py";
+ //SaveFile(init_py_filename.c_str(), "", false);
+ }
+
+ std::string code = "";
+ BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
+ code += classcode;
+ code += "\n";
+ code += "return " + NormalizedName(def) + " " + Comment + "return the module";
+ std::string filename =
+ NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua";
+ return SaveFile(filename.c_str(), code, false);
+ }
+ private:
+ std::unordered_set<std::string> keywords_;
+ };
+
+} // namespace lua
+
+bool GenerateLua(const Parser &parser, const std::string &path,
+ const std::string &file_name) {
+ lua::LuaGenerator generator(parser, path, file_name);
+ return generator.generate();
+}
+
+} // namespace flatbuffers
"with",
"yield"
};
- for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
+ keywords_.insert(std::begin(keywords), std::end(keywords));
}
// Most field accessors need to retrieve and test the field offset first,
--- /dev/null
+set buildtype=Release
+if "%1"=="-b" set buildtype=%2
+
+..\%buildtype%\flatc.exe --lua -I include_test monster_test.fbs
+
+lua53.exe luatest.lua
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local Ability = {} -- the module
+local Ability_mt = {} -- the class metatable
+
+function Ability.New()
+ local o = {}
+ setmetatable(o, {__index = Ability_mt})
+ return o
+end
+function Ability_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Ability_mt:Id()
+ return self.view:Get(flatbuffers.N.Uint32, self.view.pos + 0)
+end
+function Ability_mt:Distance()
+ return self.view:Get(flatbuffers.N.Uint32, self.view.pos + 4)
+end
+function Ability.CreateAbility(builder, id, distance)
+ builder:Prep(4, 8)
+ builder:PrependUint32(distance)
+ builder:PrependUint32(id)
+ return builder:Offset()
+end
+
+return Ability -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local Any = {
+ NONE = 0,
+ Monster = 1,
+ TestSimpleTableWithEnum = 2,
+ MyGame_Example2_Monster = 3,
+}
+
+return Any -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local Color = {
+ Red = 1,
+ Green = 2,
+ Blue = 8,
+}
+
+return Color -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+-- /// an example documentation comment: monster object
+local Monster = {} -- the module
+local Monster_mt = {} -- the class metatable
+
+function Monster.New()
+ local o = {}
+ setmetatable(o, {__index = Monster_mt})
+ return o
+end
+function Monster.GetRootAsMonster(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Monster.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Monster_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Monster_mt:Pos()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ local x = o + self.view.pos
+ local obj = require('MyGame.Example.Vec3').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Mana()
+ local o = self.view:Offset(6)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 150
+end
+function Monster_mt:Hp()
+ local o = self.view:Offset(8)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 100
+end
+function Monster_mt:Name()
+ local o = self.view:Offset(10)
+ if o ~= 0 then
+ return self.view:String(o + self.view.pos)
+ end
+end
+function Monster_mt:Inventory(j)
+ local o = self.view:Offset(14)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
+ end
+ return 0
+end
+function Monster_mt:InventoryLength()
+ local o = self.view:Offset(14)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Color()
+ local o = self.view:Offset(16)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int8, o + self.view.pos)
+ end
+ return 8
+end
+function Monster_mt:TestType()
+ local o = self.view:Offset(18)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint8, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Test()
+ local o = self.view:Offset(20)
+ if o ~= 0 then
+ local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)
+ self.view:Union(obj, o)
+ return obj
+ end
+end
+function Monster_mt:Test4(j)
+ local o = self.view:Offset(22)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ local obj = require('MyGame.Example.Test').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Test4Length()
+ local o = self.view:Offset(22)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Testarrayofstring(j)
+ local o = self.view:Offset(24)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:String(a + ((j-1) * 4))
+ end
+ return ''
+end
+function Monster_mt:TestarrayofstringLength()
+ local o = self.view:Offset(24)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+-- /// an example documentation comment: this will end up in the generated code
+-- /// multiline too
+function Monster_mt:Testarrayoftables(j)
+ local o = self.view:Offset(26)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ x = self.view:Indirect(x)
+ local obj = require('MyGame.Example.Monster').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:TestarrayoftablesLength()
+ local o = self.view:Offset(26)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Enemy()
+ local o = self.view:Offset(28)
+ if o ~= 0 then
+ local x = self.view:Indirect(o + self.view.pos)
+ local obj = require('MyGame.Example.Monster').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Testnestedflatbuffer(j)
+ local o = self.view:Offset(30)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
+ end
+ return 0
+end
+function Monster_mt:TestnestedflatbufferLength()
+ local o = self.view:Offset(30)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Testempty()
+ local o = self.view:Offset(32)
+ if o ~= 0 then
+ local x = self.view:Indirect(o + self.view.pos)
+ local obj = require('MyGame.Example.Stat').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Testbool()
+ local o = self.view:Offset(34)
+ if o ~= 0 then
+ return (self.view:Get(flatbuffers.N.Bool, o + self.view.pos) ~= 0)
+ end
+ return false
+end
+function Monster_mt:Testhashs32Fnv1()
+ local o = self.view:Offset(36)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int32, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashu32Fnv1()
+ local o = self.view:Offset(38)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint32, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashs64Fnv1()
+ local o = self.view:Offset(40)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashu64Fnv1()
+ local o = self.view:Offset(42)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashs32Fnv1a()
+ local o = self.view:Offset(44)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int32, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashu32Fnv1a()
+ local o = self.view:Offset(46)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint32, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashs64Fnv1a()
+ local o = self.view:Offset(48)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testhashu64Fnv1a()
+ local o = self.view:Offset(50)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:Testarrayofbools(j)
+ local o = self.view:Offset(52)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Bool, a + ((j-1) * 1))
+ end
+ return 0
+end
+function Monster_mt:TestarrayofboolsLength()
+ local o = self.view:Offset(52)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Testf()
+ local o = self.view:Offset(54)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Float32, o + self.view.pos)
+ end
+ return 3.14159
+end
+function Monster_mt:Testf2()
+ local o = self.view:Offset(56)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Float32, o + self.view.pos)
+ end
+ return 3.0
+end
+function Monster_mt:Testf3()
+ local o = self.view:Offset(58)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Float32, o + self.view.pos)
+ end
+ return 0.0
+end
+function Monster_mt:Testarrayofstring2(j)
+ local o = self.view:Offset(60)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:String(a + ((j-1) * 4))
+ end
+ return ''
+end
+function Monster_mt:Testarrayofstring2Length()
+ local o = self.view:Offset(60)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Testarrayofsortedstruct(j)
+ local o = self.view:Offset(62)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 8)
+ local obj = require('MyGame.Example.Ability').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:TestarrayofsortedstructLength()
+ local o = self.view:Offset(62)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Flex(j)
+ local o = self.view:Offset(64)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint8, a + ((j-1) * 1))
+ end
+ return 0
+end
+function Monster_mt:FlexLength()
+ local o = self.view:Offset(64)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:Test5(j)
+ local o = self.view:Offset(66)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ local obj = require('MyGame.Example.Test').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:Test5Length()
+ local o = self.view:Offset(66)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:VectorOfLongs(j)
+ local o = self.view:Offset(68)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Int64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function Monster_mt:VectorOfLongsLength()
+ local o = self.view:Offset(68)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:VectorOfDoubles(j)
+ local o = self.view:Offset(70)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Float64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function Monster_mt:VectorOfDoublesLength()
+ local o = self.view:Offset(70)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:ParentNamespaceTest()
+ local o = self.view:Offset(72)
+ if o ~= 0 then
+ local x = self.view:Indirect(o + self.view.pos)
+ local obj = require('MyGame.InParentNamespace').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:VectorOfReferrables(j)
+ local o = self.view:Offset(74)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ x = self.view:Indirect(x)
+ local obj = require('MyGame.Example.Referrable').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:VectorOfReferrablesLength()
+ local o = self.view:Offset(74)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:SingleWeakReference()
+ local o = self.view:Offset(76)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:VectorOfWeakReferences(j)
+ local o = self.view:Offset(78)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function Monster_mt:VectorOfWeakReferencesLength()
+ local o = self.view:Offset(78)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:VectorOfStrongReferrables(j)
+ local o = self.view:Offset(80)
+ if o ~= 0 then
+ local x = self.view:Vector(o)
+ x = x + ((j-1) * 4)
+ x = self.view:Indirect(x)
+ local obj = require('MyGame.Example.Referrable').New()
+ obj:Init(self.view.bytes, x)
+ return obj
+ end
+end
+function Monster_mt:VectorOfStrongReferrablesLength()
+ local o = self.view:Offset(80)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:CoOwningReference()
+ local o = self.view:Offset(82)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:VectorOfCoOwningReferences(j)
+ local o = self.view:Offset(84)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function Monster_mt:VectorOfCoOwningReferencesLength()
+ local o = self.view:Offset(84)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster_mt:NonOwningReference()
+ local o = self.view:Offset(86)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Monster_mt:VectorOfNonOwningReferences(j)
+ local o = self.view:Offset(88)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Uint64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function Monster_mt:VectorOfNonOwningReferencesLength()
+ local o = self.view:Offset(88)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function Monster.Start(builder) builder:StartObject(43) end
+function Monster.AddPos(builder, pos) builder:PrependStructSlot(0, pos, 0) end
+function Monster.AddMana(builder, mana) builder:PrependInt16Slot(1, mana, 150) end
+function Monster.AddHp(builder, hp) builder:PrependInt16Slot(2, hp, 100) end
+function Monster.AddName(builder, name) builder:PrependUOffsetTRelativeSlot(3, name, 0) end
+function Monster.AddInventory(builder, inventory) builder:PrependUOffsetTRelativeSlot(5, inventory, 0) end
+function Monster.StartInventoryVector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function Monster.AddColor(builder, color) builder:PrependInt8Slot(6, color, 8) end
+function Monster.AddTestType(builder, testType) builder:PrependUint8Slot(7, testType, 0) end
+function Monster.AddTest(builder, test) builder:PrependUOffsetTRelativeSlot(8, test, 0) end
+function Monster.AddTest4(builder, test4) builder:PrependUOffsetTRelativeSlot(9, test4, 0) end
+function Monster.StartTest4Vector(builder, numElems) return builder:StartVector(4, numElems, 2) end
+function Monster.AddTestarrayofstring(builder, testarrayofstring) builder:PrependUOffsetTRelativeSlot(10, testarrayofstring, 0) end
+function Monster.StartTestarrayofstringVector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddTestarrayoftables(builder, testarrayoftables) builder:PrependUOffsetTRelativeSlot(11, testarrayoftables, 0) end
+function Monster.StartTestarrayoftablesVector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddEnemy(builder, enemy) builder:PrependUOffsetTRelativeSlot(12, enemy, 0) end
+function Monster.AddTestnestedflatbuffer(builder, testnestedflatbuffer) builder:PrependUOffsetTRelativeSlot(13, testnestedflatbuffer, 0) end
+function Monster.StartTestnestedflatbufferVector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function Monster.AddTestempty(builder, testempty) builder:PrependUOffsetTRelativeSlot(14, testempty, 0) end
+function Monster.AddTestbool(builder, testbool) builder:PrependBoolSlot(15, testbool, 0) end
+function Monster.AddTesthashs32Fnv1(builder, testhashs32Fnv1) builder:PrependInt32Slot(16, testhashs32Fnv1, 0) end
+function Monster.AddTesthashu32Fnv1(builder, testhashu32Fnv1) builder:PrependUint32Slot(17, testhashu32Fnv1, 0) end
+function Monster.AddTesthashs64Fnv1(builder, testhashs64Fnv1) builder:PrependInt64Slot(18, testhashs64Fnv1, 0) end
+function Monster.AddTesthashu64Fnv1(builder, testhashu64Fnv1) builder:PrependUint64Slot(19, testhashu64Fnv1, 0) end
+function Monster.AddTesthashs32Fnv1a(builder, testhashs32Fnv1a) builder:PrependInt32Slot(20, testhashs32Fnv1a, 0) end
+function Monster.AddTesthashu32Fnv1a(builder, testhashu32Fnv1a) builder:PrependUint32Slot(21, testhashu32Fnv1a, 0) end
+function Monster.AddTesthashs64Fnv1a(builder, testhashs64Fnv1a) builder:PrependInt64Slot(22, testhashs64Fnv1a, 0) end
+function Monster.AddTesthashu64Fnv1a(builder, testhashu64Fnv1a) builder:PrependUint64Slot(23, testhashu64Fnv1a, 0) end
+function Monster.AddTestarrayofbools(builder, testarrayofbools) builder:PrependUOffsetTRelativeSlot(24, testarrayofbools, 0) end
+function Monster.StartTestarrayofboolsVector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function Monster.AddTestf(builder, testf) builder:PrependFloat32Slot(25, testf, 3.14159) end
+function Monster.AddTestf2(builder, testf2) builder:PrependFloat32Slot(26, testf2, 3.0) end
+function Monster.AddTestf3(builder, testf3) builder:PrependFloat32Slot(27, testf3, 0.0) end
+function Monster.AddTestarrayofstring2(builder, testarrayofstring2) builder:PrependUOffsetTRelativeSlot(28, testarrayofstring2, 0) end
+function Monster.StartTestarrayofstring2Vector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddTestarrayofsortedstruct(builder, testarrayofsortedstruct) builder:PrependUOffsetTRelativeSlot(29, testarrayofsortedstruct, 0) end
+function Monster.StartTestarrayofsortedstructVector(builder, numElems) return builder:StartVector(8, numElems, 4) end
+function Monster.AddFlex(builder, flex) builder:PrependUOffsetTRelativeSlot(30, flex, 0) end
+function Monster.StartFlexVector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function Monster.AddTest5(builder, test5) builder:PrependUOffsetTRelativeSlot(31, test5, 0) end
+function Monster.StartTest5Vector(builder, numElems) return builder:StartVector(4, numElems, 2) end
+function Monster.AddVectorOfLongs(builder, vectorOfLongs) builder:PrependUOffsetTRelativeSlot(32, vectorOfLongs, 0) end
+function Monster.StartVectorOfLongsVector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function Monster.AddVectorOfDoubles(builder, vectorOfDoubles) builder:PrependUOffsetTRelativeSlot(33, vectorOfDoubles, 0) end
+function Monster.StartVectorOfDoublesVector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function Monster.AddParentNamespaceTest(builder, parentNamespaceTest) builder:PrependUOffsetTRelativeSlot(34, parentNamespaceTest, 0) end
+function Monster.AddVectorOfReferrables(builder, vectorOfReferrables) builder:PrependUOffsetTRelativeSlot(35, vectorOfReferrables, 0) end
+function Monster.StartVectorOfReferrablesVector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddSingleWeakReference(builder, singleWeakReference) builder:PrependUint64Slot(36, singleWeakReference, 0) end
+function Monster.AddVectorOfWeakReferences(builder, vectorOfWeakReferences) builder:PrependUOffsetTRelativeSlot(37, vectorOfWeakReferences, 0) end
+function Monster.StartVectorOfWeakReferencesVector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function Monster.AddVectorOfStrongReferrables(builder, vectorOfStrongReferrables) builder:PrependUOffsetTRelativeSlot(38, vectorOfStrongReferrables, 0) end
+function Monster.StartVectorOfStrongReferrablesVector(builder, numElems) return builder:StartVector(4, numElems, 4) end
+function Monster.AddCoOwningReference(builder, coOwningReference) builder:PrependUint64Slot(39, coOwningReference, 0) end
+function Monster.AddVectorOfCoOwningReferences(builder, vectorOfCoOwningReferences) builder:PrependUOffsetTRelativeSlot(40, vectorOfCoOwningReferences, 0) end
+function Monster.StartVectorOfCoOwningReferencesVector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function Monster.AddNonOwningReference(builder, nonOwningReference) builder:PrependUint64Slot(41, nonOwningReference, 0) end
+function Monster.AddVectorOfNonOwningReferences(builder, vectorOfNonOwningReferences) builder:PrependUOffsetTRelativeSlot(42, vectorOfNonOwningReferences, 0) end
+function Monster.StartVectorOfNonOwningReferencesVector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function Monster.End(builder) return builder:EndObject() end
+
+return Monster -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local Referrable = {} -- the module
+local Referrable_mt = {} -- the class metatable
+
+function Referrable.New()
+ local o = {}
+ setmetatable(o, {__index = Referrable_mt})
+ return o
+end
+function Referrable.GetRootAsReferrable(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Referrable.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Referrable_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Referrable_mt:Id()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function Referrable.Start(builder) builder:StartObject(1) end
+function Referrable.AddId(builder, id) builder:PrependUint64Slot(0, id, 0) end
+function Referrable.End(builder) return builder:EndObject() end
+
+return Referrable -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local Stat = {} -- the module
+local Stat_mt = {} -- the class metatable
+
+function Stat.New()
+ local o = {}
+ setmetatable(o, {__index = Stat_mt})
+ return o
+end
+function Stat.GetRootAsStat(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Stat.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Stat_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Stat_mt:Id()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ return self.view:String(o + self.view.pos)
+ end
+end
+function Stat_mt:Val()
+ local o = self.view:Offset(6)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int64, o + self.view.pos)
+ end
+ return 0
+end
+function Stat_mt:Count()
+ local o = self.view:Offset(8)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint16, o + self.view.pos)
+ end
+ return 0
+end
+function Stat.Start(builder) builder:StartObject(3) end
+function Stat.AddId(builder, id) builder:PrependUOffsetTRelativeSlot(0, id, 0) end
+function Stat.AddVal(builder, val) builder:PrependInt64Slot(1, val, 0) end
+function Stat.AddCount(builder, count) builder:PrependUint16Slot(2, count, 0) end
+function Stat.End(builder) return builder:EndObject() end
+
+return Stat -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local Test = {} -- the module
+local Test_mt = {} -- the class metatable
+
+function Test.New()
+ local o = {}
+ setmetatable(o, {__index = Test_mt})
+ return o
+end
+function Test_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Test_mt:A()
+ return self.view:Get(flatbuffers.N.Int16, self.view.pos + 0)
+end
+function Test_mt:B()
+ return self.view:Get(flatbuffers.N.Int8, self.view.pos + 2)
+end
+function Test.CreateTest(builder, a, b)
+ builder:Prep(2, 4)
+ builder:Pad(1)
+ builder:PrependInt8(b)
+ builder:PrependInt16(a)
+ return builder:Offset()
+end
+
+return Test -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local TestSimpleTableWithEnum = {} -- the module
+local TestSimpleTableWithEnum_mt = {} -- the class metatable
+
+function TestSimpleTableWithEnum.New()
+ local o = {}
+ setmetatable(o, {__index = TestSimpleTableWithEnum_mt})
+ return o
+end
+function TestSimpleTableWithEnum.GetRootAsTestSimpleTableWithEnum(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = TestSimpleTableWithEnum.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function TestSimpleTableWithEnum_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function TestSimpleTableWithEnum_mt:Color()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int8, o + self.view.pos)
+ end
+ return 2
+end
+function TestSimpleTableWithEnum.Start(builder) builder:StartObject(1) end
+function TestSimpleTableWithEnum.AddColor(builder, color) builder:PrependInt8Slot(0, color, 2) end
+function TestSimpleTableWithEnum.End(builder) return builder:EndObject() end
+
+return TestSimpleTableWithEnum -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local TypeAliases = {} -- the module
+local TypeAliases_mt = {} -- the class metatable
+
+function TypeAliases.New()
+ local o = {}
+ setmetatable(o, {__index = TypeAliases_mt})
+ return o
+end
+function TypeAliases.GetRootAsTypeAliases(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = TypeAliases.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function TypeAliases_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function TypeAliases_mt:I8()
+ local o = self.view:Offset(4)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int8, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:U8()
+ local o = self.view:Offset(6)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint8, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:I16()
+ local o = self.view:Offset(8)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int16, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:U16()
+ local o = self.view:Offset(10)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint16, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:I32()
+ local o = self.view:Offset(12)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int32, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:U32()
+ local o = self.view:Offset(14)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint32, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:I64()
+ local o = self.view:Offset(16)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Int64, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:U64()
+ local o = self.view:Offset(18)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Uint64, o + self.view.pos)
+ end
+ return 0
+end
+function TypeAliases_mt:F32()
+ local o = self.view:Offset(20)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Float32, o + self.view.pos)
+ end
+ return 0.0
+end
+function TypeAliases_mt:F64()
+ local o = self.view:Offset(22)
+ if o ~= 0 then
+ return self.view:Get(flatbuffers.N.Float64, o + self.view.pos)
+ end
+ return 0.0
+end
+function TypeAliases_mt:V8(j)
+ local o = self.view:Offset(24)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Int8, a + ((j-1) * 1))
+ end
+ return 0
+end
+function TypeAliases_mt:V8Length()
+ local o = self.view:Offset(24)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function TypeAliases_mt:Vf64(j)
+ local o = self.view:Offset(26)
+ if o ~= 0 then
+ local a = self.view:Vector(o)
+ return self.view:Get(flatbuffers.N.Float64, a + ((j-1) * 8))
+ end
+ return 0
+end
+function TypeAliases_mt:Vf64Length()
+ local o = self.view:Offset(26)
+ if o ~= 0 then
+ return self.view:VectorLen(o)
+ end
+ return 0
+end
+function TypeAliases.Start(builder) builder:StartObject(12) end
+function TypeAliases.AddI8(builder, i8) builder:PrependInt8Slot(0, i8, 0) end
+function TypeAliases.AddU8(builder, u8) builder:PrependUint8Slot(1, u8, 0) end
+function TypeAliases.AddI16(builder, i16) builder:PrependInt16Slot(2, i16, 0) end
+function TypeAliases.AddU16(builder, u16) builder:PrependUint16Slot(3, u16, 0) end
+function TypeAliases.AddI32(builder, i32) builder:PrependInt32Slot(4, i32, 0) end
+function TypeAliases.AddU32(builder, u32) builder:PrependUint32Slot(5, u32, 0) end
+function TypeAliases.AddI64(builder, i64) builder:PrependInt64Slot(6, i64, 0) end
+function TypeAliases.AddU64(builder, u64) builder:PrependUint64Slot(7, u64, 0) end
+function TypeAliases.AddF32(builder, f32) builder:PrependFloat32Slot(8, f32, 0.0) end
+function TypeAliases.AddF64(builder, f64) builder:PrependFloat64Slot(9, f64, 0.0) end
+function TypeAliases.AddV8(builder, v8) builder:PrependUOffsetTRelativeSlot(10, v8, 0) end
+function TypeAliases.StartV8Vector(builder, numElems) return builder:StartVector(1, numElems, 1) end
+function TypeAliases.AddVf64(builder, vf64) builder:PrependUOffsetTRelativeSlot(11, vf64, 0) end
+function TypeAliases.StartVf64Vector(builder, numElems) return builder:StartVector(8, numElems, 8) end
+function TypeAliases.End(builder) return builder:EndObject() end
+
+return TypeAliases -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example
+
+local flatbuffers = require('flatbuffers')
+
+local Vec3 = {} -- the module
+local Vec3_mt = {} -- the class metatable
+
+function Vec3.New()
+ local o = {}
+ setmetatable(o, {__index = Vec3_mt})
+ return o
+end
+function Vec3_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Vec3_mt:X()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 0)
+end
+function Vec3_mt:Y()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 4)
+end
+function Vec3_mt:Z()
+ return self.view:Get(flatbuffers.N.Float32, self.view.pos + 8)
+end
+function Vec3_mt:Test1()
+ return self.view:Get(flatbuffers.N.Float64, self.view.pos + 16)
+end
+function Vec3_mt:Test2()
+ return self.view:Get(flatbuffers.N.Int8, self.view.pos + 24)
+end
+function Vec3_mt:Test3(obj)
+ obj:Init(self.view.bytes, self.view.pos + 26)
+ return obj
+end
+function Vec3.CreateVec3(builder, x, y, z, test1, test2, test3_a, test3_b)
+ builder:Prep(16, 32)
+ builder:Pad(2)
+ builder:Prep(2, 4)
+ builder:Pad(1)
+ builder:PrependInt8(test3_b)
+ builder:PrependInt16(test3_a)
+ builder:Pad(1)
+ builder:PrependInt8(test2)
+ builder:PrependFloat64(test1)
+ builder:Pad(4)
+ builder:PrependFloat32(z)
+ builder:PrependFloat32(y)
+ builder:PrependFloat32(x)
+ return builder:Offset()
+end
+
+return Vec3 -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: Example2
+
+local flatbuffers = require('flatbuffers')
+
+local Monster = {} -- the module
+local Monster_mt = {} -- the class metatable
+
+function Monster.New()
+ local o = {}
+ setmetatable(o, {__index = Monster_mt})
+ return o
+end
+function Monster.GetRootAsMonster(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = Monster.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function Monster_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function Monster.Start(builder) builder:StartObject(0) end
+function Monster.End(builder) return builder:EndObject() end
+
+return Monster -- return the module
\ No newline at end of file
--- /dev/null
+-- automatically generated by the FlatBuffers compiler, do not modify
+
+-- namespace: MyGame
+
+local flatbuffers = require('flatbuffers')
+
+local InParentNamespace = {} -- the module
+local InParentNamespace_mt = {} -- the class metatable
+
+function InParentNamespace.New()
+ local o = {}
+ setmetatable(o, {__index = InParentNamespace_mt})
+ return o
+end
+function InParentNamespace.GetRootAsInParentNamespace(buf, offset)
+ local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)
+ local o = InParentNamespace.New()
+ o:Init(buf, n + offset)
+ return o
+end
+function InParentNamespace_mt:Init(buf, pos)
+ self.view = flatbuffers.view.New(buf, pos)
+end
+function InParentNamespace.Start(builder) builder:StartObject(0) end
+function InParentNamespace.End(builder) return builder:EndObject() end
+
+return InParentNamespace -- return the module
\ No newline at end of file
set buildtype=Release
if "%1"=="-b" set buildtype=%2
-..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --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
-..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --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
+..\%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 --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
# See the License for the specific language governing permissions and
# limitations under the License.
-../flatc --cpp --java --csharp --dart --go --binary --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 --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 --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 --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
--- /dev/null
+package.path = string.format("../lua/?.lua;./?.lua;%s",package.path)
+
+local function checkReadBuffer(buf, offset, sizePrefix)
+ offset = offset or 0
+
+ if type(buf) == "string" then
+ buf = flatbuffers.binaryArray.New(buf)
+ end
+
+ if sizePrefix then
+ local size = flatbuffers.N.Int32:Unpack(buf, offset)
+ -- no longer matches python tests, but the latest 'monsterdata_test.mon'
+ -- is 448 bytes, minus 4 to arrive at the 444
+ assert(size == 444)
+ offset = offset + flatbuffers.N.Int32.bytewidth
+ end
+
+ local mon = monster.GetRootAsMonster(buf, offset)
+ assert(mon:Hp() == 80, "Monster Hp is not 80")
+ assert(mon:Mana() == 150, "Monster Mana is not 150")
+ assert(mon:Name() == "MyMonster", "Monster Name is not MyMonster")
+
+ local vec = assert(mon:Pos(), "Monster Position is nil")
+ assert(vec:X() == 1.0)
+ assert(vec:Y() == 2.0)
+ assert(vec:Z() == 3.0)
+ assert(vec:Test1() == 3.0)
+ assert(vec:Test2() == 2)
+
+ local t = require("MyGame.Example.Test").New()
+ t = assert(vec:Test3(t))
+
+ assert(t:A() == 5)
+ assert(t:B() == 6)
+
+ local ut = require("MyGame.Example.Any")
+ assert(mon:TestType() == ut.Monster)
+
+ local table2 = mon:Test()
+ assert(getmetatable(table2) == "flatbuffers.view.mt")
+
+ local mon2 = monster.New()
+ mon2:Init(table2.bytes, table2.pos)
+
+ assert(mon2:Name() == "Fred")
+
+ assert(mon:InventoryLength() == 5)
+ local invsum = 0
+ for i=1,mon:InventoryLength() do
+ local v = mon:Inventory(i)
+ invsum = invsum + v
+ end
+ assert(invsum == 10)
+
+ for i=1,5 do
+ assert(mon:VectorOfLongs(i) == 10^((i-1)*2))
+ end
+
+ local dbls = { -1.7976931348623157e+308, 0, 1.7976931348623157e+308}
+ for i=1,mon:VectorOfDoublesLength() do
+ assert(mon:VectorOfDoubles(i) == dbls[i])
+ end
+
+ assert(mon:Test4Length() == 2)
+
+ local test0 = mon:Test4(1)
+ local test1 = mon:Test4(2)
+
+ local v0 = test0:A()
+ local v1 = test0:B()
+ local v2 = test1:A()
+ local v3 = test1:B()
+
+ local sumtest12 = v0 + v1 + v2 + v3
+ assert(sumtest12 == 100)
+
+ assert(mon:TestarrayofstringLength() == 2)
+ assert(mon:Testarrayofstring(1) == "test1")
+ assert(mon:Testarrayofstring(2) == "test2")
+
+ assert(mon:TestarrayoftablesLength() == 0)
+ assert(mon:TestnestedflatbufferLength() == 0)
+ assert(mon:Testempty() == nil)
+end
+
+local function generateMonster(sizePrefix)
+ local b = flatbuffers.Builder(0)
+ local str = b:CreateString("MyMonster")
+ local test1 = b:CreateString("test1")
+ local test2 = b:CreateString("test2")
+ local fred = b:CreateString("Fred")
+
+ monster.StartInventoryVector(b, 5)
+ b:PrependByte(4)
+ b:PrependByte(3)
+ b:PrependByte(2)
+ b:PrependByte(1)
+ b:PrependByte(0)
+ local inv = b:EndVector(5)
+
+ monster.Start(b)
+ monster.AddName(b, fred)
+ local mon2 = monster.End(b)
+
+ monster.StartTest4Vector(b, 2)
+ test.CreateTest(b, 10, 20)
+ test.CreateTest(b, 30, 40)
+ local test4 = b:EndVector(2)
+
+ monster.StartTestarrayofstringVector(b, 2)
+ b:PrependUOffsetTRelative(test2)
+ b:PrependUOffsetTRelative(test1)
+ local testArrayOfString = b:EndVector(2)
+
+ monster.StartVectorOfLongsVector(b, 5)
+ b:PrependInt64(100000000)
+ b:PrependInt64(1000000)
+ b:PrependInt64(10000)
+ b:PrependInt64(100)
+ b:PrependInt64(1)
+ local vectorOfLongs = b:EndVector(5)
+
+ monster.StartVectorOfDoublesVector(b, 3)
+ b:PrependFloat64(1.7976931348623157e+308)
+ b:PrependFloat64(0)
+ b:PrependFloat64(-1.7976931348623157e+308)
+ local vectorOfDoubles = b:EndVector(3)
+
+ monster.Start(b)
+ local pos = vec3.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 2, 5, 6)
+ monster.AddPos(b, pos)
+
+ monster.AddHp(b, 80)
+ monster.AddName(b, str)
+ monster.AddInventory(b, inv)
+ monster.AddTestType(b, 1)
+ monster.AddTest(b, mon2)
+ monster.AddTest4(b, test4)
+ monster.AddTestarrayofstring(b, testArrayOfString)
+ monster.AddVectorOfLongs(b, vectorOfLongs)
+ monster.AddVectorOfDoubles(b, vectorOfDoubles)
+ local mon = monster.End(b)
+
+ if sizePrefix then
+ b:FinishSizePrefixed(mon)
+ else
+ b:Finish(mon)
+ end
+ return b:Output(true), b:Head()
+end
+
+local function sizePrefix(sizePrefix)
+ local buf,offset = generateMonster(sizePrefix)
+ checkReadBuffer(buf, offset, sizePrefix)
+end
+
+local function testCanonicalData()
+ local f = assert(io.open('monsterdata_test.mon', 'rb'))
+ local wireData = f:read("*a")
+ f:close()
+ checkReadBuffer(wireData)
+end
+
+local function benchmarkMakeMonster(count)
+ local length = #(generateMonster())
+
+ --require("flatbuffers.profiler")
+ --profiler = newProfiler("call")
+ --profiler:start()
+
+ local s = os.clock()
+ for i=1,count do
+ generateMonster()
+ end
+ local e = os.clock()
+
+ --profiler:stop()
+
+ --local outfile = io.open( "profile.txt", "w+" )
+ --profiler:report( outfile, true)
+ --outfile:close()
+
+
+ local dur = (e - s)
+ local rate = count / (dur * 1000)
+ local data = (length * count) / (1024 * 1024)
+ local dataRate = data / dur
+
+ print(string.format('built %d %d-byte flatbuffers in %.2fsec: %.2f/msec, %.2fMB/sec',
+ count, length, dur, rate, dataRate))
+end
+
+local function benchmarkReadBuffer(count)
+ local f = assert(io.open('monsterdata_test.mon', 'rb'))
+ local buf = f:read("*a")
+ f:close()
+
+ local s = os.clock()
+ for i=1,count do
+ checkReadBuffer(buf)
+ end
+ local e = os.clock()
+
+ local dur = (e - s)
+ local rate = count / (dur * 1000)
+ local data = (#buf * count) / (1024 * 1024)
+ local dataRate = data / dur
+
+ print(string.format('traversed %d %d-byte flatbuffers in %.2fsec: %.2f/msec, %.2fMB/sec',
+ count, #buf, dur, rate, dataRate))
+end
+
+local tests =
+{
+ {
+ f = sizePrefix,
+ d = "Test size prefix",
+ args = {{true}, {false}}
+ },
+ {
+ f = testCanonicalData,
+ d = "Tests Canonical flatbuffer file included in repo"
+ },
+ {
+ f = benchmarkMakeMonster,
+ d = "Benchmark making monsters",
+ args = {
+ {100},
+ {1000},
+ {10000},
+ }
+ },
+ {
+ f = benchmarkReadBuffer,
+ d = "Benchmark reading monsters",
+ args = {
+ {100},
+ {1000},
+ {10000},
+ -- uncomment following to run 1 million to compare.
+ -- Took ~141 seconds on my machine
+ --{1000000},
+ }
+ },
+}
+
+local result, err = xpcall(function()
+ flatbuffers = assert(require("flatbuffers"))
+ monster = assert(require("MyGame.Example.Monster"))
+ test = assert(require("MyGame.Example.Test"))
+ vec3 = assert(require("MyGame.Example.Vec3"))
+
+ local function buildArgList(tbl)
+ local s = ""
+ for _,item in ipairs(tbl) do
+ s = s .. tostring(item) .. ","
+ end
+ return s:sub(1,-2)
+ end
+
+ local testsPassed, testsFailed = 0,0
+ for _,test in ipairs(tests) do
+ local allargs = test.args or {{}}
+ for _,args in ipairs(allargs) do
+ local results, err = xpcall(test.f,debug.traceback, table.unpack(args))
+ if results then
+ testsPassed = testsPassed + 1
+ else
+ testsFailed = testsFailed + 1
+ print(string.format(" Test [%s](%s) failed: \n\t%s",
+ test.d or "",
+ buildArgList(args),
+ err))
+ end
+ end
+ end
+
+ local totalTests = testsPassed + testsFailed
+ print(string.format("# of test passed: %d / %d (%.2f%%)",
+ testsPassed,
+ totalTests,
+ totalTests ~= 0
+ and 100 * (testsPassed / totalTests)
+ or 0)
+ )
+
+ return 0
+end, debug.traceback)
+
+if not result then
+ print("Unable to run tests due to test framework error: ",err)
+end
+
+os.exit(result or -1)