diff --git a/go/table.go b/go/table.go index dc5c39908..695b92da8 100644 --- a/go/table.go +++ b/go/table.go @@ -26,10 +26,15 @@ func (t *Table) Indirect(off UOffsetT) UOffsetT { // String gets a string from data stored inside the flatbuffer. func (t *Table) String(off UOffsetT) string { + return string(t.ByteVector(off)) +} + +// ByteVector gets a byte slice from data stored inside the flatbuffer. +func (t *Table) ByteVector(off UOffsetT) []byte { off += GetUOffsetT(t.Bytes[off:]) start := off + UOffsetT(SizeUOffsetT) length := GetUOffsetT(t.Bytes[off:]) - return string(t.Bytes[start : start+length]) + return t.Bytes[start : start+length] } // VectorLen retrieves the length of the vector whose offset is stored at diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 24b7d0380..630fd09d4 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -144,6 +144,19 @@ static void GetVectorLen(const StructDef &struct_def, code += "\treturn 0\n}\n\n"; } +// Get a [ubyte] vector as a byte slice. +static void GetUByteSlice(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + + GenReceiver(struct_def, code_ptr); + code += " " + MakeCamel(field.name) + "Bytes("; + code += ") []byte " + OffsetPrefix(field); + code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n"; + code += "\treturn nil\n}\n\n"; +} + // Get the value of a struct's scalar. static void GetScalarFieldOfStruct(const StructDef &struct_def, const FieldDef &field, @@ -480,6 +493,9 @@ static void GenStructAccessor(const StructDef &struct_def, } if (field.value.type.base_type == BASE_TYPE_VECTOR) { GetVectorLen(struct_def, field, code_ptr); + if (field.value.type.element == BASE_TYPE_UCHAR) { + GetUByteSlice(struct_def, field, code_ptr); + } } } diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 1abb902e6..0ca0c8097 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -75,6 +75,14 @@ func (rcv *Monster) InventoryLength() int { return 0 } +func (rcv *Monster) InventoryBytes() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + func (rcv *Monster) Color() int8 { o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) if o != 0 { @@ -140,7 +148,9 @@ func (rcv *Monster) TestarrayofstringLength() int { } /// an example documentation comment: this will end up in the generated code + /// multiline too + func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool { o := flatbuffers.UOffsetT(rcv._tab.Offset(26)) if o != 0 { @@ -194,6 +204,14 @@ func (rcv *Monster) TestnestedflatbufferLength() int { return 0 } +func (rcv *Monster) TestnestedflatbufferBytes() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(30)) + if o != 0 { + return rcv._tab.ByteVector(o + rcv._tab.Pos) + } + return nil +} + func (rcv *Monster) Testempty(obj *Stat) *Stat { o := flatbuffers.UOffsetT(rcv._tab.Offset(32)) if o != 0 { diff --git a/tests/go_test.go b/tests/go_test.go index 03eaddfad..02311eb58 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -213,6 +213,11 @@ func CheckReadBuffer(buf []byte, offset flatbuffers.UOffsetT, fail func(string, fail(FailString("monster2.Name()", "Fred", got)) } + inventorySlice := monster.InventoryBytes() + if len(inventorySlice) != monster.InventoryLength() { + fail(FailString("len(monster.InventoryBytes) != monster.InventoryLength", len(inventorySlice), monster.InventoryLength())) + } + if got := monster.InventoryLength(); 5 != got { fail(FailString("monster.InventoryLength", 5, got)) } @@ -221,6 +226,9 @@ func CheckReadBuffer(buf []byte, offset flatbuffers.UOffsetT, fail func(string, l := monster.InventoryLength() for i := 0; i < l; i++ { v := monster.Inventory(i) + if v != inventorySlice[i] { + fail(FailString("monster inventory slice[i] != Inventory(i)", v, inventorySlice[i])) + } invsum += int(v) } if invsum != 10 {