mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-03 09:42:26 +00:00
Merge pull request #363 from danring/fix-341
Emit GetRootAs methods for all types in Go and Python
This commit is contained in:
@@ -551,13 +551,12 @@ static void GenTableBuilders(const StructDef &struct_def,
|
|||||||
|
|
||||||
// Generate struct or table methods.
|
// Generate struct or table methods.
|
||||||
static void GenStruct(const StructDef &struct_def,
|
static void GenStruct(const StructDef &struct_def,
|
||||||
std::string *code_ptr,
|
std::string *code_ptr) {
|
||||||
StructDef *root_struct_def) {
|
|
||||||
if (struct_def.generated) return;
|
if (struct_def.generated) return;
|
||||||
|
|
||||||
GenComment(struct_def.doc_comment, code_ptr, nullptr);
|
GenComment(struct_def.doc_comment, code_ptr, nullptr);
|
||||||
BeginClass(struct_def, code_ptr);
|
BeginClass(struct_def, code_ptr);
|
||||||
if (&struct_def == root_struct_def) {
|
if (!struct_def.fixed) {
|
||||||
// Generate a special accessor for the table that has been declared as
|
// Generate a special accessor for the table that has been declared as
|
||||||
// the root type.
|
// the root type.
|
||||||
NewRootTypeFromBuffer(struct_def, code_ptr);
|
NewRootTypeFromBuffer(struct_def, code_ptr);
|
||||||
@@ -681,7 +680,7 @@ class GoGenerator : public BaseGenerator {
|
|||||||
for (auto it = parser_.structs_.vec.begin();
|
for (auto it = parser_.structs_.vec.begin();
|
||||||
it != parser_.structs_.vec.end(); ++it) {
|
it != parser_.structs_.vec.end(); ++it) {
|
||||||
std::string declcode;
|
std::string declcode;
|
||||||
go::GenStruct(**it, &declcode, parser_.root_struct_def_);
|
go::GenStruct(**it, &declcode);
|
||||||
if (!SaveType(**it, declcode, true)) return false;
|
if (!SaveType(**it, declcode, true)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ static void NewRootTypeFromBuffer(const StructDef &struct_def,
|
|||||||
code += Indent + Indent + "x = " + struct_def.name + "()\n";
|
code += Indent + Indent + "x = " + struct_def.name + "()\n";
|
||||||
code += Indent + Indent + "x.Init(buf, n + offset)\n";
|
code += Indent + Indent + "x.Init(buf, n + offset)\n";
|
||||||
code += Indent + Indent + "return x\n";
|
code += Indent + Indent + "return x\n";
|
||||||
code += "\n\n";
|
code += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize an existing object with other data, to avoid an allocation.
|
// Initialize an existing object with other data, to avoid an allocation.
|
||||||
@@ -478,13 +478,12 @@ static void GenTableBuilders(const StructDef &struct_def,
|
|||||||
|
|
||||||
// Generate struct or table methods.
|
// Generate struct or table methods.
|
||||||
static void GenStruct(const StructDef &struct_def,
|
static void GenStruct(const StructDef &struct_def,
|
||||||
std::string *code_ptr,
|
std::string *code_ptr) {
|
||||||
StructDef *root_struct_def) {
|
|
||||||
if (struct_def.generated) return;
|
if (struct_def.generated) return;
|
||||||
|
|
||||||
GenComment(struct_def.doc_comment, code_ptr, nullptr, "# ");
|
GenComment(struct_def.doc_comment, code_ptr, nullptr, "# ");
|
||||||
BeginClass(struct_def, code_ptr);
|
BeginClass(struct_def, code_ptr);
|
||||||
if (&struct_def == root_struct_def) {
|
if (!struct_def.fixed) {
|
||||||
// Generate a special accessor for the table that has been declared as
|
// Generate a special accessor for the table that has been declared as
|
||||||
// the root type.
|
// the root type.
|
||||||
NewRootTypeFromBuffer(struct_def, code_ptr);
|
NewRootTypeFromBuffer(struct_def, code_ptr);
|
||||||
@@ -621,7 +620,7 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
it != parser_.structs_.vec.end(); ++it) {
|
it != parser_.structs_.vec.end(); ++it) {
|
||||||
auto &struct_def = **it;
|
auto &struct_def = **it;
|
||||||
std::string declcode;
|
std::string declcode;
|
||||||
GenStruct(struct_def, &declcode, parser_.root_struct_def_);
|
GenStruct(struct_def, &declcode);
|
||||||
if (!SaveType(struct_def, declcode, true)) return false;
|
if (!SaveType(struct_def, declcode, true)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ class Monster(object):
|
|||||||
x.Init(buf, n + offset)
|
x.Init(buf, n + offset)
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
# Monster
|
# Monster
|
||||||
def Init(self, buf, pos):
|
def Init(self, buf, pos):
|
||||||
self._tab = flatbuffers.table.Table(buf, pos)
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ type Stat struct {
|
|||||||
_tab flatbuffers.Table
|
_tab flatbuffers.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetRootAsStat(buf []byte, offset flatbuffers.UOffsetT) *Stat {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||||
|
x := &Stat{}
|
||||||
|
x.Init(buf, n + offset)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
func (rcv *Stat) Init(buf []byte, i flatbuffers.UOffsetT) {
|
func (rcv *Stat) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||||
rcv._tab.Bytes = buf
|
rcv._tab.Bytes = buf
|
||||||
rcv._tab.Pos = i
|
rcv._tab.Pos = i
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ import flatbuffers
|
|||||||
class Stat(object):
|
class Stat(object):
|
||||||
__slots__ = ['_tab']
|
__slots__ = ['_tab']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def GetRootAsStat(cls, buf, offset):
|
||||||
|
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||||
|
x = Stat()
|
||||||
|
x.Init(buf, n + offset)
|
||||||
|
return x
|
||||||
|
|
||||||
# Stat
|
# Stat
|
||||||
def Init(self, buf, pos):
|
def Init(self, buf, pos):
|
||||||
self._tab = flatbuffers.table.Table(buf, pos)
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ type TestSimpleTableWithEnum struct {
|
|||||||
_tab flatbuffers.Table
|
_tab flatbuffers.Table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetRootAsTestSimpleTableWithEnum(buf []byte, offset flatbuffers.UOffsetT) *TestSimpleTableWithEnum {
|
||||||
|
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||||
|
x := &TestSimpleTableWithEnum{}
|
||||||
|
x.Init(buf, n + offset)
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
func (rcv *TestSimpleTableWithEnum) Init(buf []byte, i flatbuffers.UOffsetT) {
|
func (rcv *TestSimpleTableWithEnum) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||||
rcv._tab.Bytes = buf
|
rcv._tab.Bytes = buf
|
||||||
rcv._tab.Pos = i
|
rcv._tab.Pos = i
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ import flatbuffers
|
|||||||
class TestSimpleTableWithEnum(object):
|
class TestSimpleTableWithEnum(object):
|
||||||
__slots__ = ['_tab']
|
__slots__ = ['_tab']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def GetRootAsTestSimpleTableWithEnum(cls, buf, offset):
|
||||||
|
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||||
|
x = TestSimpleTableWithEnum()
|
||||||
|
x.Init(buf, n + offset)
|
||||||
|
return x
|
||||||
|
|
||||||
# TestSimpleTableWithEnum
|
# TestSimpleTableWithEnum
|
||||||
def Init(self, buf, pos):
|
def Init(self, buf, pos):
|
||||||
self._tab = flatbuffers.table.Table(buf, pos)
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ func TestAll(t *testing.T) {
|
|||||||
CheckStructIsNotInlineError(t.Fatalf)
|
CheckStructIsNotInlineError(t.Fatalf)
|
||||||
CheckFinishedBytesError(t.Fatalf)
|
CheckFinishedBytesError(t.Fatalf)
|
||||||
|
|
||||||
|
// Verify that GetRootAs works for non-root tables
|
||||||
|
CheckGetRootAsForNonRootTable(t.Fatalf)
|
||||||
|
|
||||||
// Verify that using the generated Go code builds a buffer without
|
// Verify that using the generated Go code builds a buffer without
|
||||||
// returning errors:
|
// returning errors:
|
||||||
generated, off := CheckGeneratedBuild(t.Fatalf)
|
generated, off := CheckGeneratedBuild(t.Fatalf)
|
||||||
@@ -1081,6 +1084,31 @@ func CheckManualBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UO
|
|||||||
return b.Bytes, b.Head()
|
return b.Bytes, b.Head()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckGetRootAsForNonRootTable(fail func(string, ...interface{})) {
|
||||||
|
b := flatbuffers.NewBuilder(0)
|
||||||
|
str := b.CreateString("MyStat")
|
||||||
|
example.StatStart(b)
|
||||||
|
example.StatAddId(b, str)
|
||||||
|
example.StatAddVal(b, 12345678)
|
||||||
|
example.StatAddCount(b, 12345)
|
||||||
|
stat_end := example.StatEnd(b)
|
||||||
|
b.Finish(stat_end)
|
||||||
|
|
||||||
|
stat := example.GetRootAsStat(b.Bytes, b.Head())
|
||||||
|
|
||||||
|
if got := stat.Id(); !bytes.Equal([]byte("MyStat"), got) {
|
||||||
|
fail(FailString("stat.Id()", "MyStat", got))
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := stat.Val(); 12345678 != got {
|
||||||
|
fail(FailString("stat.Val()", 12345678, got))
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := stat.Count(); 12345 != got {
|
||||||
|
fail(FailString("stat.Count()", 12345, got))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CheckGeneratedBuild uses generated code to build the example Monster.
|
// CheckGeneratedBuild uses generated code to build the example Monster.
|
||||||
func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) {
|
func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) {
|
||||||
b := flatbuffers.NewBuilder(0)
|
b := flatbuffers.NewBuilder(0)
|
||||||
|
|||||||
@@ -1034,6 +1034,23 @@ class TestAllCodePathsOfExampleSchema(unittest.TestCase):
|
|||||||
self.assertEqual(7, mon2.Testhashs64Fnv1a())
|
self.assertEqual(7, mon2.Testhashs64Fnv1a())
|
||||||
self.assertEqual(8, mon2.Testhashu64Fnv1a())
|
self.assertEqual(8, mon2.Testhashu64Fnv1a())
|
||||||
|
|
||||||
|
def test_getrootas_for_nonroot_table(self):
|
||||||
|
b = flatbuffers.Builder(0)
|
||||||
|
string = b.CreateString("MyStat")
|
||||||
|
|
||||||
|
MyGame.Example.Stat.StatStart(b)
|
||||||
|
MyGame.Example.Stat.StatAddId(b, string)
|
||||||
|
MyGame.Example.Stat.StatAddVal(b, 12345678)
|
||||||
|
MyGame.Example.Stat.StatAddCount(b, 12345)
|
||||||
|
stat = MyGame.Example.Stat.StatEnd(b)
|
||||||
|
b.Finish(stat)
|
||||||
|
|
||||||
|
stat2 = MyGame.Example.Stat.Stat.GetRootAsStat(b.Bytes, b.Head())
|
||||||
|
|
||||||
|
self.assertEqual(b"MyStat", stat2.Id())
|
||||||
|
self.assertEqual(12345678, stat2.Val())
|
||||||
|
self.assertEqual(12345, stat2.Count())
|
||||||
|
|
||||||
|
|
||||||
class TestVtableDeduplication(unittest.TestCase):
|
class TestVtableDeduplication(unittest.TestCase):
|
||||||
''' TestVtableDeduplication verifies that vtables are deduplicated. '''
|
''' TestVtableDeduplication verifies that vtables are deduplicated. '''
|
||||||
|
|||||||
Reference in New Issue
Block a user