Skip to content

Commit 3aa2a02

Browse files
dbaileychessLuckyRu
authored andcommitted
Add Lua FlatbufferBuilder Clean() method to enable reuseable builders (google#5606)
1 parent 8af7170 commit 3aa2a02

File tree

2 files changed

+68
-2
lines changed

2 files changed

+68
-2
lines changed

lua/flatbuffers/builder.lua

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@ function m.New(initialSize)
6060
return o
6161
end
6262

63+
-- Clears the builder and resets the state. It does not actually clear the backing binary array, it just reuses it as
64+
-- needed. This is a performant way to use the builder for multiple constructions without the overhead of multiple
65+
-- builder allocations.
66+
function mt:Clear()
67+
self.finished = false
68+
self.nested = false
69+
self.minalign = 1
70+
self.currentVTable = nil
71+
self.objectEnd = nil
72+
self.head = #self.bytes -- place the head at the end of the binary array
73+
74+
-- clear vtables instead of making a new table
75+
local vtable = self.vtables
76+
local vtableCount = #vtable
77+
for i=1,vtableCount do vtable[i] = nil end
78+
end
79+
6380
function mt:Output(full)
6481
assert(self.finished, "Builder Not Finished")
6582
if full then

tests/luatest.lua

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ local function checkReadBuffer(buf, offset, sizePrefix)
8181
assert(mon:Testempty() == nil)
8282
end
8383

84-
local function generateMonster(sizePrefix)
85-
local b = flatbuffers.Builder(0)
84+
local function generateMonster(sizePrefix, b)
85+
b = b or flatbuffers.Builder(0)
8686
local str = b:CreateString("MyMonster")
8787
local test1 = b:CreateString("test1")
8888
local test2 = b:CreateString("test2")
@@ -156,6 +156,51 @@ local function sizePrefix(sizePrefix)
156156
checkReadBuffer(buf, offset, sizePrefix)
157157
end
158158

159+
local function fbbClear()
160+
-- Generate a builder that will be 'cleared' and reused to create two different objects.
161+
local fbb = flatbuffers.Builder(0)
162+
163+
-- First use the builder to read the normal monster data and verify it works
164+
local buf, offset = generateMonster(false, fbb)
165+
checkReadBuffer(buf, offset, false)
166+
167+
-- Then clear the builder to be used again
168+
fbb:Clear()
169+
170+
-- Storage for the built monsters
171+
local monsters = {}
172+
local lastBuf
173+
174+
-- Make another builder that will be use identically to the 'cleared' one so outputs can be compared. Build both the
175+
-- Cleared builder and new builder in the exact same way, so we can compare their results
176+
for i, builder in ipairs({fbb, flatbuffers.Builder(0)}) do
177+
local strOffset = builder:CreateString("Hi there")
178+
monster.Start(builder)
179+
monster.AddPos(builder, vec3.CreateVec3(builder, 3.0, 2.0, 1.0, 17.0, 3, 100, 123))
180+
monster.AddName(builder, strOffset)
181+
monster.AddMana(builder, 123)
182+
builder:Finish(monster.End(builder))
183+
local buf = builder:Output(false)
184+
if not lastBuf then
185+
lastBuf = buf
186+
else
187+
-- the output, sized-buffer should be identical
188+
assert(lastBuf == buf, "Monster output buffers are not identical")
189+
end
190+
monsters[i] = monster.GetRootAsMonster(flatbuffers.binaryArray.New(buf), 0)
191+
end
192+
193+
-- Check that all the fields for the generated monsters are as we expect
194+
for i, monster in ipairs(monsters) do
195+
assert(monster:Name() == "Hi there", "Monster Name is not 'Hi There' for monster "..i)
196+
-- HP is default to 100 in the schema, but we change it in generateMonster to 80, so this is a good test to
197+
-- see if the cleared builder really clears the data.
198+
assert(monster:Hp() == 100, "HP doesn't equal the default value for monster "..i)
199+
assert(monster:Mana() == 123, "Monster Mana is not '123' for monster "..i)
200+
assert(monster:Pos():X() == 3.0, "Monster vec3.X is not '3' for monster "..i)
201+
end
202+
end
203+
159204
local function testCanonicalData()
160205
local f = assert(io.open('monsterdata_test.mon', 'rb'))
161206
local wireData = f:read("*a")
@@ -219,6 +264,10 @@ local tests =
219264
d = "Test size prefix",
220265
args = {{true}, {false}}
221266
},
267+
{
268+
f = fbbClear,
269+
d = "FlatBufferBuilder Clear",
270+
},
222271
{
223272
f = testCanonicalData,
224273
d = "Tests Canonical flatbuffer file included in repo"

0 commit comments

Comments
 (0)