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