diff --git a/lua/flatbuffers/builder.lua b/lua/flatbuffers/builder.lua index 25e0032a1df..0f1ac79c0af 100644 --- a/lua/flatbuffers/builder.lua +++ b/lua/flatbuffers/builder.lua @@ -296,25 +296,62 @@ function mt:Slot(slotnum) self.currentVTable[slotnum + 1] = self:Offset() end -local function finish(self, rootTable, sizePrefix) +local function finish(self, rootTable, sizePrefix, fileIdentifier) UOffsetT:EnforceNumber(rootTable) - self:Prep(self.minalign, sizePrefix and 8 or 4) - self:PrependUOffsetTRelative(rootTable) + local hasFid = fileIdentifier ~= nil + if hasFid then + assert(#fileIdentifier == 4, "File identifier must be exactly 4 bytes") + end + + local fid_byte_count = (hasFid and 4 or 0) + + -- alignment: + -- root offset (4) + -- optional file id (4) + -- optional size prefix (4) + self:Prep( + self.minalign, + (sizePrefix and 4 or 0) + + 4 + + fid_byte_count + ) + + -- root offset (points past file identifier if present) + self:PrependUOffsetTRelative(rootTable + fid_byte_count) + + -- file identifier + if hasFid then + for i = 4, 1, -1 do + self:PrependByte(string.byte(fileIdentifier, i)) + end + end + + -- size prefix if sizePrefix then local size = self.bytes.size - 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) + return finish(self, rootTable, false, nil) end function mt:FinishSizePrefixed(rootTable) - return finish(self, rootTable, true) + return finish(self, rootTable, true, nil) +end + +function mt:FinishWithIdentifier(rootTable, fileIdentifier) + return finish(self, rootTable, false, fileIdentifier) +end + +function mt:FinishSizePrefixedWithIdentifier(rootTable, fileIdentifier) + return finish(self, rootTable, true, fileIdentifier) end function mt:Prepend(flags, off) diff --git a/src/bfbs_gen_lua.cpp b/src/bfbs_gen_lua.cpp index f21892953f7..dea7a106621 100644 --- a/src/bfbs_gen_lua.cpp +++ b/src/bfbs_gen_lua.cpp @@ -194,6 +194,13 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { code += "\n"; if (object == root_object) { + // emit file identifier if present + const auto ident = schema_->file_ident(); + if (ident && ident->size() == 4) { + code += "local FileIdentifier = \"" + ident->str() + "\"\n"; + code += "\n"; + } + code += "function " + object_name + ".GetRootAs" + object_name + "(buf, offset)\n"; code += " if type(buf) == \"string\" then\n"; @@ -454,6 +461,34 @@ class LuaBfbsGenerator : public BaseBfbsGenerator { code += " return builder:EndObject()\n"; code += "end\n"; code += "\n"; + + if (object == root_object) { + code += "function " + object_name + ".Finish" + object_name + + "Buffer(builder, offset)\n"; + // emit file identifier if present + const auto ident = schema_->file_ident(); + if (ident && ident->size() == 4) { + code += " builder:FinishWithIdentifier(offset, FileIdentifier)\n"; + } else { + code += " builder:Finish(offset)\n"; + } + code += "end\n"; + code += "\n"; + + // size prefixed option + code += "function " + object_name + ".FinishSizePrefixed" + + object_name + "Buffer(builder, offset)\n"; + // emit file identifier if present + if (ident && ident->size() == 4) { + code += + " builder:FinishSizePrefixedWithIdentifier(offset, " + "FileIdentifier)\n"; + } else { + code += " builder:FinishSizePrefixed(offset)\n"; + } + code += "end\n"; + code += "\n"; + } } EmitCodeBlock(code, object_name, ns, object->declaration_file()->str()); diff --git a/tests/MyGame/Example/Monster.lua b/tests/MyGame/Example/Monster.lua index 851ae03000d..e39d17280f8 100644 --- a/tests/MyGame/Example/Monster.lua +++ b/tests/MyGame/Example/Monster.lua @@ -28,6 +28,8 @@ function Monster.New() return o end +local FileIdentifier = "MONS" + function Monster.GetRootAsMonster(buf, offset) if type(buf) == "string" then buf = flatbuffers.binaryArray.New(buf) @@ -1099,4 +1101,12 @@ function Monster.End(builder) return builder:EndObject() end +function Monster.FinishMonsterBuffer(builder, offset) + builder:FinishWithIdentifier(offset, FileIdentifier) +end + +function Monster.FinishSizePrefixedMonsterBuffer(builder, offset) + builder:FinishSizePrefixedWithIdentifier(offset, FileIdentifier) +end + return Monster \ No newline at end of file