Commit ba5eb3b5 authored by Derek Bailey's avatar Derek Bailey Committed by Wouter van Oortmerssen

Lua (5.3) Language addition (#4804)

* starting Lua port of python implmention. Syncing commit

* Bulk of Lua module port from Python done. Not tested, only static analysis. Need to work on binary strings. Started work on flatc lua code generation

* Fixed all the basic errors to produced a binary output from the builder, don't know if it is generated correctly, but it contains data, so that must be good

* fixed binary set command that was extending the array improperly

* continued improvement

* Moved lua submodules down a directory so their names don't clash with potential other modules. Added compat module to provide Lua versioning logic

* Successful sample port from Python

* working on testing Lua code with formal tests

* continued to work on tests and fixes to code to make tests pass

* Added reading buffer test

* Changed binaryarray implmentation to use a temporary table for storing data, and then serialize it to a string when requested. This double the rate of building flatbuffers compared to the string approach.

* Didn't need encode module as it just added another layer of indirection that isn't need

* profiled reading buffers, optimizations to increase read performance of monster data to ~7 monster / millisecond

* Writing profiler improvments. Get about
~2 monsters/millisecond building rate

* removed Numpy generation from Lua (came from the Python port)

* math.pow is deprecated in Lua 5.3, so changed to ^ notation. Also added .bat script for starting Lua tests

* adding results of generate_code.bat

* simple edits for code review in PR.

* There was a buffer overflow in inserting the keywords into the unorder set for both the Lua and Python code gens. Changed insertion to use iterators.

* fixed spacing issue

* basic documenation/tutorial updates. Updated sample_binary.lua to reflect the tutorial better

* removed windows-specific build step in Lua tests
parent 8ea293b9
......@@ -12,7 +12,9 @@
*.vcxproj.user
*.sln
*.suo
*.opendb
*.keystore
**/.vs/**
**/bin/**
**/gen/**
**/libs/**
......@@ -25,6 +27,8 @@
**/CMakeTestfile.cmake
**/Debug/**
**/Release/**
**/RelWithDebInfo/**
**/x64/ #build artifacts from VS
build.xml
local.properties
project.properties
......
......@@ -51,6 +51,7 @@ set(FlatBuffers_Compiler_SRCS
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
......
......@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
serialization library for C++, C#, C, Go, Java, JavaScript, 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.
......@@ -134,6 +134,8 @@ sections provide a more in-depth usage guide.
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
......
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>
This diff is collapsed.
......@@ -758,6 +758,7 @@ INPUT = "FlatBuffers.md" \
"TypeScriptUsage.md" \
"PHPUsage.md" \
"PythonUsage.md" \
"LuaUsage.md" \
"Support.md" \
"Benchmarks.md" \
"WhitePaper.md" \
......
......@@ -41,6 +41,8 @@
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">
......
......@@ -408,6 +408,7 @@ struct IDLOptions {
kTs = 1 << 9,
kJsonSchema = 1 << 10,
kDart = 1 << 11,
kLua = 1 << 12,
kMAX
};
......@@ -814,6 +815,12 @@ extern bool GeneratePython(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate Lua files from the definitions in the Parser object.
// See idl_gen_lua.cpp.
extern bool GenerateLua(const Parser &parser,
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,
......
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
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
This diff is collapsed.
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
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
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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
......@@ -71,6 +71,10 @@ int main(int argc, const char *argv[]) {
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 },
......
This diff is collapsed.
......@@ -72,7 +72,7 @@ class PythonGenerator : public BaseGenerator {
"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,
......
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
-- 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
-- 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
-- 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
This diff is collapsed.
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
-- 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
......@@ -15,8 +15,8 @@
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
......
......@@ -14,8 +14,8 @@
# 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
......
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment