Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright 2014 Google Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // independent from idl_parser, since this code is not needed for most clients
     18 
     19 #include <string>
     20 
     21 #include "flatbuffers/flatbuffers.h"
     22 #include "flatbuffers/idl.h"
     23 #include "flatbuffers/util.h"
     24 #include "flatbuffers/code_generators.h"
     25 
     26 #ifdef _WIN32
     27 #include <direct.h>
     28 #define PATH_SEPARATOR "\\"
     29 #define mkdir(n, m) _mkdir(n)
     30 #else
     31 #include <sys/stat.h>
     32 #define PATH_SEPARATOR "/"
     33 #endif
     34 
     35 namespace flatbuffers {
     36 namespace go {
     37 
     38 static std::string GenGetter(const Type &type);
     39 static std::string GenMethod(const FieldDef &field);
     40 static void GenStructBuilder(const StructDef &struct_def,
     41                              std::string *code_ptr);
     42 static void GenReceiver(const StructDef &struct_def, std::string *code_ptr);
     43 static std::string GenTypeBasic(const Type &type);
     44 static std::string GenTypeGet(const Type &type);
     45 static std::string TypeName(const FieldDef &field);
     46 
     47 
     48 // Most field accessors need to retrieve and test the field offset first,
     49 // this is the prefix code for that.
     50 std::string OffsetPrefix(const FieldDef &field) {
     51   return "{\n\to := flatbuffers.UOffsetT(rcv._tab.Offset(" +
     52          NumToString(field.value.offset) +
     53          "))\n\tif o != 0 {\n";
     54 }
     55 
     56 // Begin a class declaration.
     57 static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
     58   std::string &code = *code_ptr;
     59 
     60   code += "type " + struct_def.name + " struct {\n\t";
     61 
     62   // _ is reserved in flatbuffers field names, so no chance of name conflict:
     63   code += "_tab ";
     64   code += struct_def.fixed ? "flatbuffers.Struct" : "flatbuffers.Table";
     65   code += "\n}\n\n";
     66 }
     67 
     68 // Begin enum code with a class declaration.
     69 static void BeginEnum(std::string *code_ptr) {
     70   std::string &code = *code_ptr;
     71   code += "const (\n";
     72 }
     73 
     74 // A single enum member.
     75 static void EnumMember(const EnumDef &enum_def, const EnumVal ev,
     76                        std::string *code_ptr) {
     77   std::string &code = *code_ptr;
     78   code += "\t";
     79   code += enum_def.name;
     80   code += ev.name;
     81   code += " = ";
     82   code += NumToString(ev.value) + "\n";
     83 }
     84 
     85 // End enum code.
     86 static void EndEnum(std::string *code_ptr) {
     87   std::string &code = *code_ptr;
     88   code += ")\n\n";
     89 }
     90 
     91 // Begin enum name code.
     92 static void BeginEnumNames(const EnumDef &enum_def, std::string *code_ptr) {
     93   std::string &code = *code_ptr;
     94   code += "var EnumNames";
     95   code += enum_def.name;
     96   code += " = map[int]string{\n";
     97 }
     98 
     99 // A single enum name member.
    100 static void EnumNameMember(const EnumDef &enum_def, const EnumVal ev,
    101                            std::string *code_ptr) {
    102   std::string &code = *code_ptr;
    103   code += "\t";
    104   code += enum_def.name;
    105   code += ev.name;
    106   code += ":\"";
    107   code += ev.name;
    108   code += "\",\n";
    109 }
    110 
    111 // End enum name code.
    112 static void EndEnumNames(std::string *code_ptr) {
    113   std::string &code = *code_ptr;
    114   code += "}\n\n";
    115 }
    116 
    117 // Initialize a new struct or table from existing data.
    118 static void NewRootTypeFromBuffer(const StructDef &struct_def,
    119                                   std::string *code_ptr) {
    120   std::string &code = *code_ptr;
    121 
    122   code += "func GetRootAs";
    123   code += struct_def.name;
    124   code += "(buf []byte, offset flatbuffers.UOffsetT) ";
    125   code += "*" + struct_def.name + "";
    126   code += " {\n";
    127   code += "\tn := flatbuffers.GetUOffsetT(buf[offset:])\n";
    128   code += "\tx := &" + struct_def.name + "{}\n";
    129   code += "\tx.Init(buf, n+offset)\n";
    130   code += "\treturn x\n";
    131   code += "}\n\n";
    132 }
    133 
    134 // Initialize an existing object with other data, to avoid an allocation.
    135 static void InitializeExisting(const StructDef &struct_def,
    136                                std::string *code_ptr) {
    137   std::string &code = *code_ptr;
    138 
    139   GenReceiver(struct_def, code_ptr);
    140   code += " Init(buf []byte, i flatbuffers.UOffsetT) ";
    141   code += "{\n";
    142   code += "\trcv._tab.Bytes = buf\n";
    143   code += "\trcv._tab.Pos = i\n";
    144   code += "}\n\n";
    145 }
    146 
    147 // Implement the table accessor
    148 static void GenTableAccessor(const StructDef &struct_def,
    149                                std::string *code_ptr) {
    150   std::string &code = *code_ptr;
    151 
    152   GenReceiver(struct_def, code_ptr);
    153   code += " Table() flatbuffers.Table ";
    154   code += "{\n";
    155 
    156   if (struct_def.fixed) {
    157       code += "\treturn rcv._tab.Table\n";
    158   } else {
    159       code += "\treturn rcv._tab\n";
    160   }
    161   code += "}\n\n";
    162 }
    163 
    164 // Get the length of a vector.
    165 static void GetVectorLen(const StructDef &struct_def,
    166                          const FieldDef &field,
    167                          std::string *code_ptr) {
    168   std::string &code = *code_ptr;
    169 
    170   GenReceiver(struct_def, code_ptr);
    171   code += " " + MakeCamel(field.name) + "Length(";
    172   code += ") int " + OffsetPrefix(field);
    173   code += "\t\treturn rcv._tab.VectorLen(o)\n\t}\n";
    174   code += "\treturn 0\n}\n\n";
    175 }
    176 
    177 // Get a [ubyte] vector as a byte slice.
    178 static void GetUByteSlice(const StructDef &struct_def,
    179                           const FieldDef &field,
    180                           std::string *code_ptr) {
    181   std::string &code = *code_ptr;
    182 
    183   GenReceiver(struct_def, code_ptr);
    184   code += " " + MakeCamel(field.name) + "Bytes(";
    185   code += ") []byte " + OffsetPrefix(field);
    186   code += "\t\treturn rcv._tab.ByteVector(o + rcv._tab.Pos)\n\t}\n";
    187   code += "\treturn nil\n}\n\n";
    188 }
    189 
    190 // Get the value of a struct's scalar.
    191 static void GetScalarFieldOfStruct(const StructDef &struct_def,
    192                                    const FieldDef &field,
    193                                    std::string *code_ptr) {
    194   std::string &code = *code_ptr;
    195   std::string getter = GenGetter(field.value.type);
    196   GenReceiver(struct_def, code_ptr);
    197   code += " " + MakeCamel(field.name);
    198   code += "() " + TypeName(field) + " {\n";
    199   code +="\treturn " + getter;
    200   code += "(rcv._tab.Pos + flatbuffers.UOffsetT(";
    201   code += NumToString(field.value.offset) + "))\n}\n";
    202 }
    203 
    204 // Get the value of a table's scalar.
    205 static void GetScalarFieldOfTable(const StructDef &struct_def,
    206                                   const FieldDef &field,
    207                                   std::string *code_ptr) {
    208   std::string &code = *code_ptr;
    209   std::string getter = GenGetter(field.value.type);
    210   GenReceiver(struct_def, code_ptr);
    211   code += " " + MakeCamel(field.name);
    212   code += "() " + TypeName(field) + " ";
    213   code += OffsetPrefix(field) + "\t\treturn " + getter;
    214   code += "(o + rcv._tab.Pos)\n\t}\n";
    215   code += "\treturn " + field.value.constant + "\n";
    216   code += "}\n\n";
    217 }
    218 
    219 // Get a struct by initializing an existing struct.
    220 // Specific to Struct.
    221 static void GetStructFieldOfStruct(const StructDef &struct_def,
    222                                    const FieldDef &field,
    223                                    std::string *code_ptr) {
    224   std::string &code = *code_ptr;
    225   GenReceiver(struct_def, code_ptr);
    226   code += " " + MakeCamel(field.name);
    227   code += "(obj *" + TypeName(field);
    228   code += ") *" + TypeName(field);
    229   code += " {\n";
    230   code += "\tif obj == nil {\n";
    231   code += "\t\tobj = new(" + TypeName(field) + ")\n";
    232   code += "\t}\n";
    233   code += "\tobj.Init(rcv._tab.Bytes, rcv._tab.Pos+";
    234   code += NumToString(field.value.offset) + ")";
    235   code += "\n\treturn obj\n";
    236   code += "}\n";
    237 }
    238 
    239 // Get a struct by initializing an existing struct.
    240 // Specific to Table.
    241 static void GetStructFieldOfTable(const StructDef &struct_def,
    242                                   const FieldDef &field,
    243                                   std::string *code_ptr) {
    244   std::string &code = *code_ptr;
    245   GenReceiver(struct_def, code_ptr);
    246   code += " " + MakeCamel(field.name);
    247   code += "(obj *";
    248   code += TypeName(field);
    249   code += ") *" + TypeName(field) + " " + OffsetPrefix(field);
    250   if (field.value.type.struct_def->fixed) {
    251     code += "\t\tx := o + rcv._tab.Pos\n";
    252   } else {
    253     code += "\t\tx := rcv._tab.Indirect(o + rcv._tab.Pos)\n";
    254   }
    255   code += "\t\tif obj == nil {\n";
    256   code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
    257   code += "\t\t}\n";
    258   code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
    259   code += "\t\treturn obj\n\t}\n\treturn nil\n";
    260   code += "}\n\n";
    261 }
    262 
    263 // Get the value of a string.
    264 static void GetStringField(const StructDef &struct_def,
    265                            const FieldDef &field,
    266                            std::string *code_ptr) {
    267   std::string &code = *code_ptr;
    268   GenReceiver(struct_def, code_ptr);
    269   code += " " +  MakeCamel(field.name);
    270   code += "() " + TypeName(field) + " ";
    271   code += OffsetPrefix(field) + "\t\treturn " + GenGetter(field.value.type);
    272   code += "(o + rcv._tab.Pos)\n\t}\n\treturn nil\n";
    273   code += "}\n\n";
    274 }
    275 
    276 // Get the value of a union from an object.
    277 static void GetUnionField(const StructDef &struct_def,
    278                           const FieldDef &field,
    279                           std::string *code_ptr) {
    280   std::string &code = *code_ptr;
    281   GenReceiver(struct_def, code_ptr);
    282   code += " " + MakeCamel(field.name) + "(";
    283   code += "obj " + TypeName(field) + ") bool ";
    284   code += OffsetPrefix(field);
    285   code += "\t\t" + GenGetter(field.value.type);
    286   code += "(obj, o)\n\t\treturn true\n\t}\n";
    287   code += "\treturn false\n";
    288   code += "}\n\n";
    289 }
    290 
    291 // Get the value of a vector's struct member.
    292 static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
    293                                       const FieldDef &field,
    294                                       std::string *code_ptr) {
    295   std::string &code = *code_ptr;
    296   auto vectortype = field.value.type.VectorType();
    297 
    298   GenReceiver(struct_def, code_ptr);
    299   code += " " + MakeCamel(field.name);
    300   code += "(obj *" + TypeName(field);
    301   code += ", j int) bool " + OffsetPrefix(field);
    302   code += "\t\tx := rcv._tab.Vector(o)\n";
    303   code += "\t\tx += flatbuffers.UOffsetT(j) * ";
    304   code += NumToString(InlineSize(vectortype)) + "\n";
    305   if (!(vectortype.struct_def->fixed)) {
    306     code += "\t\tx = rcv._tab.Indirect(x)\n";
    307   }
    308   code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
    309   code += "\t\treturn true\n\t}\n";
    310   code += "\treturn false\n";
    311   code += "}\n\n";
    312 }
    313 
    314 // Get the value of a vector's non-struct member. Uses a named return
    315 // argument to conveniently set the zero value for the result.
    316 static void GetMemberOfVectorOfNonStruct(const StructDef &struct_def,
    317                                          const FieldDef &field,
    318                                          std::string *code_ptr) {
    319   std::string &code = *code_ptr;
    320   auto vectortype = field.value.type.VectorType();
    321 
    322   GenReceiver(struct_def, code_ptr);
    323   code += " " + MakeCamel(field.name);
    324   code += "(j int) " + TypeName(field) + " ";
    325   code += OffsetPrefix(field);
    326   code += "\t\ta := rcv._tab.Vector(o)\n";
    327   code += "\t\treturn " + GenGetter(field.value.type) + "(";
    328   code += "a + flatbuffers.UOffsetT(j*";
    329   code += NumToString(InlineSize(vectortype)) + "))\n";
    330   code += "\t}\n";
    331   if (vectortype.base_type == BASE_TYPE_STRING) {
    332     code += "\treturn nil\n";
    333   } else {
    334     code += "\treturn 0\n";
    335   }
    336   code += "}\n\n";
    337 }
    338 
    339 // Begin the creator function signature.
    340 static void BeginBuilderArgs(const StructDef &struct_def,
    341                              std::string *code_ptr) {
    342   std::string &code = *code_ptr;
    343 
    344   if (code.substr(code.length() - 2) != "\n\n") {
    345       // a previous mutate has not put an extra new line
    346       code += "\n";
    347   }
    348   code += "func Create" + struct_def.name;
    349   code += "(builder *flatbuffers.Builder";
    350 }
    351 
    352 // Recursively generate arguments for a constructor, to deal with nested
    353 // structs.
    354 static void StructBuilderArgs(const StructDef &struct_def,
    355                               const char *nameprefix,
    356                               std::string *code_ptr) {
    357   for (auto it = struct_def.fields.vec.begin();
    358        it != struct_def.fields.vec.end();
    359        ++it) {
    360     auto &field = **it;
    361     if (IsStruct(field.value.type)) {
    362       // Generate arguments for a struct inside a struct. To ensure names
    363       // don't clash, and to make it obvious these arguments are constructing
    364       // a nested struct, prefix the name with the field name.
    365       StructBuilderArgs(*field.value.type.struct_def,
    366                         (nameprefix + (field.name + "_")).c_str(),
    367                         code_ptr);
    368     } else {
    369       std::string &code = *code_ptr;
    370       code += (std::string)", " + nameprefix;
    371       code += MakeCamel(field.name, false);
    372       code += " " + GenTypeBasic(field.value.type);
    373     }
    374   }
    375 }
    376 
    377 // End the creator function signature.
    378 static void EndBuilderArgs(std::string *code_ptr) {
    379   std::string &code = *code_ptr;
    380   code += ") flatbuffers.UOffsetT {\n";
    381 }
    382 
    383 // Recursively generate struct construction statements and instert manual
    384 // padding.
    385 static void StructBuilderBody(const StructDef &struct_def,
    386                               const char *nameprefix,
    387                               std::string *code_ptr) {
    388   std::string &code = *code_ptr;
    389   code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", ";
    390   code += NumToString(struct_def.bytesize) + ")\n";
    391   for (auto it = struct_def.fields.vec.rbegin();
    392        it != struct_def.fields.vec.rend();
    393        ++it) {
    394     auto &field = **it;
    395     if (field.padding)
    396       code += "\tbuilder.Pad(" + NumToString(field.padding) + ")\n";
    397     if (IsStruct(field.value.type)) {
    398       StructBuilderBody(*field.value.type.struct_def,
    399                         (nameprefix + (field.name + "_")).c_str(),
    400                         code_ptr);
    401     } else {
    402       code += "\tbuilder.Prepend" + GenMethod(field) + "(";
    403       code += nameprefix + MakeCamel(field.name, false) + ")\n";
    404     }
    405   }
    406 }
    407 
    408 static void EndBuilderBody(std::string *code_ptr) {
    409   std::string &code = *code_ptr;
    410   code += "\treturn builder.Offset()\n";
    411   code += "}\n";
    412 }
    413 
    414 // Get the value of a table's starting offset.
    415 static void GetStartOfTable(const StructDef &struct_def,
    416                             std::string *code_ptr) {
    417   std::string &code = *code_ptr;
    418   code += "func " + struct_def.name + "Start";
    419   code += "(builder *flatbuffers.Builder) {\n";
    420   code += "\tbuilder.StartObject(";
    421   code += NumToString(struct_def.fields.vec.size());
    422   code += ")\n}\n";
    423 }
    424 
    425 // Set the value of a table's field.
    426 static void BuildFieldOfTable(const StructDef &struct_def,
    427                               const FieldDef &field,
    428                               const size_t offset,
    429                               std::string *code_ptr) {
    430   std::string &code = *code_ptr;
    431   code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
    432   code += "(builder *flatbuffers.Builder, ";
    433   code += MakeCamel(field.name, false) + " ";
    434   if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
    435     code += "flatbuffers.UOffsetT";
    436   } else {
    437     code += GenTypeBasic(field.value.type);
    438   }
    439   code += ") {\n";
    440   code += "\tbuilder.Prepend";
    441   code += GenMethod(field) + "Slot(";
    442   code += NumToString(offset) + ", ";
    443   if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
    444     code += "flatbuffers.UOffsetT";
    445     code += "(";
    446     code += MakeCamel(field.name, false) + ")";
    447   } else {
    448     code += MakeCamel(field.name, false);
    449   }
    450   code += ", " + field.value.constant;
    451   code += ")\n}\n";
    452 }
    453 
    454 // Set the value of one of the members of a table's vector.
    455 static void BuildVectorOfTable(const StructDef &struct_def,
    456                                const FieldDef &field,
    457                                std::string *code_ptr) {
    458   std::string &code = *code_ptr;
    459   code += "func " + struct_def.name + "Start";
    460   code += MakeCamel(field.name);
    461   code += "Vector(builder *flatbuffers.Builder, numElems int) ";
    462   code += "flatbuffers.UOffsetT {\n\treturn builder.StartVector(";
    463   auto vector_type = field.value.type.VectorType();
    464   auto alignment = InlineAlignment(vector_type);
    465   auto elem_size = InlineSize(vector_type);
    466   code += NumToString(elem_size);
    467   code += ", numElems, " + NumToString(alignment);
    468   code += ")\n}\n";
    469 }
    470 
    471 // Get the offset of the end of a table.
    472 static void GetEndOffsetOnTable(const StructDef &struct_def,
    473                                 std::string *code_ptr) {
    474   std::string &code = *code_ptr;
    475   code += "func " + struct_def.name + "End";
    476   code += "(builder *flatbuffers.Builder) flatbuffers.UOffsetT ";
    477   code += "{\n\treturn builder.EndObject()\n}\n";
    478 }
    479 
    480 // Generate the receiver for function signatures.
    481 static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) {
    482   std::string &code = *code_ptr;
    483   code += "func (rcv *" + struct_def.name + ")";
    484 }
    485 
    486 // Generate a struct field getter, conditioned on its child type(s).
    487 static void GenStructAccessor(const StructDef &struct_def,
    488                               const FieldDef &field,
    489                               std::string *code_ptr) {
    490   GenComment(field.doc_comment, code_ptr, nullptr, "");
    491   if (IsScalar(field.value.type.base_type)) {
    492     if (struct_def.fixed) {
    493       GetScalarFieldOfStruct(struct_def, field, code_ptr);
    494     } else {
    495       GetScalarFieldOfTable(struct_def, field, code_ptr);
    496     }
    497   } else {
    498     switch (field.value.type.base_type) {
    499       case BASE_TYPE_STRUCT:
    500         if (struct_def.fixed) {
    501           GetStructFieldOfStruct(struct_def, field, code_ptr);
    502         } else {
    503           GetStructFieldOfTable(struct_def, field, code_ptr);
    504         }
    505         break;
    506       case BASE_TYPE_STRING:
    507         GetStringField(struct_def, field, code_ptr);
    508         break;
    509       case BASE_TYPE_VECTOR: {
    510         auto vectortype = field.value.type.VectorType();
    511         if (vectortype.base_type == BASE_TYPE_STRUCT) {
    512           GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
    513         } else {
    514           GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
    515         }
    516         break;
    517       }
    518       case BASE_TYPE_UNION:
    519         GetUnionField(struct_def, field, code_ptr);
    520         break;
    521       default:
    522         assert(0);
    523     }
    524   }
    525   if (field.value.type.base_type == BASE_TYPE_VECTOR) {
    526     GetVectorLen(struct_def, field, code_ptr);
    527     if (field.value.type.element == BASE_TYPE_UCHAR) {
    528       GetUByteSlice(struct_def, field, code_ptr);
    529     }
    530   }
    531 }
    532 
    533 // Mutate the value of a struct's scalar.
    534 static void MutateScalarFieldOfStruct(const StructDef &struct_def,
    535                                    const FieldDef &field,
    536                                    std::string *code_ptr) {
    537   std::string &code = *code_ptr;
    538   std::string type = MakeCamel(GenTypeBasic(field.value.type));
    539   std::string setter = "rcv._tab.Mutate" + type;
    540   GenReceiver(struct_def, code_ptr);
    541   code += " Mutate" + MakeCamel(field.name);
    542   code += "(n " + TypeName(field) + ") bool {\n\treturn " + setter;
    543   code += "(rcv._tab.Pos+flatbuffers.UOffsetT(";
    544   code += NumToString(field.value.offset) + "), n)\n}\n\n";
    545 }
    546 
    547 // Mutate the value of a table's scalar.
    548 static void MutateScalarFieldOfTable(const StructDef &struct_def,
    549                                   const FieldDef &field,
    550                                   std::string *code_ptr) {
    551   std::string &code = *code_ptr;
    552   std::string type = MakeCamel(GenTypeBasic(field.value.type));
    553   std::string setter = "rcv._tab.Mutate" + type + "Slot";
    554   GenReceiver(struct_def, code_ptr);
    555   code += " Mutate" + MakeCamel(field.name);
    556   code += "(n " + TypeName(field) + ") bool {\n\treturn ";
    557   code += setter + "(" + NumToString(field.value.offset) + ", n)\n";
    558   code += "}\n\n";
    559 }
    560 
    561 // Generate a struct field setter, conditioned on its child type(s).
    562 static void GenStructMutator(const StructDef &struct_def,
    563                               const FieldDef &field,
    564                               std::string *code_ptr) {
    565   GenComment(field.doc_comment, code_ptr, nullptr, "");
    566   if (IsScalar(field.value.type.base_type)) {
    567     if (struct_def.fixed) {
    568       MutateScalarFieldOfStruct(struct_def, field, code_ptr);
    569     } else {
    570       MutateScalarFieldOfTable(struct_def, field, code_ptr);
    571     }
    572   }
    573 }
    574 
    575 // Generate table constructors, conditioned on its members' types.
    576 static void GenTableBuilders(const StructDef &struct_def,
    577                              std::string *code_ptr) {
    578   GetStartOfTable(struct_def, code_ptr);
    579 
    580   for (auto it = struct_def.fields.vec.begin();
    581        it != struct_def.fields.vec.end();
    582        ++it) {
    583     auto &field = **it;
    584     if (field.deprecated) continue;
    585 
    586     auto offset = it - struct_def.fields.vec.begin();
    587     BuildFieldOfTable(struct_def, field, offset, code_ptr);
    588     if (field.value.type.base_type == BASE_TYPE_VECTOR) {
    589       BuildVectorOfTable(struct_def, field, code_ptr);
    590     }
    591   }
    592 
    593   GetEndOffsetOnTable(struct_def, code_ptr);
    594 }
    595 
    596 // Generate struct or table methods.
    597 static void GenStruct(const StructDef &struct_def,
    598                       std::string *code_ptr) {
    599   if (struct_def.generated) return;
    600 
    601   GenComment(struct_def.doc_comment, code_ptr, nullptr);
    602   BeginClass(struct_def, code_ptr);
    603   if (!struct_def.fixed) {
    604     // Generate a special accessor for the table that has been declared as
    605     // the root type.
    606     NewRootTypeFromBuffer(struct_def, code_ptr);
    607   }
    608   // Generate the Init method that sets the field in a pre-existing
    609   // accessor object. This is to allow object reuse.
    610   InitializeExisting(struct_def, code_ptr);
    611   // Generate _tab accessor
    612   GenTableAccessor(struct_def, code_ptr);
    613 
    614   // Generate struct fields accessors
    615   for (auto it = struct_def.fields.vec.begin();
    616        it != struct_def.fields.vec.end();
    617        ++it) {
    618     auto &field = **it;
    619     if (field.deprecated) continue;
    620 
    621     GenStructAccessor(struct_def, field, code_ptr);
    622     GenStructMutator(struct_def, field, code_ptr);
    623   }
    624 
    625   // Generate builders
    626   if (struct_def.fixed) {
    627     // create a struct constructor function
    628     GenStructBuilder(struct_def, code_ptr);
    629   } else {
    630     // Create a set of functions that allow table construction.
    631     GenTableBuilders(struct_def, code_ptr);
    632   }
    633 }
    634 
    635 // Generate enum declarations.
    636 static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
    637   if (enum_def.generated) return;
    638 
    639   GenComment(enum_def.doc_comment, code_ptr, nullptr);
    640   BeginEnum(code_ptr);
    641   for (auto it = enum_def.vals.vec.begin();
    642        it != enum_def.vals.vec.end();
    643        ++it) {
    644     auto &ev = **it;
    645     GenComment(ev.doc_comment, code_ptr, nullptr, "\t");
    646     EnumMember(enum_def, ev, code_ptr);
    647   }
    648   EndEnum(code_ptr);
    649 
    650   BeginEnumNames(enum_def, code_ptr);
    651   for (auto it = enum_def.vals.vec.begin();
    652        it != enum_def.vals.vec.end();
    653        ++it) {
    654     auto &ev = **it;
    655     EnumNameMember(enum_def, ev, code_ptr);
    656   }
    657   EndEnumNames(code_ptr);
    658 }
    659 
    660 // Returns the function name that is able to read a value of the given type.
    661 static std::string GenGetter(const Type &type) {
    662   switch (type.base_type) {
    663     case BASE_TYPE_STRING: return "rcv._tab.ByteVector";
    664     case BASE_TYPE_UNION: return "rcv._tab.Union";
    665     case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
    666     default:
    667       return "rcv._tab.Get" + MakeCamel(GenTypeGet(type));
    668   }
    669 }
    670 
    671 // Returns the method name for use with add/put calls.
    672 static std::string GenMethod(const FieldDef &field) {
    673   return IsScalar(field.value.type.base_type)
    674     ? MakeCamel(GenTypeBasic(field.value.type))
    675     : (IsStruct(field.value.type) ? "Struct" : "UOffsetT");
    676 }
    677 
    678 static std::string GenTypeBasic(const Type &type) {
    679   static const char *ctypename[] = {
    680     #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
    681       #GTYPE,
    682       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
    683     #undef FLATBUFFERS_TD
    684   };
    685   return ctypename[type.base_type];
    686 }
    687 
    688 static std::string GenTypePointer(const Type &type) {
    689   switch (type.base_type) {
    690     case BASE_TYPE_STRING:
    691       return "[]byte";
    692     case BASE_TYPE_VECTOR:
    693       return GenTypeGet(type.VectorType());
    694     case BASE_TYPE_STRUCT:
    695       return type.struct_def->name;
    696     case BASE_TYPE_UNION:
    697       // fall through
    698     default:
    699       return "*flatbuffers.Table";
    700   }
    701 }
    702 
    703 static std::string GenTypeGet(const Type &type) {
    704   return IsScalar(type.base_type)
    705     ? GenTypeBasic(type)
    706     : GenTypePointer(type);
    707 }
    708 
    709 static std::string TypeName(const FieldDef &field) {
    710   return GenTypeGet(field.value.type);
    711 }
    712 
    713 // Create a struct with a builder and the struct's arguments.
    714 static void GenStructBuilder(const StructDef &struct_def,
    715                              std::string *code_ptr) {
    716   BeginBuilderArgs(struct_def, code_ptr);
    717   StructBuilderArgs(struct_def, "", code_ptr);
    718   EndBuilderArgs(code_ptr);
    719 
    720   StructBuilderBody(struct_def, "", code_ptr);
    721   EndBuilderBody(code_ptr);
    722 }
    723 
    724 class GoGenerator : public BaseGenerator {
    725  public:
    726   GoGenerator(const Parser &parser, const std::string &path,
    727               const std::string &file_name)
    728       : BaseGenerator(parser, path, file_name, "" /* not used*/,
    729                       "" /* not used */){};
    730   bool generate() {
    731     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
    732          ++it) {
    733       std::string enumcode;
    734       go::GenEnum(**it, &enumcode);
    735       if (!SaveType(**it, enumcode, false)) return false;
    736     }
    737 
    738     for (auto it = parser_.structs_.vec.begin();
    739          it != parser_.structs_.vec.end(); ++it) {
    740       std::string declcode;
    741       go::GenStruct(**it, &declcode);
    742       if (!SaveType(**it, declcode, true)) return false;
    743     }
    744 
    745     return true;
    746   }
    747 
    748  private:
    749   // Begin by declaring namespace and imports.
    750   void BeginFile(const std::string name_space_name, const bool needs_imports,
    751                  std::string *code_ptr) {
    752     std::string &code = *code_ptr;
    753     code = code + "// " + FlatBuffersGeneratedWarning();
    754     code += "package " + name_space_name + "\n\n";
    755     if (needs_imports) {
    756       code += "import (\n";
    757       code += "\tflatbuffers \"github.com/google/flatbuffers/go\"\n";
    758       code += ")\n\n";
    759     }
    760   }
    761 
    762   // Save out the generated code for a Go Table type.
    763   bool SaveType(const Definition &def, const std::string &classcode,
    764                 bool needs_imports) {
    765     if (!classcode.length()) return true;
    766 
    767     std::string code = "";
    768     BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
    769     code += classcode;
    770     std::string filename =
    771         NamespaceDir(*def.defined_namespace) + def.name + ".go";
    772     return SaveFile(filename.c_str(), code, false);
    773   }
    774 };
    775 }  // namespace go
    776 
    777 bool GenerateGo(const Parser &parser, const std::string &path,
    778                 const std::string &file_name) {
    779   go::GoGenerator generator(parser, path, file_name);
    780   return generator.generate();
    781 }
    782 
    783 }  // namespace flatbuffers
    784