Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit GetRootAs methods for all types in Go and Python #363

Merged
merged 2 commits into from Jul 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/idl_gen_go.cpp
Expand Up @@ -509,13 +509,12 @@ static void GenTableBuilders(const StructDef &struct_def,

// Generate struct or table methods.
static void GenStruct(const StructDef &struct_def,
std::string *code_ptr,
StructDef *root_struct_def) {
std::string *code_ptr) {
if (struct_def.generated) return;

GenComment(struct_def.doc_comment, code_ptr, nullptr);
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
// the root type.
NewRootTypeFromBuffer(struct_def, code_ptr);
Expand Down Expand Up @@ -637,7 +636,7 @@ class GoGenerator : public BaseGenerator {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
std::string declcode;
go::GenStruct(**it, &declcode, parser_.root_struct_def_);
go::GenStruct(**it, &declcode);
if (!SaveType(**it, declcode, true)) return false;
}

Expand Down
9 changes: 4 additions & 5 deletions src/idl_gen_python.cpp
Expand Up @@ -94,7 +94,7 @@ static void NewRootTypeFromBuffer(const StructDef &struct_def,
code += Indent + Indent + "x = " + struct_def.name + "()\n";
code += Indent + Indent + "x.Init(buf, n + offset)\n";
code += Indent + Indent + "return x\n";
code += "\n\n";
code += "\n";
}

// Initialize an existing object with other data, to avoid an allocation.
Expand Down Expand Up @@ -478,13 +478,12 @@ static void GenTableBuilders(const StructDef &struct_def,

// Generate struct or table methods.
static void GenStruct(const StructDef &struct_def,
std::string *code_ptr,
StructDef *root_struct_def) {
std::string *code_ptr) {
if (struct_def.generated) return;

GenComment(struct_def.doc_comment, code_ptr, nullptr, "# ");
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
// the root type.
NewRootTypeFromBuffer(struct_def, code_ptr);
Expand Down Expand Up @@ -620,7 +619,7 @@ class PythonGenerator : public BaseGenerator {
it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it;
std::string declcode;
GenStruct(struct_def, &declcode, parser_.root_struct_def_);
GenStruct(struct_def, &declcode);
if (!SaveType(struct_def, declcode, true)) return false;
}
return true;
Expand Down
1 change: 0 additions & 1 deletion tests/MyGame/Example/Monster.py
Expand Up @@ -15,7 +15,6 @@ def GetRootAsMonster(cls, buf, offset):
x.Init(buf, n + offset)
return x


# Monster
def Init(self, buf, pos):
self._tab = flatbuffers.table.Table(buf, pos)
Expand Down
7 changes: 7 additions & 0 deletions tests/MyGame/Example/Stat.go
Expand Up @@ -9,6 +9,13 @@ type Stat struct {
_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) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
Expand Down
7 changes: 7 additions & 0 deletions tests/MyGame/Example/Stat.py
Expand Up @@ -7,6 +7,13 @@
class Stat(object):
__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
def Init(self, buf, pos):
self._tab = flatbuffers.table.Table(buf, pos)
Expand Down
7 changes: 7 additions & 0 deletions tests/MyGame/Example/TestSimpleTableWithEnum.go
Expand Up @@ -9,6 +9,13 @@ type TestSimpleTableWithEnum struct {
_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) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
Expand Down
7 changes: 7 additions & 0 deletions tests/MyGame/Example/TestSimpleTableWithEnum.py
Expand Up @@ -7,6 +7,13 @@
class TestSimpleTableWithEnum(object):
__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
def Init(self, buf, pos):
self._tab = flatbuffers.table.Table(buf, pos)
Expand Down
28 changes: 28 additions & 0 deletions tests/go_test.go
Expand Up @@ -75,6 +75,9 @@ func TestAll(t *testing.T) {
CheckStructIsNotInlineError(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
// returning errors:
generated, off := CheckGeneratedBuild(t.Fatalf)
Expand Down Expand Up @@ -964,6 +967,31 @@ func CheckManualBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UO
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.
func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) {
b := flatbuffers.NewBuilder(0)
Expand Down
17 changes: 17 additions & 0 deletions tests/py_test.py
Expand Up @@ -1033,6 +1033,23 @@ def test_nondefault_monster_testhashes(self):
self.assertEqual(7, mon2.Testhashs64Fnv1a())
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):
''' TestVtableDeduplication verifies that vtables are deduplicated. '''
Expand Down