xref: /aosp_15_r20/external/flatbuffers/src/idl_gen_rust.cpp (revision 890232f25432b36107d06881e0a25aaa6b473652)
1 /*
2  * Copyright 2018 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 "flatbuffers/code_generators.h"
20 #include "flatbuffers/flatbuffers.h"
21 #include "flatbuffers/idl.h"
22 #include "flatbuffers/util.h"
23 #include "idl_namer.h"
24 
25 namespace flatbuffers {
26 namespace {
27 
RustDefaultConfig()28 static Namer::Config RustDefaultConfig() {
29   // Historical note: We've been using "keep" casing since the original
30   // implementation, presumably because Flatbuffers schema style and Rust style
31   // roughly align. We are not going to enforce proper casing since its an
32   // unnecessary breaking change.
33   return { /*types=*/Case::kKeep,
34            /*constants=*/Case::kScreamingSnake,
35            /*methods=*/Case::kSnake,
36            /*functions=*/Case::kSnake,
37            /*fields=*/Case::kKeep,
38            /*variables=*/Case::kUnknown,  // Unused.
39            /*variants=*/Case::kKeep,
40            /*enum_variant_seperator=*/"::",
41            /*escape_keywords=*/Namer::Config::Escape::BeforeConvertingCase,
42            /*namespaces=*/Case::kSnake,
43            /*namespace_seperator=*/"::",
44            /*object_prefix=*/"",
45            /*object_suffix=*/"T",
46            /*keyword_prefix=*/"",
47            /*keyword_suffix=*/"_",
48            /*filenames=*/Case::kSnake,
49            /*directories=*/Case::kSnake,
50            /*output_path=*/"",
51            /*filename_suffix=*/"_generated",
52            /*filename_extension=*/".rs" };
53 }
54 
RustKeywords()55 static std::set<std::string> RustKeywords() {
56   return {
57     // https://doc.rust-lang.org/book/second-edition/appendix-01-keywords.html
58     "as",
59     "break",
60     "const",
61     "continue",
62     "crate",
63     "else",
64     "enum",
65     "extern",
66     "false",
67     "fn",
68     "for",
69     "if",
70     "impl",
71     "in",
72     "let",
73     "loop",
74     "match",
75     "mod",
76     "move",
77     "mut",
78     "pub",
79     "ref",
80     "return",
81     "Self",
82     "self",
83     "static",
84     "struct",
85     "super",
86     "trait",
87     "true",
88     "type",
89     "unsafe",
90     "use",
91     "where",
92     "while",
93     // future possible keywords
94     "abstract",
95     "alignof",
96     "become",
97     "box",
98     "do",
99     "final",
100     "macro",
101     "offsetof",
102     "override",
103     "priv",
104     "proc",
105     "pure",
106     "sizeof",
107     "typeof",
108     "unsized",
109     "virtual",
110     "yield",
111     // other rust terms we should not use
112     "std",
113     "usize",
114     "isize",
115     "u8",
116     "i8",
117     "u16",
118     "i16",
119     "u32",
120     "i32",
121     "u64",
122     "i64",
123     "u128",
124     "i128",
125     "f32",
126     "f64",
127     // Terms that we use ourselves
128     "follow",
129     "push",
130     "size",
131     "alignment",
132     "to_little_endian",
133     "from_little_endian",
134     "ENUM_MAX",
135     "ENUM_MIN",
136     "ENUM_VALUES",
137   };
138 }
139 
140 // Encapsulate all logical field types in this enum. This allows us to write
141 // field logic based on type switches, instead of branches on the properties
142 // set on the Type.
143 // TODO(rw): for backwards compatibility, we can't use a strict `enum class`
144 //           declaration here. could we use the `-Wswitch-enum` warning to
145 //           achieve the same effect?
146 enum FullType {
147   ftInteger = 0,
148   ftFloat = 1,
149   ftBool = 2,
150 
151   ftStruct = 3,
152   ftTable = 4,
153 
154   ftEnumKey = 5,
155   ftUnionKey = 6,
156 
157   ftUnionValue = 7,
158 
159   // TODO(rw): bytestring?
160   ftString = 8,
161 
162   ftVectorOfInteger = 9,
163   ftVectorOfFloat = 10,
164   ftVectorOfBool = 11,
165   ftVectorOfEnumKey = 12,
166   ftVectorOfStruct = 13,
167   ftVectorOfTable = 14,
168   ftVectorOfString = 15,
169   ftVectorOfUnionValue = 16,
170 
171   ftArrayOfBuiltin = 17,
172   ftArrayOfEnum = 18,
173   ftArrayOfStruct = 19,
174 };
175 
176 // Convert a Type to a FullType (exhaustive).
GetFullType(const Type & type)177 static FullType GetFullType(const Type &type) {
178   // N.B. The order of these conditionals matters for some types.
179 
180   if (IsString(type)) {
181     return ftString;
182   } else if (type.base_type == BASE_TYPE_STRUCT) {
183     if (type.struct_def->fixed) {
184       return ftStruct;
185     } else {
186       return ftTable;
187     }
188   } else if (IsVector(type)) {
189     switch (GetFullType(type.VectorType())) {
190       case ftInteger: {
191         return ftVectorOfInteger;
192       }
193       case ftFloat: {
194         return ftVectorOfFloat;
195       }
196       case ftBool: {
197         return ftVectorOfBool;
198       }
199       case ftStruct: {
200         return ftVectorOfStruct;
201       }
202       case ftTable: {
203         return ftVectorOfTable;
204       }
205       case ftString: {
206         return ftVectorOfString;
207       }
208       case ftEnumKey: {
209         return ftVectorOfEnumKey;
210       }
211       case ftUnionKey:
212       case ftUnionValue: {
213         FLATBUFFERS_ASSERT(false && "vectors of unions are unsupported");
214         break;
215       }
216       default: {
217         FLATBUFFERS_ASSERT(false && "vector of vectors are unsupported");
218       }
219     }
220   } else if (IsArray(type)) {
221     switch (GetFullType(type.VectorType())) {
222       case ftInteger:
223       case ftFloat:
224       case ftBool: {
225         return ftArrayOfBuiltin;
226       }
227       case ftStruct: {
228         return ftArrayOfStruct;
229       }
230       case ftEnumKey: {
231         return ftArrayOfEnum;
232       }
233       default: {
234         FLATBUFFERS_ASSERT(false && "Unsupported type for fixed array");
235       }
236     }
237   } else if (type.enum_def != nullptr) {
238     if (type.enum_def->is_union) {
239       if (type.base_type == BASE_TYPE_UNION) {
240         return ftUnionValue;
241       } else if (IsInteger(type.base_type)) {
242         return ftUnionKey;
243       } else {
244         FLATBUFFERS_ASSERT(false && "unknown union field type");
245       }
246     } else {
247       return ftEnumKey;
248     }
249   } else if (IsScalar(type.base_type)) {
250     if (IsBool(type.base_type)) {
251       return ftBool;
252     } else if (IsInteger(type.base_type)) {
253       return ftInteger;
254     } else if (IsFloat(type.base_type)) {
255       return ftFloat;
256     } else {
257       FLATBUFFERS_ASSERT(false && "unknown number type");
258     }
259   }
260 
261   FLATBUFFERS_ASSERT(false && "completely unknown type");
262 
263   // this is only to satisfy the compiler's return analysis.
264   return ftBool;
265 }
266 
IsBitFlagsEnum(const EnumDef & enum_def)267 static bool IsBitFlagsEnum(const EnumDef &enum_def) {
268   return enum_def.attributes.Lookup("bit_flags") != nullptr;
269 }
270 
271 // TableArgs make required non-scalars "Option<_>".
272 // TODO(cneo): Rework how we do defaults and stuff.
IsOptionalToBuilder(const FieldDef & field)273 static bool IsOptionalToBuilder(const FieldDef &field) {
274   return field.IsOptional() || !IsScalar(field.value.type.base_type);
275 }
276 } // namespace
277 
GenerateRustModuleRootFile(const Parser & parser,const std::string & output_dir)278 bool GenerateRustModuleRootFile(const Parser &parser,
279                                 const std::string &output_dir) {
280   if (!parser.opts.rust_module_root_file) {
281     // Don't generate a root file when generating one file. This isn't an error
282     // so return true.
283     return true;
284   }
285   Namer namer(WithFlagOptions(RustDefaultConfig(), parser.opts, output_dir),
286               RustKeywords());
287   // We gather the symbols into a tree of namespaces (which are rust mods) and
288   // generate a file that gathers them all.
289   struct Module {
290     std::map<std::string, Module> sub_modules;
291     std::vector<std::string> generated_files;
292     // Add a symbol into the tree.
293     void Insert(const Namer &namer, const Definition *s) {
294       const Definition &symbol = *s;
295       Module *current_module = this;
296       for (auto it = symbol.defined_namespace->components.begin();
297            it != symbol.defined_namespace->components.end(); it++) {
298         std::string ns_component = namer.Namespace(*it);
299         current_module = &current_module->sub_modules[ns_component];
300       }
301       current_module->generated_files.push_back(
302           namer.File(symbol.name, SkipFile::Extension));
303     }
304     // Recursively create the importer file.
305     void GenerateImports(CodeWriter &code) {
306       for (auto it = sub_modules.begin(); it != sub_modules.end(); it++) {
307         code += "pub mod " + it->first + " {";
308         code.IncrementIdentLevel();
309         code += "use super::*;";
310         it->second.GenerateImports(code);
311         code.DecrementIdentLevel();
312         code += "} // " + it->first;
313       }
314       for (auto it = generated_files.begin(); it != generated_files.end();
315            it++) {
316         code += "mod " + *it + ";";
317         code += "pub use self::" + *it + "::*;";
318       }
319     }
320   };
321   Module root_module;
322   for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end();
323        it++) {
324     root_module.Insert(namer, *it);
325   }
326   for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end();
327        it++) {
328     root_module.Insert(namer, *it);
329   }
330   CodeWriter code("  ");
331   // TODO(caspern): Move generated warning out of BaseGenerator.
332   code +=
333       "// Automatically generated by the Flatbuffers compiler. "
334       "Do not modify.";
335   code += "// @generated";
336   root_module.GenerateImports(code);
337   const bool success =
338       SaveFile((output_dir + "mod.rs").c_str(), code.ToString(), false);
339   code.Clear();
340   return success;
341 }
342 
343 namespace rust {
344 
345 class RustGenerator : public BaseGenerator {
346  public:
RustGenerator(const Parser & parser,const std::string & path,const std::string & file_name)347   RustGenerator(const Parser &parser, const std::string &path,
348                 const std::string &file_name)
349       : BaseGenerator(parser, path, file_name, "", "::", "rs"),
350         cur_name_space_(nullptr),
351         namer_(WithFlagOptions(RustDefaultConfig(), parser.opts, path),
352                RustKeywords()) {
353     // TODO: Namer flag overrides should be in flatc or flatc_main.
354     code_.SetPadding("  ");
355   }
356 
generate()357   bool generate() {
358     if (!parser_.opts.rust_module_root_file) {
359       return GenerateOneFile();
360     } else {
361       return GenerateIndividualFiles();
362     }
363   }
364 
365   template<typename T>
GenerateSymbols(const SymbolTable<T> & symbols,std::function<void (const T &)> gen_symbol)366   bool GenerateSymbols(const SymbolTable<T> &symbols,
367                        std::function<void(const T &)> gen_symbol) {
368     for (auto it = symbols.vec.begin(); it != symbols.vec.end(); it++) {
369       const T &symbol = **it;
370       if (symbol.generated) continue;
371       code_.Clear();
372       code_ += "// " + std::string(FlatBuffersGeneratedWarning());
373       code_ += "// @generated";
374       code_ += "extern crate alloc;";
375       code_ += "extern crate flatbuffers;";
376       code_ += "use alloc::boxed::Box;";
377       code_ += "use alloc::string::{String, ToString};";
378       code_ += "use alloc::vec::Vec;";
379       code_ += "use core::mem;";
380       code_ += "use core::cmp::Ordering;";
381       if (parser_.opts.rust_serialize) {
382         code_ += "extern crate serde;";
383         code_ +=
384             "use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
385       }
386       code_ += "use self::flatbuffers::{EndianScalar, Follow};";
387       code_ += "use super::*;";
388       cur_name_space_ = symbol.defined_namespace;
389       gen_symbol(symbol);
390 
391       const std::string directories =
392           namer_.Directories(*symbol.defined_namespace);
393       EnsureDirExists(directories);
394       const std::string file_path = directories + namer_.File(symbol);
395       const bool save_success =
396           SaveFile(file_path.c_str(), code_.ToString(), /*binary=*/false);
397       if (!save_success) return false;
398     }
399     return true;
400   }
401 
GenerateIndividualFiles()402   bool GenerateIndividualFiles() {
403     code_.Clear();
404     // Don't bother with imports. Use absolute paths everywhere.
405     return GenerateSymbols<EnumDef>(
406                parser_.enums_, [&](const EnumDef &e) { this->GenEnum(e); }) &&
407            GenerateSymbols<StructDef>(
408                parser_.structs_, [&](const StructDef &s) {
409                  if (s.fixed) {
410                    this->GenStruct(s);
411                  } else {
412                    this->GenTable(s);
413                    if (this->parser_.opts.generate_object_based_api) {
414                      this->GenTableObject(s);
415                    }
416                  }
417                  if (this->parser_.root_struct_def_ == &s) {
418                    this->GenRootTableFuncs(s);
419                  }
420                });
421   }
422 
423   // Generates code organized by .fbs files. This is broken legacy behavior
424   // that does not work with multiple fbs files with shared namespaces.
425   // Iterate through all definitions we haven't generated code for (enums,
426   // structs, and tables) and output them to a single file.
GenerateOneFile()427   bool GenerateOneFile() {
428     code_.Clear();
429     code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
430     code_ += "// @generated";
431 
432     assert(!cur_name_space_);
433 
434     // Generate imports for the global scope in case no namespace is used
435     // in the schema file.
436     GenNamespaceImports(0);
437     code_ += "";
438 
439     // Generate all code in their namespaces, once, because Rust does not
440     // permit re-opening modules.
441     //
442     // TODO(rw): Use a set data structure to reduce namespace evaluations from
443     //           O(n**2) to O(n).
444     for (auto ns_it = parser_.namespaces_.begin();
445          ns_it != parser_.namespaces_.end(); ++ns_it) {
446       const auto &ns = *ns_it;
447 
448       // Generate code for all the enum declarations.
449       for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
450            ++it) {
451         const auto &enum_def = **it;
452         if (enum_def.defined_namespace == ns && !enum_def.generated) {
453           SetNameSpace(enum_def.defined_namespace);
454           GenEnum(enum_def);
455         }
456       }
457 
458       // Generate code for all structs.
459       for (auto it = parser_.structs_.vec.begin();
460            it != parser_.structs_.vec.end(); ++it) {
461         const auto &struct_def = **it;
462         if (struct_def.defined_namespace == ns && struct_def.fixed &&
463             !struct_def.generated) {
464           SetNameSpace(struct_def.defined_namespace);
465           GenStruct(struct_def);
466         }
467       }
468 
469       // Generate code for all tables.
470       for (auto it = parser_.structs_.vec.begin();
471            it != parser_.structs_.vec.end(); ++it) {
472         const auto &struct_def = **it;
473         if (struct_def.defined_namespace == ns && !struct_def.fixed &&
474             !struct_def.generated) {
475           SetNameSpace(struct_def.defined_namespace);
476           GenTable(struct_def);
477           if (parser_.opts.generate_object_based_api) {
478             GenTableObject(struct_def);
479           }
480         }
481       }
482 
483       // Generate global helper functions.
484       if (parser_.root_struct_def_) {
485         auto &struct_def = *parser_.root_struct_def_;
486         if (struct_def.defined_namespace != ns) { continue; }
487         SetNameSpace(struct_def.defined_namespace);
488         GenRootTableFuncs(struct_def);
489       }
490     }
491     if (cur_name_space_) SetNameSpace(nullptr);
492 
493     const auto file_path = GeneratedFileName(path_, file_name_, parser_.opts);
494     const auto final_code = code_.ToString();
495     return SaveFile(file_path.c_str(), final_code, false);
496   }
497 
498  private:
499   CodeWriter code_;
500 
501   // This tracks the current namespace so we can insert namespace declarations.
502   const Namespace *cur_name_space_;
503 
CurrentNameSpace() const504   const Namespace *CurrentNameSpace() const { return cur_name_space_; }
505 
506   // Determine if a Type needs a lifetime template parameter when used in the
507   // Rust builder args.
TableBuilderTypeNeedsLifetime(const Type & type) const508   bool TableBuilderTypeNeedsLifetime(const Type &type) const {
509     switch (GetFullType(type)) {
510       case ftInteger:
511       case ftFloat:
512       case ftBool:
513       case ftEnumKey:
514       case ftUnionKey:
515       case ftUnionValue: {
516         return false;
517       }
518       default: {
519         return true;
520       }
521     }
522   }
523 
524   // Determine if a table args rust type needs a lifetime template parameter.
TableBuilderArgsNeedsLifetime(const StructDef & struct_def) const525   bool TableBuilderArgsNeedsLifetime(const StructDef &struct_def) const {
526     FLATBUFFERS_ASSERT(!struct_def.fixed);
527 
528     for (auto it = struct_def.fields.vec.begin();
529          it != struct_def.fields.vec.end(); ++it) {
530       const auto &field = **it;
531       if (field.deprecated) { continue; }
532 
533       if (TableBuilderTypeNeedsLifetime(field.value.type)) { return true; }
534     }
535 
536     return false;
537   }
538 
NamespacedNativeName(const EnumDef & def)539   std::string NamespacedNativeName(const EnumDef &def) {
540     return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
541   }
NamespacedNativeName(const StructDef & def)542   std::string NamespacedNativeName(const StructDef &def) {
543     return WrapInNameSpace(def.defined_namespace, namer_.ObjectType(def));
544   }
545 
WrapInNameSpace(const Definition & def) const546   std::string WrapInNameSpace(const Definition &def) const {
547     return WrapInNameSpace(def.defined_namespace,
548                            namer_.EscapeKeyword(def.name));
549   }
WrapInNameSpace(const Namespace * ns,const std::string & name) const550   std::string WrapInNameSpace(const Namespace *ns,
551                               const std::string &name) const {
552     if (CurrentNameSpace() == ns) return name;
553     std::string prefix = GetRelativeNamespaceTraversal(CurrentNameSpace(), ns);
554     return prefix + name;
555   }
556 
557   // Determine the relative namespace traversal needed to reference one
558   // namespace from another namespace. This is useful because it does not force
559   // the user to have a particular file layout. (If we output absolute
560   // namespace paths, that may require users to organize their Rust crates in a
561   // particular way.)
GetRelativeNamespaceTraversal(const Namespace * src,const Namespace * dst) const562   std::string GetRelativeNamespaceTraversal(const Namespace *src,
563                                             const Namespace *dst) const {
564     // calculate the path needed to reference dst from src.
565     // example: f(A::B::C, A::B::C) -> (none)
566     // example: f(A::B::C, A::B)    -> super::
567     // example: f(A::B::C, A::B::D) -> super::D
568     // example: f(A::B::C, A)       -> super::super::
569     // example: f(A::B::C, D)       -> super::super::super::D
570     // example: f(A::B::C, D::E)    -> super::super::super::D::E
571     // example: f(A, D::E)          -> super::D::E
572     // does not include leaf object (typically a struct type).
573 
574     std::stringstream stream;
575     size_t common = 0;
576     std::vector<std::string> s, d;
577     if (src) s = src->components;
578     if (dst) d = dst->components;
579     while (common < s.size() && common < d.size() && s[common] == d[common])
580       common++;
581     // If src namespace is empty, this must be an absolute path.
582     for (size_t i = common; i < s.size(); i++) stream << "super::";
583     for (size_t i = common; i < d.size(); i++)
584       stream << namer_.Namespace(d[i]) + "::";
585     return stream.str();
586   }
587 
588   // Generate a comment from the schema.
GenComment(const std::vector<std::string> & dc,const char * prefix="")589   void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
590     for (auto it = dc.begin(); it != dc.end(); it++) {
591       code_ += std::string(prefix) + "///" + *it;
592     }
593   }
594 
595   // Return a Rust type from the table in idl.h.
GetTypeBasic(const Type & type) const596   std::string GetTypeBasic(const Type &type) const {
597     switch (GetFullType(type)) {
598       case ftInteger:
599       case ftFloat:
600       case ftBool:
601       case ftEnumKey:
602       case ftUnionKey: {
603         break;
604       }
605       default: {
606         FLATBUFFERS_ASSERT(false && "incorrect type given");
607       }
608     }
609 
610     // clang-format off
611     static const char * const ctypename[] = {
612     #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
613                            RTYPE, ...) \
614       #RTYPE,
615       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
616     #undef FLATBUFFERS_TD
617     };
618     // clang-format on
619 
620     if (type.enum_def) { return WrapInNameSpace(*type.enum_def); }
621     return ctypename[type.base_type];
622   }
623 
624   // Look up the native type for an enum. This will always be an integer like
625   // u8, i32, etc.
GetEnumTypeForDecl(const Type & type)626   std::string GetEnumTypeForDecl(const Type &type) {
627     const auto ft = GetFullType(type);
628     if (!(ft == ftEnumKey || ft == ftUnionKey)) {
629       FLATBUFFERS_ASSERT(false && "precondition failed in GetEnumTypeForDecl");
630     }
631 
632     // clang-format off
633     static const char *ctypename[] = {
634     #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
635                            RTYPE, ...) \
636       #RTYPE,
637       FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
638     #undef FLATBUFFERS_TD
639     };
640     // clang-format on
641 
642     // Enums can be bools, but their Rust representation must be a u8, as used
643     // in the repr attribute (#[repr(bool)] is an invalid attribute).
644     if (type.base_type == BASE_TYPE_BOOL) return "u8";
645     return ctypename[type.base_type];
646   }
647 
648   // Return a Rust type for any type (scalar, table, struct) specifically for
649   // using a FlatBuffer.
GetTypeGet(const Type & type) const650   std::string GetTypeGet(const Type &type) const {
651     switch (GetFullType(type)) {
652       case ftInteger:
653       case ftFloat:
654       case ftBool:
655       case ftEnumKey:
656       case ftUnionKey: {
657         return GetTypeBasic(type);
658       }
659       case ftArrayOfBuiltin:
660       case ftArrayOfEnum:
661       case ftArrayOfStruct: {
662         return "[" + GetTypeGet(type.VectorType()) + "; " +
663                NumToString(type.fixed_length) + "]";
664       }
665       case ftTable: {
666         return WrapInNameSpace(type.struct_def->defined_namespace,
667                                type.struct_def->name) +
668                "<'a>";
669       }
670       default: {
671         return WrapInNameSpace(type.struct_def->defined_namespace,
672                                type.struct_def->name);
673       }
674     }
675   }
676 
GetEnumValue(const EnumDef & enum_def,const EnumVal & enum_val) const677   std::string GetEnumValue(const EnumDef &enum_def,
678                            const EnumVal &enum_val) const {
679     return namer_.EnumVariant(enum_def, enum_val);
680   }
681 
682   // 1 suffix since old C++ can't figure out the overload.
ForAllEnumValues1(const EnumDef & enum_def,std::function<void (const EnumVal &)> cb)683   void ForAllEnumValues1(const EnumDef &enum_def,
684                          std::function<void(const EnumVal &)> cb) {
685     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
686       const auto &ev = **it;
687       code_.SetValue("VARIANT", namer_.Variant(ev));
688       code_.SetValue("VALUE", enum_def.ToString(ev));
689       code_.IncrementIdentLevel();
690       cb(ev);
691       code_.DecrementIdentLevel();
692     }
693   }
ForAllEnumValues(const EnumDef & enum_def,std::function<void ()> cb)694   void ForAllEnumValues(const EnumDef &enum_def, std::function<void()> cb) {
695     std::function<void(const EnumVal &)> wrapped = [&](const EnumVal &unused) {
696       (void)unused;
697       cb();
698     };
699     ForAllEnumValues1(enum_def, wrapped);
700   }
701   // Generate an enum declaration,
702   // an enum string lookup table,
703   // an enum match function,
704   // and an enum array of values
GenEnum(const EnumDef & enum_def)705   void GenEnum(const EnumDef &enum_def) {
706     const bool is_private = parser_.opts.no_leak_private_annotations &&
707         (enum_def.attributes.Lookup("private") != nullptr);
708     code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
709     code_.SetValue("ENUM_TY", namer_.Type(enum_def));
710     code_.SetValue("BASE_TYPE", GetEnumTypeForDecl(enum_def.underlying_type));
711     code_.SetValue("ENUM_NAMESPACE", namer_.Namespace(enum_def.name));
712     code_.SetValue("ENUM_CONSTANT", namer_.Constant(enum_def.name));
713     const EnumVal *minv = enum_def.MinValue();
714     const EnumVal *maxv = enum_def.MaxValue();
715     FLATBUFFERS_ASSERT(minv && maxv);
716     code_.SetValue("ENUM_MIN_BASE_VALUE", enum_def.ToString(*minv));
717     code_.SetValue("ENUM_MAX_BASE_VALUE", enum_def.ToString(*maxv));
718 
719     if (IsBitFlagsEnum(enum_def)) {
720       // Defer to the convenient and canonical bitflags crate. We declare it in
721       // a module to #allow camel case constants in a smaller scope. This
722       // matches Flatbuffers c-modeled enums where variants are associated
723       // constants but in camel case.
724       code_ += "#[allow(non_upper_case_globals)]";
725       code_ += "mod bitflags_{{ENUM_NAMESPACE}} {";
726       code_ += "  flatbuffers::bitflags::bitflags! {";
727       GenComment(enum_def.doc_comment, "    ");
728       code_ += "    #[derive(Default)]";
729       code_ += "    {{ACCESS_TYPE}} struct {{ENUM_TY}}: {{BASE_TYPE}} {";
730       ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
731         this->GenComment(ev.doc_comment, "    ");
732         code_ += "    const {{VARIANT}} = {{VALUE}};";
733       });
734       code_ += "    }";
735       code_ += "  }";
736       code_ += "}";
737       code_ += "pub use self::bitflags_{{ENUM_NAMESPACE}}::{{ENUM_TY}};";
738       code_ += "";
739 
740       code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
741       code_.SetValue("INTO_BASE", "self.bits()");
742     } else {
743       // Normal, c-modelled enums.
744       // Deprecated associated constants;
745       const std::string deprecation_warning =
746           "#[deprecated(since = \"2.0.0\", note = \"Use associated constants"
747           " instead. This will no longer be generated in 2021.\")]";
748       code_ += deprecation_warning;
749       code_ +=
750           "pub const ENUM_MIN_{{ENUM_CONSTANT}}: {{BASE_TYPE}}"
751           " = {{ENUM_MIN_BASE_VALUE}};";
752       code_ += deprecation_warning;
753       code_ +=
754           "pub const ENUM_MAX_{{ENUM_CONSTANT}}: {{BASE_TYPE}}"
755           " = {{ENUM_MAX_BASE_VALUE}};";
756       auto num_fields = NumToString(enum_def.size());
757       code_ += deprecation_warning;
758       code_ += "#[allow(non_camel_case_types)]";
759       code_ += "pub const ENUM_VALUES_{{ENUM_CONSTANT}}: [{{ENUM_TY}}; " +
760                num_fields + "] = [";
761       ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
762         code_ += namer_.EnumVariant(enum_def, ev) + ",";
763       });
764       code_ += "];";
765       code_ += "";
766 
767       GenComment(enum_def.doc_comment);
768       // Derive Default to be 0. flatc enforces this when the enum
769       // is put into a struct, though this isn't documented behavior, it is
770       // needed to derive defaults in struct objects.
771       code_ +=
772           "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, "
773           "Default)]";
774       code_ += "#[repr(transparent)]";
775       code_ += "{{ACCESS_TYPE}} struct {{ENUM_TY}}(pub {{BASE_TYPE}});";
776       code_ += "#[allow(non_upper_case_globals)]";
777       code_ += "impl {{ENUM_TY}} {";
778       ForAllEnumValues1(enum_def, [&](const EnumVal &ev) {
779         this->GenComment(ev.doc_comment);
780         code_ += "pub const {{VARIANT}}: Self = Self({{VALUE}});";
781       });
782       code_ += "";
783       // Generate Associated constants
784       code_ += "  pub const ENUM_MIN: {{BASE_TYPE}} = {{ENUM_MIN_BASE_VALUE}};";
785       code_ += "  pub const ENUM_MAX: {{BASE_TYPE}} = {{ENUM_MAX_BASE_VALUE}};";
786       code_ += "  pub const ENUM_VALUES: &'static [Self] = &[";
787       ForAllEnumValues(enum_def, [&]() { code_ += "  Self::{{VARIANT}},"; });
788       code_ += "  ];";
789       code_ += "  /// Returns the variant's name or \"\" if unknown.";
790       code_ += "  pub fn variant_name(self) -> Option<&'static str> {";
791       code_ += "    match self {";
792       ForAllEnumValues(enum_def, [&]() {
793         code_ += "    Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
794       });
795       code_ += "      _ => None,";
796       code_ += "    }";
797       code_ += "  }";
798       code_ += "}";
799 
800       // Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
801       code_ += "impl core::fmt::Debug for {{ENUM_TY}} {";
802       code_ +=
803           "  fn fmt(&self, f: &mut core::fmt::Formatter) ->"
804           " core::fmt::Result {";
805       code_ += "    if let Some(name) = self.variant_name() {";
806       code_ += "      f.write_str(name)";
807       code_ += "    } else {";
808       code_ += "      f.write_fmt(format_args!(\"<UNKNOWN {:?}>\", self.0))";
809       code_ += "    }";
810       code_ += "  }";
811       code_ += "}";
812 
813       code_.SetValue("FROM_BASE", "Self(b)");
814       code_.SetValue("INTO_BASE", "self.0");
815     }
816 
817     // Implement serde::Serialize
818     if (parser_.opts.rust_serialize) {
819       code_ += "impl Serialize for {{ENUM_TY}} {";
820       code_ +=
821           "  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
822       code_ += "  where";
823       code_ += "    S: Serializer,";
824       code_ += "  {";
825       if (IsBitFlagsEnum(enum_def)) {
826         code_ += "    serializer.serialize_u32(self.bits() as u32)";
827       } else {
828         code_ +=
829             "    serializer.serialize_unit_variant(\"{{ENUM_TY}}\", self.0 "
830             "as "
831             "u32, self.variant_name().unwrap())";
832       }
833       code_ += "  }";
834       code_ += "}";
835       code_ += "";
836     }
837 
838     // Generate Follow and Push so we can serialize and stuff.
839     code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_TY}} {";
840     code_ += "  type Inner = Self;";
841     code_ += "  #[inline]";
842     code_ += "  fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
843     code_ += "    let b = unsafe {";
844     code_ += "      flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc)";
845     code_ += "    };";
846     code_ += "    {{FROM_BASE}}";
847     code_ += "  }";
848     code_ += "}";
849     code_ += "";
850     code_ += "impl flatbuffers::Push for {{ENUM_TY}} {";
851     code_ += "    type Output = {{ENUM_TY}};";
852     code_ += "    #[inline]";
853     code_ += "    fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
854     code_ +=
855         "        unsafe { flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
856         "(dst, {{INTO_BASE}}); }";
857     code_ += "    }";
858     code_ += "}";
859     code_ += "";
860     code_ += "impl flatbuffers::EndianScalar for {{ENUM_TY}} {";
861     code_ += "  #[inline]";
862     code_ += "  fn to_little_endian(self) -> Self {";
863     code_ += "    let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
864     code_ += "    {{FROM_BASE}}";
865     code_ += "  }";
866     code_ += "  #[inline]";
867     code_ += "  #[allow(clippy::wrong_self_convention)]";
868     code_ += "  fn from_little_endian(self) -> Self {";
869     code_ += "    let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});";
870     code_ += "    {{FROM_BASE}}";
871     code_ += "  }";
872     code_ += "}";
873     code_ += "";
874 
875     // Generate verifier - deferring to the base type.
876     code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_TY}} {";
877     code_ += "  #[inline]";
878     code_ += "  fn run_verifier(";
879     code_ += "    v: &mut flatbuffers::Verifier, pos: usize";
880     code_ += "  ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
881     code_ += "    use self::flatbuffers::Verifiable;";
882     code_ += "    {{BASE_TYPE}}::run_verifier(v, pos)";
883     code_ += "  }";
884     code_ += "}";
885     code_ += "";
886     // Enums are basically integers.
887     code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_TY}} {}";
888 
889     if (enum_def.is_union) {
890       // Generate typesafe offset(s) for unions
891       code_.SetValue("UNION_TYPE", namer_.Type(enum_def));
892       code_ += "{{ACCESS_TYPE}} struct {{UNION_TYPE}}UnionTableOffset {}";
893       code_ += "";
894       if (parser_.opts.generate_object_based_api) { GenUnionObject(enum_def); }
895     }
896   }
897 
898   // TODO(cneo): dedup Object versions from non object versions.
ForAllUnionObjectVariantsBesidesNone(const EnumDef & enum_def,std::function<void ()> cb)899   void ForAllUnionObjectVariantsBesidesNone(const EnumDef &enum_def,
900                                             std::function<void()> cb) {
901     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
902       auto &enum_val = **it;
903       if (enum_val.union_type.base_type == BASE_TYPE_NONE) continue;
904       code_.SetValue("VARIANT_NAME", namer_.Variant(enum_val));
905       // For legacy reasons, enum variants are Keep case while enum native
906       // variants are UpperCamel case.
907       code_.SetValue("NATIVE_VARIANT",
908                      namer_.LegacyRustNativeVariant(enum_val));
909       code_.SetValue("U_ELEMENT_NAME", namer_.Method(enum_val));
910       code_.SetValue("U_ELEMENT_TABLE_TYPE",
911                      NamespacedNativeName(*enum_val.union_type.struct_def));
912       code_.IncrementIdentLevel();
913       cb();
914       code_.DecrementIdentLevel();
915     }
916   }
GenUnionObject(const EnumDef & enum_def)917   void GenUnionObject(const EnumDef &enum_def) {
918     code_.SetValue("ENUM_TY", namer_.Type(enum_def));
919     code_.SetValue("ENUM_FN", namer_.Function(enum_def));
920     code_.SetValue("ENUM_OTY", namer_.ObjectType(enum_def));
921 
922     // Generate native union.
923     code_ += "#[allow(clippy::upper_case_acronyms)]";  // NONE's spelling is
924                                                        // intended.
925     code_ += "#[non_exhaustive]";
926     code_ += "#[derive(Debug, Clone, PartialEq)]";
927     code_ += "{{ACCESS_TYPE}} enum {{ENUM_OTY}} {";
928     code_ += "  NONE,";
929     ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
930       code_ += "{{NATIVE_VARIANT}}(Box<{{U_ELEMENT_TABLE_TYPE}}>),";
931     });
932     code_ += "}";
933     // Generate Default (NONE).
934     code_ += "impl Default for {{ENUM_OTY}} {";
935     code_ += "  fn default() -> Self {";
936     code_ += "    Self::NONE";
937     code_ += "  }";
938     code_ += "}";
939 
940     // Generate native union methods.
941     code_ += "impl {{ENUM_OTY}} {";
942 
943     // Get flatbuffers union key.
944     // TODO(cneo): add docstrings?
945     code_ += "  pub fn {{ENUM_FN}}_type(&self) -> {{ENUM_TY}} {";
946     code_ += "    match self {";
947     code_ += "      Self::NONE => {{ENUM_TY}}::NONE,";
948     ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
949       code_ +=
950           "    Self::{{NATIVE_VARIANT}}(_) => {{ENUM_TY}}::"
951           "{{VARIANT_NAME}},";
952     });
953     code_ += "    }";
954     code_ += "  }";
955     // Pack flatbuffers union value
956     code_ +=
957         "  pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder)"
958         " -> Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>"
959         " {";
960     code_ += "    match self {";
961     code_ += "      Self::NONE => None,";
962     ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
963       code_ += "    Self::{{NATIVE_VARIANT}}(v) => \\";
964       code_ += "Some(v.pack(fbb).as_union_value()),";
965     });
966     code_ += "    }";
967     code_ += "  }";
968 
969     // Generate some accessors;
970     ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
971       // Move accessor.
972       code_ +=
973           "/// If the union variant matches, return the owned "
974           "{{U_ELEMENT_TABLE_TYPE}}, setting the union to NONE.";
975       code_ +=
976           "pub fn take_{{U_ELEMENT_NAME}}(&mut self) -> "
977           "Option<Box<{{U_ELEMENT_TABLE_TYPE}}>> {";
978       code_ += "  if let Self::{{NATIVE_VARIANT}}(_) = self {";
979       code_ += "    let v = core::mem::replace(self, Self::NONE);";
980       code_ += "    if let Self::{{NATIVE_VARIANT}}(w) = v {";
981       code_ += "      Some(w)";
982       code_ += "    } else {";
983       code_ += "      unreachable!()";
984       code_ += "    }";
985       code_ += "  } else {";
986       code_ += "    None";
987       code_ += "  }";
988       code_ += "}";
989       // Immutable reference accessor.
990       code_ +=
991           "/// If the union variant matches, return a reference to the "
992           "{{U_ELEMENT_TABLE_TYPE}}.";
993       code_ +=
994           "pub fn as_{{U_ELEMENT_NAME}}(&self) -> "
995           "Option<&{{U_ELEMENT_TABLE_TYPE}}> {";
996       code_ +=
997           "  if let Self::{{NATIVE_VARIANT}}(v) = self "
998           "{ Some(v.as_ref()) } else { None }";
999       code_ += "}";
1000       // Mutable reference accessor.
1001       code_ +=
1002           "/// If the union variant matches, return a mutable reference"
1003           " to the {{U_ELEMENT_TABLE_TYPE}}.";
1004       code_ +=
1005           "pub fn as_{{U_ELEMENT_NAME}}_mut(&mut self) -> "
1006           "Option<&mut {{U_ELEMENT_TABLE_TYPE}}> {";
1007       code_ +=
1008           "  if let Self::{{NATIVE_VARIANT}}(v) = self "
1009           "{ Some(v.as_mut()) } else { None }";
1010       code_ += "}";
1011     });
1012     code_ += "}";  // End union methods impl.
1013   }
1014 
1015   enum DefaultContext { kBuilder, kAccessor, kObject };
GetDefaultValue(const FieldDef & field,const DefaultContext context)1016   std::string GetDefaultValue(const FieldDef &field,
1017                               const DefaultContext context) {
1018     if (context == kBuilder) {
1019       // Builders and Args structs model nonscalars "optional" even if they're
1020       // required or have defaults according to the schema. I guess its because
1021       // WIPOffset is not nullable.
1022       if (!IsScalar(field.value.type.base_type) || field.IsOptional()) {
1023         return "None";
1024       }
1025     } else {
1026       // This for defaults in objects.
1027       // Unions have a NONE variant instead of using Rust's None.
1028       if (field.IsOptional() && !IsUnion(field.value.type)) { return "None"; }
1029     }
1030     switch (GetFullType(field.value.type)) {
1031       case ftInteger:
1032       case ftFloat: {
1033         return field.value.constant;
1034       }
1035       case ftBool: {
1036         return field.value.constant == "0" ? "false" : "true";
1037       }
1038       case ftUnionKey:
1039       case ftEnumKey: {
1040         auto ev = field.value.type.enum_def->FindByValue(field.value.constant);
1041         if (!ev) return "Default::default()";  // Bitflags enum.
1042         return WrapInNameSpace(
1043             field.value.type.enum_def->defined_namespace,
1044             namer_.EnumVariant(*field.value.type.enum_def, *ev));
1045       }
1046       case ftUnionValue: {
1047         return ObjectFieldType(field, true) + "::NONE";
1048       }
1049       case ftString: {
1050         // Required fields do not have defaults defined by the schema, but we
1051         // need one for Rust's Default trait so we use empty string. The usual
1052         // value of field.value.constant is `0`, which is non-sensical except
1053         // maybe to c++ (nullptr == 0).
1054         // TODO: Escape strings?
1055         const std::string defval =
1056             field.IsRequired() ? "\"\"" : "\"" + field.value.constant + "\"";
1057         if (context == kObject) return defval + ".to_string()";
1058         if (context == kAccessor) return "&" + defval;
1059         FLATBUFFERS_ASSERT(false);
1060         return "INVALID_CODE_GENERATION";
1061       }
1062 
1063       case ftArrayOfStruct:
1064       case ftArrayOfEnum:
1065       case ftArrayOfBuiltin:
1066       case ftVectorOfBool:
1067       case ftVectorOfFloat:
1068       case ftVectorOfInteger:
1069       case ftVectorOfString:
1070       case ftVectorOfStruct:
1071       case ftVectorOfTable:
1072       case ftVectorOfEnumKey:
1073       case ftVectorOfUnionValue:
1074       case ftStruct:
1075       case ftTable: {
1076         // We only support empty vectors which matches the defaults for
1077         // &[T] and Vec<T> anyway.
1078         //
1079         // For required structs and tables fields, we defer to their object API
1080         // defaults. This works so long as there's nothing recursive happening,
1081         // but `table Infinity { i: Infinity (required); }` does compile.
1082         return "Default::default()";
1083       }
1084     }
1085     FLATBUFFERS_ASSERT(false);
1086     return "INVALID_CODE_GENERATION";
1087   }
1088 
1089   // Create the return type for fields in the *BuilderArgs structs that are
1090   // used to create Tables.
1091   //
1092   // Note: we could make all inputs to the BuilderArgs be an Option, as well
1093   // as all outputs. But, the UX of Flatbuffers is that the user doesn't get to
1094   // know if the value is default or not, because there are three ways to
1095   // return a default value:
1096   // 1) return a stored value that happens to be the default,
1097   // 2) return a hardcoded value because the relevant vtable field is not in
1098   //    the vtable, or
1099   // 3) return a hardcoded value because the vtable field value is set to zero.
TableBuilderArgsDefnType(const FieldDef & field,const std::string & lifetime)1100   std::string TableBuilderArgsDefnType(const FieldDef &field,
1101                                        const std::string &lifetime) {
1102     const Type &type = field.value.type;
1103     auto WrapOption = [&](std::string s) {
1104       return IsOptionalToBuilder(field) ? "Option<" + s + ">" : s;
1105     };
1106     auto WrapVector = [&](std::string ty) {
1107       return WrapOption("flatbuffers::WIPOffset<flatbuffers::Vector<" +
1108                         lifetime + ", " + ty + ">>");
1109     };
1110     auto WrapUOffsetsVector = [&](std::string ty) {
1111       return WrapVector("flatbuffers::ForwardsUOffset<" + ty + ">");
1112     };
1113 
1114     switch (GetFullType(type)) {
1115       case ftInteger:
1116       case ftFloat:
1117       case ftBool: {
1118         return WrapOption(GetTypeBasic(type));
1119       }
1120       case ftStruct: {
1121         const auto typname = WrapInNameSpace(*type.struct_def);
1122         return WrapOption("&" + lifetime + " " + typname);
1123       }
1124       case ftTable: {
1125         const auto typname = WrapInNameSpace(*type.struct_def);
1126         return WrapOption("flatbuffers::WIPOffset<" + typname + "<" + lifetime +
1127                           ">>");
1128       }
1129       case ftString: {
1130         return WrapOption("flatbuffers::WIPOffset<&" + lifetime + " str>");
1131       }
1132       case ftEnumKey:
1133       case ftUnionKey: {
1134         return WrapOption(WrapInNameSpace(*type.enum_def));
1135       }
1136       case ftUnionValue: {
1137         return "Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>";
1138       }
1139 
1140       case ftVectorOfInteger:
1141       case ftVectorOfBool:
1142       case ftVectorOfFloat: {
1143         const auto typname = GetTypeBasic(type.VectorType());
1144         return WrapVector(typname);
1145       }
1146       case ftVectorOfEnumKey: {
1147         const auto typname = WrapInNameSpace(*type.enum_def);
1148         return WrapVector(typname);
1149       }
1150       case ftVectorOfStruct: {
1151         const auto typname = WrapInNameSpace(*type.struct_def);
1152         return WrapVector(typname);
1153       }
1154       case ftVectorOfTable: {
1155         const auto typname = WrapInNameSpace(*type.struct_def);
1156         return WrapUOffsetsVector(typname + "<" + lifetime + ">");
1157       }
1158       case ftVectorOfString: {
1159         return WrapUOffsetsVector("&" + lifetime + " str");
1160       }
1161       case ftVectorOfUnionValue: {
1162         return WrapUOffsetsVector("flatbuffers::Table<" + lifetime + ">");
1163       }
1164       case ftArrayOfEnum:
1165       case ftArrayOfStruct:
1166       case ftArrayOfBuiltin: {
1167         FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
1168         return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
1169       }
1170     }
1171     return "INVALID_CODE_GENERATION";  // for return analysis
1172   }
1173 
ObjectFieldType(const FieldDef & field,bool in_a_table)1174   std::string ObjectFieldType(const FieldDef &field, bool in_a_table) {
1175     const Type &type = field.value.type;
1176     std::string ty;
1177     switch (GetFullType(type)) {
1178       case ftInteger:
1179       case ftBool:
1180       case ftFloat: {
1181         ty = GetTypeBasic(type);
1182         break;
1183       }
1184       case ftString: {
1185         ty = "String";
1186         break;
1187       }
1188       case ftStruct: {
1189         ty = NamespacedNativeName(*type.struct_def);
1190         break;
1191       }
1192       case ftTable: {
1193         // Since Tables can contain themselves, Box is required to avoid
1194         // infinite types.
1195         ty = "Box<" + NamespacedNativeName(*type.struct_def) + ">";
1196         break;
1197       }
1198       case ftUnionKey: {
1199         // There is no native "UnionKey", natively, unions are rust enums with
1200         // newtype-struct-variants.
1201         return "INVALID_CODE_GENERATION";
1202       }
1203       case ftUnionValue: {
1204         ty = NamespacedNativeName(*type.enum_def);
1205         break;
1206       }
1207       case ftEnumKey: {
1208         ty = WrapInNameSpace(*type.enum_def);
1209         break;
1210       }
1211       // Vectors are in tables and are optional
1212       case ftVectorOfEnumKey: {
1213         ty = "Vec<" + WrapInNameSpace(*type.VectorType().enum_def) + ">";
1214         break;
1215       }
1216       case ftVectorOfInteger:
1217       case ftVectorOfBool:
1218       case ftVectorOfFloat: {
1219         ty = "Vec<" + GetTypeBasic(type.VectorType()) + ">";
1220         break;
1221       }
1222       case ftVectorOfString: {
1223         ty = "Vec<String>";
1224         break;
1225       }
1226       case ftVectorOfTable:
1227       case ftVectorOfStruct: {
1228         ty = NamespacedNativeName(*type.VectorType().struct_def);
1229         ty = "Vec<" + ty + ">";
1230         break;
1231       }
1232       case ftVectorOfUnionValue: {
1233         FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
1234         return "INVALID_CODE_GENERATION";  // OH NO!
1235       }
1236       case ftArrayOfEnum: {
1237         ty = "[" + WrapInNameSpace(*type.VectorType().enum_def) + "; " +
1238              NumToString(type.fixed_length) + "]";
1239         break;
1240       }
1241       case ftArrayOfStruct: {
1242         ty = "[" + NamespacedNativeName(*type.VectorType().struct_def) + "; " +
1243              NumToString(type.fixed_length) + "]";
1244         break;
1245       }
1246       case ftArrayOfBuiltin: {
1247         ty = "[" + GetTypeBasic(type.VectorType()) + "; " +
1248              NumToString(type.fixed_length) + "]";
1249         break;
1250       }
1251     }
1252     if (in_a_table && !IsUnion(type) && field.IsOptional()) {
1253       return "Option<" + ty + ">";
1254     } else {
1255       return ty;
1256     }
1257   }
1258 
TableBuilderArgsAddFuncType(const FieldDef & field,const std::string & lifetime)1259   std::string TableBuilderArgsAddFuncType(const FieldDef &field,
1260                                           const std::string &lifetime) {
1261     const Type &type = field.value.type;
1262 
1263     switch (GetFullType(field.value.type)) {
1264       case ftVectorOfStruct: {
1265         const auto typname = WrapInNameSpace(*type.struct_def);
1266         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
1267                typname + ">>";
1268       }
1269       case ftVectorOfTable: {
1270         const auto typname = WrapInNameSpace(*type.struct_def);
1271         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
1272                ", flatbuffers::ForwardsUOffset<" + typname + "<" + lifetime +
1273                ">>>>";
1274       }
1275       case ftVectorOfInteger:
1276       case ftVectorOfBool:
1277       case ftVectorOfFloat: {
1278         const auto typname = GetTypeBasic(type.VectorType());
1279         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
1280                typname + ">>";
1281       }
1282       case ftVectorOfString: {
1283         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
1284                ", flatbuffers::ForwardsUOffset<&" + lifetime + " str>>>";
1285       }
1286       case ftVectorOfEnumKey: {
1287         const auto typname = WrapInNameSpace(*type.enum_def);
1288         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " +
1289                typname + ">>";
1290       }
1291       case ftVectorOfUnionValue: {
1292         return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime +
1293                ", flatbuffers::ForwardsUOffset<flatbuffers::Table<" + lifetime +
1294                ">>>";
1295       }
1296       case ftEnumKey:
1297       case ftUnionKey: {
1298         const auto typname = WrapInNameSpace(*type.enum_def);
1299         return typname;
1300       }
1301       case ftStruct: {
1302         const auto typname = WrapInNameSpace(*type.struct_def);
1303         return "&" + typname + "";
1304       }
1305       case ftTable: {
1306         const auto typname = WrapInNameSpace(*type.struct_def);
1307         return "flatbuffers::WIPOffset<" + typname + "<" + lifetime + ">>";
1308       }
1309       case ftInteger:
1310       case ftBool:
1311       case ftFloat: {
1312         return GetTypeBasic(type);
1313       }
1314       case ftString: {
1315         return "flatbuffers::WIPOffset<&" + lifetime + " str>";
1316       }
1317       case ftUnionValue: {
1318         return "flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>";
1319       }
1320       case ftArrayOfBuiltin: {
1321         const auto typname = GetTypeBasic(type.VectorType());
1322         return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
1323                NumToString(type.fixed_length) + ">";
1324       }
1325       case ftArrayOfEnum: {
1326         const auto typname = WrapInNameSpace(*type.enum_def);
1327         return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
1328                NumToString(type.fixed_length) + ">";
1329       }
1330       case ftArrayOfStruct: {
1331         const auto typname = WrapInNameSpace(*type.struct_def);
1332         return "flatbuffers::Array<" + lifetime + ", " + typname + ", " +
1333                NumToString(type.fixed_length) + ">";
1334       }
1335     }
1336 
1337     return "INVALID_CODE_GENERATION";  // for return analysis
1338   }
1339 
TableBuilderArgsAddFuncBody(const FieldDef & field)1340   std::string TableBuilderArgsAddFuncBody(const FieldDef &field) {
1341     const Type &type = field.value.type;
1342 
1343     switch (GetFullType(field.value.type)) {
1344       case ftInteger:
1345       case ftBool:
1346       case ftFloat: {
1347         const auto typname = GetTypeBasic(field.value.type);
1348         return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
1349                                    : "self.fbb_.push_slot::<") +
1350                typname + ">";
1351       }
1352       case ftEnumKey:
1353       case ftUnionKey: {
1354         const auto underlying_typname = GetTypeBasic(type);
1355         return (field.IsOptional() ? "self.fbb_.push_slot_always::<"
1356                                    : "self.fbb_.push_slot::<") +
1357                underlying_typname + ">";
1358       }
1359 
1360       case ftStruct: {
1361         const std::string typname = WrapInNameSpace(*type.struct_def);
1362         return "self.fbb_.push_slot_always::<&" + typname + ">";
1363       }
1364       case ftTable: {
1365         const auto typname = WrapInNameSpace(*type.struct_def);
1366         return "self.fbb_.push_slot_always::<flatbuffers::WIPOffset<" +
1367                typname + ">>";
1368       }
1369 
1370       case ftUnionValue:
1371       case ftString:
1372       case ftVectorOfInteger:
1373       case ftVectorOfFloat:
1374       case ftVectorOfBool:
1375       case ftVectorOfEnumKey:
1376       case ftVectorOfStruct:
1377       case ftVectorOfTable:
1378       case ftVectorOfString:
1379       case ftVectorOfUnionValue: {
1380         return "self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>";
1381       }
1382       case ftArrayOfEnum:
1383       case ftArrayOfStruct:
1384       case ftArrayOfBuiltin: {
1385         FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
1386         return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
1387       }
1388     }
1389     return "INVALID_CODE_GENERATION";  // for return analysis
1390   }
1391 
GenTableAccessorFuncReturnType(const FieldDef & field,const std::string & lifetime)1392   std::string GenTableAccessorFuncReturnType(const FieldDef &field,
1393                                              const std::string &lifetime) {
1394     const Type &type = field.value.type;
1395     const auto WrapOption = [&](std::string s) {
1396       return field.IsOptional() ? "Option<" + s + ">" : s;
1397     };
1398 
1399     switch (GetFullType(field.value.type)) {
1400       case ftInteger:
1401       case ftFloat:
1402       case ftBool: {
1403         return WrapOption(GetTypeBasic(type));
1404       }
1405       case ftStruct: {
1406         const auto typname = WrapInNameSpace(*type.struct_def);
1407         return WrapOption("&" + lifetime + " " + typname);
1408       }
1409       case ftTable: {
1410         const auto typname = WrapInNameSpace(*type.struct_def);
1411         return WrapOption(typname + "<" + lifetime + ">");
1412       }
1413       case ftEnumKey:
1414       case ftUnionKey: {
1415         return WrapOption(WrapInNameSpace(*type.enum_def));
1416       }
1417 
1418       case ftUnionValue: {
1419         return WrapOption("flatbuffers::Table<" + lifetime + ">");
1420       }
1421       case ftString: {
1422         return WrapOption("&" + lifetime + " str");
1423       }
1424       case ftVectorOfInteger:
1425       case ftVectorOfBool:
1426       case ftVectorOfFloat: {
1427         const auto typname = GetTypeBasic(type.VectorType());
1428         const auto vector_type =
1429             IsOneByte(type.VectorType().base_type)
1430                 ? "&" + lifetime + " [" + typname + "]"
1431                 : "flatbuffers::Vector<" + lifetime + ", " + typname + ">";
1432         return WrapOption(vector_type);
1433       }
1434       case ftVectorOfEnumKey: {
1435         const auto typname = WrapInNameSpace(*type.enum_def);
1436         return WrapOption("flatbuffers::Vector<" + lifetime + ", " + typname +
1437                           ">");
1438       }
1439       case ftVectorOfStruct: {
1440         const auto typname = WrapInNameSpace(*type.struct_def);
1441         return WrapOption("&" + lifetime + " [" + typname + "]");
1442       }
1443       case ftVectorOfTable: {
1444         const auto typname = WrapInNameSpace(*type.struct_def);
1445         return WrapOption("flatbuffers::Vector<" + lifetime +
1446                           ", flatbuffers::ForwardsUOffset<" + typname + "<" +
1447                           lifetime + ">>>");
1448       }
1449       case ftVectorOfString: {
1450         return WrapOption("flatbuffers::Vector<" + lifetime +
1451                           ", flatbuffers::ForwardsUOffset<&" + lifetime +
1452                           " str>>");
1453       }
1454       case ftVectorOfUnionValue: {
1455         FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
1456         // TODO(rw): when we do support these, we should consider using the
1457         //           Into trait to convert tables to typesafe union values.
1458         return "INVALID_CODE_GENERATION";  // for return analysis
1459       }
1460       case ftArrayOfEnum:
1461       case ftArrayOfStruct:
1462       case ftArrayOfBuiltin: {
1463         FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
1464         return "ARRAYS_NOT_SUPPORTED_IN_TABLES";
1465       }
1466     }
1467     return "INVALID_CODE_GENERATION";  // for return analysis
1468   }
1469 
FollowType(const Type & type,const std::string & lifetime)1470   std::string FollowType(const Type &type, const std::string &lifetime) {
1471     // IsVector... This can be made iterative?
1472 
1473     const auto WrapForwardsUOffset = [](std::string ty) -> std::string {
1474       return "flatbuffers::ForwardsUOffset<" + ty + ">";
1475     };
1476     const auto WrapVector = [&](std::string ty) -> std::string {
1477       return "flatbuffers::Vector<" + lifetime + ", " + ty + ">";
1478     };
1479     const auto WrapArray = [&](std::string ty, uint16_t length) -> std::string {
1480       return "flatbuffers::Array<" + lifetime + ", " + ty + ", " +
1481              NumToString(length) + ">";
1482     };
1483     switch (GetFullType(type)) {
1484       case ftInteger:
1485       case ftFloat:
1486       case ftBool: {
1487         return GetTypeBasic(type);
1488       }
1489       case ftStruct: {
1490         return WrapInNameSpace(*type.struct_def);
1491       }
1492       case ftUnionKey:
1493       case ftEnumKey: {
1494         return WrapInNameSpace(*type.enum_def);
1495       }
1496       case ftTable: {
1497         const auto typname = WrapInNameSpace(*type.struct_def);
1498         return WrapForwardsUOffset(typname);
1499       }
1500       case ftUnionValue: {
1501         return WrapForwardsUOffset("flatbuffers::Table<" + lifetime + ">");
1502       }
1503       case ftString: {
1504         return WrapForwardsUOffset("&str");
1505       }
1506       case ftVectorOfInteger:
1507       case ftVectorOfBool:
1508       case ftVectorOfFloat: {
1509         const auto typname = GetTypeBasic(type.VectorType());
1510         return WrapForwardsUOffset(WrapVector(typname));
1511       }
1512       case ftVectorOfEnumKey: {
1513         const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
1514         return WrapForwardsUOffset(WrapVector(typname));
1515       }
1516       case ftVectorOfStruct: {
1517         const auto typname = WrapInNameSpace(*type.struct_def);
1518         return WrapForwardsUOffset(WrapVector(typname));
1519       }
1520       case ftVectorOfTable: {
1521         const auto typname = WrapInNameSpace(*type.struct_def);
1522         return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(typname)));
1523       }
1524       case ftVectorOfString: {
1525         return WrapForwardsUOffset(
1526             WrapVector(WrapForwardsUOffset("&" + lifetime + " str")));
1527       }
1528       case ftVectorOfUnionValue: {
1529         FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
1530         return "INVALID_CODE_GENERATION";  // for return analysis
1531       }
1532       case ftArrayOfEnum: {
1533         const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
1534         return WrapArray(typname, type.fixed_length);
1535       }
1536       case ftArrayOfStruct: {
1537         const auto typname = WrapInNameSpace(*type.struct_def);
1538         return WrapArray(typname, type.fixed_length);
1539       }
1540       case ftArrayOfBuiltin: {
1541         const auto typname = GetTypeBasic(type.VectorType());
1542         return WrapArray(typname, type.fixed_length);
1543       }
1544     }
1545     return "INVALID_CODE_GENERATION";  // for return analysis
1546   }
1547 
GenTableAccessorFuncBody(const FieldDef & field,const std::string & lifetime)1548   std::string GenTableAccessorFuncBody(const FieldDef &field,
1549                                        const std::string &lifetime) {
1550     const std::string vt_offset = namer_.LegacyRustFieldOffsetName(field);
1551     const std::string typname = FollowType(field.value.type, lifetime);
1552     // Default-y fields (scalars so far) are neither optional nor required.
1553     const std::string default_value =
1554         !(field.IsOptional() || field.IsRequired())
1555             ? "Some(" + GetDefaultValue(field, kAccessor) + ")"
1556             : "None";
1557     const std::string unwrap = field.IsOptional() ? "" : ".unwrap()";
1558 
1559     const auto t = GetFullType(field.value.type);
1560 
1561     // TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
1562     const std::string safe_slice =
1563         (t == ftVectorOfStruct ||
1564          ((t == ftVectorOfBool || t == ftVectorOfFloat ||
1565            t == ftVectorOfInteger) &&
1566           IsOneByte(field.value.type.VectorType().base_type)))
1567             ? ".map(|v| v.safe_slice())"
1568             : "";
1569 
1570     return "self._tab.get::<" + typname + ">({{STRUCT_TY}}::" + vt_offset +
1571            ", " + default_value + ")" + safe_slice + unwrap;
1572   }
1573 
1574   // Generates a fully-qualified name getter for use with --gen-name-strings
GenFullyQualifiedNameGetter(const StructDef & struct_def,const std::string & name)1575   void GenFullyQualifiedNameGetter(const StructDef &struct_def,
1576                                    const std::string &name) {
1577     const std::string fully_qualified_name =
1578         struct_def.defined_namespace->GetFullyQualifiedName(name);
1579     code_ += "  pub const fn get_fully_qualified_name() -> &'static str {";
1580     code_ += "    \"" + fully_qualified_name + "\"";
1581     code_ += "  }";
1582     code_ += "";
1583   }
1584 
ForAllUnionVariantsBesidesNone(const EnumDef & def,std::function<void (const EnumVal & ev)> cb)1585   void ForAllUnionVariantsBesidesNone(
1586       const EnumDef &def, std::function<void(const EnumVal &ev)> cb) {
1587     FLATBUFFERS_ASSERT(def.is_union);
1588 
1589     for (auto it = def.Vals().begin(); it != def.Vals().end(); ++it) {
1590       const EnumVal &ev = **it;
1591       // TODO(cneo): Can variants be deprecated, should we skip them?
1592       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
1593       code_.SetValue(
1594           "U_ELEMENT_ENUM_TYPE",
1595           WrapInNameSpace(def.defined_namespace, namer_.EnumVariant(def, ev)));
1596       code_.SetValue(
1597           "U_ELEMENT_TABLE_TYPE",
1598           WrapInNameSpace(ev.union_type.struct_def->defined_namespace,
1599                           ev.union_type.struct_def->name));
1600       code_.SetValue("U_ELEMENT_NAME", namer_.Function(ev.name));
1601       cb(ev);
1602     }
1603   }
1604 
ForAllTableFields(const StructDef & struct_def,std::function<void (const FieldDef &)> cb,bool reversed=false)1605   void ForAllTableFields(const StructDef &struct_def,
1606                          std::function<void(const FieldDef &)> cb,
1607                          bool reversed = false) {
1608     // TODO(cneo): Remove `reversed` overload. It's only here to minimize the
1609     // diff when refactoring to the `ForAllX` helper functions.
1610     auto go = [&](const FieldDef &field) {
1611       if (field.deprecated) return;
1612       code_.SetValue("OFFSET_NAME", namer_.LegacyRustFieldOffsetName(field));
1613       code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
1614       code_.SetValue("FIELD", namer_.Field(field));
1615       code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder));
1616       code_.SetValue("DISCRIMINANT", namer_.Field(field) + "_type");
1617       code_.IncrementIdentLevel();
1618       cb(field);
1619       code_.DecrementIdentLevel();
1620     };
1621     const auto &fields = struct_def.fields.vec;
1622     if (reversed) {
1623       for (auto it = fields.rbegin(); it != fields.rend(); ++it) go(**it);
1624     } else {
1625       for (auto it = fields.begin(); it != fields.end(); ++it) go(**it);
1626     }
1627   }
1628   // Generate an accessor struct, builder struct, and create function for a
1629   // table.
GenTable(const StructDef & struct_def)1630   void GenTable(const StructDef &struct_def) {
1631 
1632     const bool is_private = parser_.opts.no_leak_private_annotations &&
1633         (struct_def.attributes.Lookup("private") != nullptr);
1634     code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
1635     code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
1636     code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
1637 
1638     // Generate an offset type, the base type, the Follow impl, and the
1639     // init_from_table impl.
1640     code_ += "{{ACCESS_TYPE}} enum {{STRUCT_TY}}Offset {}";
1641     code_ += "#[derive(Copy, Clone, PartialEq)]";
1642     code_ += "";
1643 
1644     GenComment(struct_def.doc_comment);
1645 
1646     code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}<'a> {";
1647     code_ += "  pub _tab: flatbuffers::Table<'a>,";
1648     code_ += "}";
1649     code_ += "";
1650     code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}}<'a> {";
1651     code_ += "  type Inner = {{STRUCT_TY}}<'a>;";
1652     code_ += "  #[inline]";
1653     code_ += "  fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
1654     code_ += "    Self { _tab: flatbuffers::Table { buf, loc } }";
1655     code_ += "  }";
1656     code_ += "}";
1657     code_ += "";
1658     code_ += "impl<'a> {{STRUCT_TY}}<'a> {";
1659 
1660     // Generate field id constants.
1661     ForAllTableFields(struct_def, [&](const FieldDef &unused) {
1662       (void)unused;
1663       code_ +=
1664           "pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = "
1665           "{{OFFSET_VALUE}};";
1666     });
1667     code_ += "";
1668 
1669     if (parser_.opts.generate_name_strings) {
1670       GenFullyQualifiedNameGetter(struct_def, struct_def.name);
1671     }
1672 
1673     code_ += "  #[inline]";
1674     code_ +=
1675         "  pub fn init_from_table(table: flatbuffers::Table<'a>) -> "
1676         "Self {";
1677     code_ += "    {{STRUCT_TY}} { _tab: table }";
1678     code_ += "  }";
1679 
1680     // Generate a convenient create* function that uses the above builder
1681     // to create a table in one function call.
1682     code_.SetValue("MAYBE_US", struct_def.fields.vec.size() == 0 ? "_" : "");
1683     code_.SetValue("MAYBE_LT",
1684                    TableBuilderArgsNeedsLifetime(struct_def) ? "<'args>" : "");
1685     code_ += "  #[allow(unused_mut)]";
1686     code_ += "  pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>(";
1687     code_ += "    _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,";
1688     code_ += "    {{MAYBE_US}}args: &'args {{STRUCT_TY}}Args{{MAYBE_LT}}";
1689     code_ += "  ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'bldr>> {";
1690 
1691     code_ += "    let mut builder = {{STRUCT_TY}}Builder::new(_fbb);";
1692     for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1;
1693          size; size /= 2) {
1694       ForAllTableFields(
1695           struct_def,
1696           [&](const FieldDef &field) {
1697             if (struct_def.sortbysize &&
1698                 size != SizeOf(field.value.type.base_type))
1699               return;
1700             if (IsOptionalToBuilder(field)) {
1701               code_ +=
1702                   "  if let Some(x) = args.{{FIELD}} "
1703                   "{ builder.add_{{FIELD}}(x); }";
1704             } else {
1705               code_ += "  builder.add_{{FIELD}}(args.{{FIELD}});";
1706             }
1707           },
1708           /*reverse=*/true);
1709     }
1710     code_ += "    builder.finish()";
1711     code_ += "  }";
1712     code_ += "";
1713     // Generate Object API Packer function.
1714     if (parser_.opts.generate_object_based_api) {
1715       // TODO(cneo): Replace more for loops with ForAllX stuff.
1716       // TODO(cneo): Manage indentation with IncrementIdentLevel?
1717       code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
1718       code_ += "  pub fn unpack(&self) -> {{STRUCT_OTY}} {";
1719       ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
1720         const Type &type = field.value.type;
1721         switch (GetFullType(type)) {
1722           case ftInteger:
1723           case ftBool:
1724           case ftFloat:
1725           case ftEnumKey: {
1726             code_ += "  let {{FIELD}} = self.{{FIELD}}();";
1727             return;
1728           }
1729           case ftUnionKey: return;
1730           case ftUnionValue: {
1731             const auto &enum_def = *type.enum_def;
1732             code_.SetValue("ENUM_TY", WrapInNameSpace(enum_def));
1733             code_.SetValue("NATIVE_ENUM_NAME", NamespacedNativeName(enum_def));
1734             code_ += "  let {{FIELD}} = match self.{{FIELD}}_type() {";
1735             code_ += "    {{ENUM_TY}}::NONE => {{NATIVE_ENUM_NAME}}::NONE,";
1736             ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
1737               code_ +=
1738                   "  {{ENUM_TY}}::{{VARIANT_NAME}} => "
1739                   "{{NATIVE_ENUM_NAME}}::{{NATIVE_VARIANT}}(Box::new(";
1740               code_ += "    self.{{FIELD}}_as_{{U_ELEMENT_NAME}}()";
1741               code_ +=
1742                   "        .expect(\"Invalid union table, "
1743                   "expected `{{ENUM_TY}}::{{VARIANT_NAME}}`.\")";
1744               code_ += "        .unpack()";
1745               code_ += "  )),";
1746             });
1747             // Maybe we shouldn't throw away unknown discriminants?
1748             code_ += "    _ => {{NATIVE_ENUM_NAME}}::NONE,";
1749             code_ += "  };";
1750             return;
1751           }
1752           // The rest of the types need special handling based on if the field
1753           // is optional or not.
1754           case ftString: {
1755             code_.SetValue("EXPR", "x.to_string()");
1756             break;
1757           }
1758           case ftStruct: {
1759             code_.SetValue("EXPR", "x.unpack()");
1760             break;
1761           }
1762           case ftTable: {
1763             code_.SetValue("EXPR", "Box::new(x.unpack())");
1764             break;
1765           }
1766           case ftVectorOfInteger:
1767           case ftVectorOfBool: {
1768             if (IsOneByte(type.VectorType().base_type)) {
1769               // 1 byte stuff is viewed w/ slice instead of flatbuffer::Vector
1770               // and thus needs to be cloned out of the slice.
1771               code_.SetValue("EXPR", "x.to_vec()");
1772               break;
1773             }
1774             code_.SetValue("EXPR", "x.into_iter().collect()");
1775             break;
1776           }
1777           case ftVectorOfFloat:
1778           case ftVectorOfEnumKey: {
1779             code_.SetValue("EXPR", "x.into_iter().collect()");
1780             break;
1781           }
1782           case ftVectorOfString: {
1783             code_.SetValue("EXPR", "x.iter().map(|s| s.to_string()).collect()");
1784             break;
1785           }
1786           case ftVectorOfStruct:
1787           case ftVectorOfTable: {
1788             code_.SetValue("EXPR", "x.iter().map(|t| t.unpack()).collect()");
1789             break;
1790           }
1791           case ftVectorOfUnionValue: {
1792             FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
1793             return;
1794           }
1795           case ftArrayOfEnum:
1796           case ftArrayOfStruct:
1797           case ftArrayOfBuiltin: {
1798             FLATBUFFERS_ASSERT(false &&
1799                                "arrays are not supported within tables");
1800             return;
1801           }
1802         }
1803         if (field.IsOptional()) {
1804           code_ += "  let {{FIELD}} = self.{{FIELD}}().map(|x| {";
1805           code_ += "    {{EXPR}}";
1806           code_ += "  });";
1807         } else {
1808           code_ += "  let {{FIELD}} = {";
1809           code_ += "    let x = self.{{FIELD}}();";
1810           code_ += "    {{EXPR}}";
1811           code_ += "  };";
1812         }
1813       });
1814       code_ += "    {{STRUCT_OTY}} {";
1815       ForAllObjectTableFields(struct_def, [&](const FieldDef &field) {
1816         if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
1817         code_ += "    {{FIELD}},";
1818       });
1819       code_ += "    }";
1820       code_ += "  }";
1821     }
1822 
1823     if (struct_def.fields.vec.size() > 0) code_ += "";
1824 
1825     // Generate the accessors. Each has one of two forms:
1826     //
1827     // If a value can be None:
1828     //   pub fn name(&'a self) -> Option<user_facing_type> {
1829     //     self._tab.get::<internal_type>(offset, defaultval)
1830     //   }
1831     //
1832     // If a value is always Some:
1833     //   pub fn name(&'a self) -> user_facing_type {
1834     //     self._tab.get::<internal_type>(offset, defaultval).unwrap()
1835     //   }
1836     ForAllTableFields(struct_def, [&](const FieldDef &field) {
1837       code_.SetValue("RETURN_TYPE",
1838                      GenTableAccessorFuncReturnType(field, "'a"));
1839 
1840       this->GenComment(field.doc_comment);
1841       code_ += "#[inline]";
1842       code_ += "pub fn {{FIELD}}(&self) -> {{RETURN_TYPE}} {";
1843       code_ += "  " + GenTableAccessorFuncBody(field, "'a");
1844       code_ += "}";
1845 
1846       // Generate a comparison function for this field if it is a key.
1847       if (field.key) { GenKeyFieldMethods(field); }
1848 
1849       // Generate a nested flatbuffer field, if applicable.
1850       auto nested = field.attributes.Lookup("nested_flatbuffer");
1851       if (nested) {
1852         std::string qualified_name = nested->constant;
1853         auto nested_root = parser_.LookupStruct(nested->constant);
1854         if (nested_root == nullptr) {
1855           qualified_name = parser_.current_namespace_->GetFullyQualifiedName(
1856               nested->constant);
1857           nested_root = parser_.LookupStruct(qualified_name);
1858         }
1859         FLATBUFFERS_ASSERT(nested_root);  // Guaranteed to exist by parser.
1860 
1861         code_.SetValue("NESTED", WrapInNameSpace(*nested_root));
1862         code_ += "pub fn {{FIELD}}_nested_flatbuffer(&'a self) -> \\";
1863         if (field.IsRequired()) {
1864           code_ += "{{NESTED}}<'a> {";
1865           code_ += "  let data = self.{{FIELD}}();";
1866           code_ += "  use flatbuffers::Follow;";
1867           code_ +=
1868               "  <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
1869               "::follow(data, 0)";
1870         } else {
1871           code_ += "Option<{{NESTED}}<'a>> {";
1872           code_ += "  self.{{FIELD}}().map(|data| {";
1873           code_ += "    use flatbuffers::Follow;";
1874           code_ +=
1875               "    <flatbuffers::ForwardsUOffset<{{NESTED}}<'a>>>"
1876               "::follow(data, 0)";
1877           code_ += "  })";
1878         }
1879         code_ += "}";
1880       }
1881     });
1882 
1883     // Explicit specializations for union accessors
1884     ForAllTableFields(struct_def, [&](const FieldDef &field) {
1885       if (field.value.type.base_type != BASE_TYPE_UNION) return;
1886       ForAllUnionVariantsBesidesNone(
1887           *field.value.type.enum_def, [&](const EnumVal &unused) {
1888             (void)unused;
1889             code_ += "#[inline]";
1890             code_ += "#[allow(non_snake_case)]";
1891             code_ +=
1892                 "pub fn {{FIELD}}_as_{{U_ELEMENT_NAME}}(&self) -> "
1893                 "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {";
1894             // If the user defined schemas name a field that clashes with a
1895             // language reserved word, flatc will try to escape the field name
1896             // by appending an underscore. This works well for most cases,
1897             // except one. When generating union accessors (and referring to
1898             // them internally within the code generated here), an extra
1899             // underscore will be appended to the name, causing build failures.
1900             //
1901             // This only happens when unions have members that overlap with
1902             // language reserved words.
1903             //
1904             // To avoid this problem the type field name is used unescaped here:
1905             code_ +=
1906                 "  if self.{{DISCRIMINANT}}() == {{U_ELEMENT_ENUM_TYPE}} {";
1907 
1908             // The following logic is not tested in the integration test,
1909             // as of April 10, 2020
1910             if (field.IsRequired()) {
1911               code_ += "    let u = self.{{FIELD}}();";
1912               code_ += "    Some({{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))";
1913             } else {
1914               code_ +=
1915                   "    self.{{FIELD}}().map("
1916                   "{{U_ELEMENT_TABLE_TYPE}}::init_from_table)";
1917             }
1918             code_ += "  } else {";
1919             code_ += "    None";
1920             code_ += "  }";
1921             code_ += "}";
1922             code_ += "";
1923           });
1924     });
1925     code_ += "}";  // End of table impl.
1926     code_ += "";
1927 
1928     // Generate Verifier;
1929     code_ += "impl flatbuffers::Verifiable for {{STRUCT_TY}}<'_> {";
1930     code_ += "  #[inline]";
1931     code_ += "  fn run_verifier(";
1932     code_ += "    v: &mut flatbuffers::Verifier, pos: usize";
1933     code_ += "  ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
1934     code_ += "    use self::flatbuffers::Verifiable;";
1935     code_ += "    v.visit_table(pos)?\\";
1936     // Escape newline and insert it onthe next line so we can end the builder
1937     // with a nice semicolon.
1938     ForAllTableFields(struct_def, [&](const FieldDef &field) {
1939       if (GetFullType(field.value.type) == ftUnionKey) return;
1940 
1941       code_.SetValue("IS_REQ", field.IsRequired() ? "true" : "false");
1942       if (GetFullType(field.value.type) != ftUnionValue) {
1943         // All types besides unions.
1944         code_.SetValue("TY", FollowType(field.value.type, "'_"));
1945         code_ +=
1946             "\n     .visit_field::<{{TY}}>(\"{{FIELD}}\", "
1947             "Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
1948         return;
1949       }
1950       // Unions.
1951       const EnumDef &union_def = *field.value.type.enum_def;
1952       code_.SetValue("UNION_TYPE", WrapInNameSpace(union_def));
1953       code_.SetValue("UNION_TYPE_OFFSET_NAME",
1954                      namer_.LegacyRustFieldOffsetName(field) + "_TYPE");
1955       code_ +=
1956           "\n     .visit_union::<{{UNION_TYPE}}, _>("
1957           "\"{{FIELD}}_type\", Self::{{UNION_TYPE_OFFSET_NAME}}, "
1958           "\"{{FIELD}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
1959           "|key, v, pos| {";
1960       code_ += "      match key {";
1961       ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
1962         (void)unused;
1963         code_ +=
1964             "        {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
1965             "<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
1966             "\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
1967       });
1968       code_ += "        _ => Ok(()),";
1969       code_ += "      }";
1970       code_ += "   })?\\";
1971     });
1972     code_ += "\n     .finish();";
1973     code_ += "    Ok(())";
1974     code_ += "  }";
1975     code_ += "}";
1976 
1977     // Generate an args struct:
1978     code_.SetValue("MAYBE_LT",
1979                    TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
1980     code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Args{{MAYBE_LT}} {";
1981     ForAllTableFields(struct_def, [&](const FieldDef &field) {
1982       code_.SetValue("PARAM_TYPE", TableBuilderArgsDefnType(field, "'a"));
1983       code_ += "  pub {{FIELD}}: {{PARAM_TYPE}},";
1984     });
1985     code_ += "}";
1986 
1987     // Generate an impl of Default for the *Args type:
1988     code_ += "impl<'a> Default for {{STRUCT_TY}}Args{{MAYBE_LT}} {";
1989     code_ += "  #[inline]";
1990     code_ += "  fn default() -> Self {";
1991     code_ += "    {{STRUCT_TY}}Args {";
1992     ForAllTableFields(struct_def, [&](const FieldDef &field) {
1993       code_ += "    {{FIELD}}: {{BLDR_DEF_VAL}},\\";
1994       code_ += field.IsRequired() ? " // required field" : "";
1995     });
1996     code_ += "    }";
1997     code_ += "  }";
1998     code_ += "}";
1999     code_ += "";
2000 
2001     // Implement serde::Serialize
2002     if (parser_.opts.rust_serialize) {
2003       const auto numFields = struct_def.fields.vec.size();
2004       code_.SetValue("NUM_FIELDS", NumToString(numFields));
2005       code_ += "impl Serialize for {{STRUCT_TY}}<'_> {";
2006       code_ +=
2007           "  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
2008       code_ += "  where";
2009       code_ += "    S: Serializer,";
2010       code_ += "  {";
2011       if (numFields == 0) {
2012         code_ +=
2013             "    let s = serializer.serialize_struct(\"{{STRUCT_TY}}\", 0)?;";
2014       } else {
2015         code_ +=
2016             "    let mut s = serializer.serialize_struct(\"{{STRUCT_TY}}\", "
2017             "{{NUM_FIELDS}})?;";
2018       }
2019       ForAllTableFields(struct_def, [&](const FieldDef &field) {
2020         const Type &type = field.value.type;
2021         if (IsUnion(type)) {
2022           if (type.base_type == BASE_TYPE_UNION) {
2023             const auto &enum_def = *type.enum_def;
2024             code_.SetValue("ENUM_TY", WrapInNameSpace(enum_def));
2025             code_.SetValue("FIELD", namer_.Field(field));
2026 
2027             code_ += "    match self.{{FIELD}}_type() {";
2028             code_ += "      {{ENUM_TY}}::NONE => (),";
2029             ForAllUnionObjectVariantsBesidesNone(enum_def, [&] {
2030               code_.SetValue("FIELD", namer_.Field(field));
2031               code_ += "      {{ENUM_TY}}::{{VARIANT_NAME}} => {";
2032               code_ +=
2033                   "        let f = "
2034                   "self.{{FIELD}}_as_{{U_ELEMENT_NAME}}()";
2035               code_ +=
2036                   "          .expect(\"Invalid union table, expected "
2037                   "`{{ENUM_TY}}::{{VARIANT_NAME}}`.\");";
2038               code_ += "        s.serialize_field(\"{{FIELD}}\", &f)?;";
2039               code_ += "      }";
2040             });
2041             code_ += "      _ => unimplemented!(),";
2042             code_ += "    }";
2043           } else {
2044             code_ +=
2045                 "    s.serialize_field(\"{{FIELD}}\", "
2046                 "&self.{{FIELD}}())?;";
2047           }
2048         } else {
2049           if (field.IsOptional()) {
2050             code_ += "    if let Some(f) = self.{{FIELD}}() {";
2051             code_ += "      s.serialize_field(\"{{FIELD}}\", &f)?;";
2052             code_ += "    } else {";
2053             code_ += "      s.skip_field(\"{{FIELD}}\")?;";
2054             code_ += "    }";
2055           } else {
2056             code_ +=
2057                 "    s.serialize_field(\"{{FIELD}}\", "
2058                 "&self.{{FIELD}}())?;";
2059           }
2060         }
2061       });
2062       code_ += "    s.end()";
2063       code_ += "  }";
2064       code_ += "}";
2065       code_ += "";
2066     }
2067 
2068     // Generate a builder struct:
2069     code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}Builder<'a: 'b, 'b> {";
2070     code_ += "  fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
2071     code_ +=
2072         "  start_: flatbuffers::WIPOffset<"
2073         "flatbuffers::TableUnfinishedWIPOffset>,";
2074     code_ += "}";
2075 
2076     // Generate builder functions:
2077     code_ += "impl<'a: 'b, 'b> {{STRUCT_TY}}Builder<'a, 'b> {";
2078     ForAllTableFields(struct_def, [&](const FieldDef &field) {
2079       const bool is_scalar = IsScalar(field.value.type.base_type);
2080       std::string offset = namer_.LegacyRustFieldOffsetName(field);
2081       // Generate functions to add data, which take one of two forms.
2082       //
2083       // If a value has a default:
2084       //   fn add_x(x_: type) {
2085       //     fbb_.push_slot::<type>(offset, x_, Some(default));
2086       //   }
2087       //
2088       // If a value does not have a default:
2089       //   fn add_x(x_: type) {
2090       //     fbb_.push_slot_always::<type>(offset, x_);
2091       //   }
2092       code_.SetValue("FIELD_OFFSET", namer_.Type(struct_def) + "::" + offset);
2093       code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b "));
2094       code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field));
2095       code_ += "#[inline]";
2096       code_ +=
2097           "pub fn add_{{FIELD}}(&mut self, {{FIELD}}: "
2098           "{{FIELD_TYPE}}) {";
2099       if (is_scalar && !field.IsOptional()) {
2100         code_ +=
2101             "  {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD}}, "
2102             "{{BLDR_DEF_VAL}});";
2103       } else {
2104         code_ += "  {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD}});";
2105       }
2106       code_ += "}";
2107     });
2108 
2109     // Struct initializer (all fields required);
2110     code_ += "  #[inline]";
2111     code_ +=
2112         "  pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> "
2113         "{{STRUCT_TY}}Builder<'a, 'b> {";
2114     code_.SetValue("NUM_FIELDS", NumToString(struct_def.fields.vec.size()));
2115     code_ += "    let start = _fbb.start_table();";
2116     code_ += "    {{STRUCT_TY}}Builder {";
2117     code_ += "      fbb_: _fbb,";
2118     code_ += "      start_: start,";
2119     code_ += "    }";
2120     code_ += "  }";
2121 
2122     // finish() function.
2123     code_ += "  #[inline]";
2124     code_ +=
2125         "  pub fn finish(self) -> "
2126         "flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>> {";
2127     code_ += "    let o = self.fbb_.end_table(self.start_);";
2128 
2129     ForAllTableFields(struct_def, [&](const FieldDef &field) {
2130       if (!field.IsRequired()) return;
2131       code_ +=
2132           "  self.fbb_.required(o, {{STRUCT_TY}}::{{OFFSET_NAME}},"
2133           "\"{{FIELD}}\");";
2134     });
2135     code_ += "    flatbuffers::WIPOffset::new(o.value())";
2136     code_ += "  }";
2137     code_ += "}";
2138     code_ += "";
2139 
2140     code_ += "impl core::fmt::Debug for {{STRUCT_TY}}<'_> {";
2141     code_ +=
2142         "  fn fmt(&self, f: &mut core::fmt::Formatter<'_>"
2143         ") -> core::fmt::Result {";
2144     code_ += "    let mut ds = f.debug_struct(\"{{STRUCT_TY}}\");";
2145     ForAllTableFields(struct_def, [&](const FieldDef &field) {
2146       if (GetFullType(field.value.type) == ftUnionValue) {
2147         // Generate a match statement to handle unions properly.
2148         code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
2149         code_.SetValue("UNION_ERR",
2150                        "&\"InvalidFlatbuffer: Union discriminant"
2151                        " does not match value.\"");
2152 
2153         code_ += "    match self.{{DISCRIMINANT}}() {";
2154         ForAllUnionVariantsBesidesNone(
2155             *field.value.type.enum_def, [&](const EnumVal &unused) {
2156               (void)unused;
2157               code_ += "      {{U_ELEMENT_ENUM_TYPE}} => {";
2158               code_ +=
2159                   "        if let Some(x) = "
2160                   "self.{{FIELD}}_as_"
2161                   "{{U_ELEMENT_NAME}}() {";
2162               code_ += "          ds.field(\"{{FIELD}}\", &x)";
2163               code_ += "        } else {";
2164               code_ += "          ds.field(\"{{FIELD}}\", {{UNION_ERR}})";
2165               code_ += "        }";
2166               code_ += "      },";
2167             });
2168         code_ += "      _ => {";
2169         code_ += "        let x: Option<()> = None;";
2170         code_ += "        ds.field(\"{{FIELD}}\", &x)";
2171         code_ += "      },";
2172         code_ += "    };";
2173       } else {
2174         // Most fields.
2175         code_ += "    ds.field(\"{{FIELD}}\", &self.{{FIELD}}());";
2176       }
2177     });
2178     code_ += "      ds.finish()";
2179     code_ += "  }";
2180     code_ += "}";
2181   }
2182 
GenTableObject(const StructDef & table)2183   void GenTableObject(const StructDef &table) {
2184     code_.SetValue("STRUCT_OTY", namer_.ObjectType(table));
2185     code_.SetValue("STRUCT_TY", namer_.Type(table));
2186 
2187     // Generate the native object.
2188     code_ += "#[non_exhaustive]";
2189     code_ += "#[derive(Debug, Clone, PartialEq)]";
2190     code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
2191     ForAllObjectTableFields(table, [&](const FieldDef &field) {
2192       // Union objects combine both the union discriminant and value, so we
2193       // skip making a field for the discriminant.
2194       if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
2195       code_ += "pub {{FIELD}}: {{FIELD_OTY}},";
2196     });
2197     code_ += "}";
2198 
2199     code_ += "impl Default for {{STRUCT_OTY}} {";
2200     code_ += "  fn default() -> Self {";
2201     code_ += "    Self {";
2202     ForAllObjectTableFields(table, [&](const FieldDef &field) {
2203       if (field.value.type.base_type == BASE_TYPE_UTYPE) return;
2204       std::string default_value = GetDefaultValue(field, kObject);
2205       code_ += "    {{FIELD}}: " + default_value + ",";
2206     });
2207     code_ += "    }";
2208     code_ += "  }";
2209     code_ += "}";
2210 
2211     // TODO(cneo): Generate defaults for Native tables. However, since structs
2212     // may be required, they, and therefore enums need defaults.
2213 
2214     // Generate pack function.
2215     code_ += "impl {{STRUCT_OTY}} {";
2216     code_ += "  pub fn pack<'b>(";
2217     code_ += "    &self,";
2218     code_ += "    _fbb: &mut flatbuffers::FlatBufferBuilder<'b>";
2219     code_ += "  ) -> flatbuffers::WIPOffset<{{STRUCT_TY}}<'b>> {";
2220     // First we generate variables for each field and then later assemble them
2221     // using "StructArgs" to more easily manage ownership of the builder.
2222     ForAllObjectTableFields(table, [&](const FieldDef &field) {
2223       const Type &type = field.value.type;
2224       switch (GetFullType(type)) {
2225         case ftInteger:
2226         case ftBool:
2227         case ftFloat:
2228         case ftEnumKey: {
2229           code_ += "  let {{FIELD}} = self.{{FIELD}};";
2230           return;
2231         }
2232         case ftUnionKey: return;  // Generate union type with union value.
2233         case ftUnionValue: {
2234           code_.SetValue("ENUM_METHOD",
2235                          namer_.Method(*field.value.type.enum_def));
2236           code_ +=
2237               "  let {{FIELD}}_type = "
2238               "self.{{FIELD}}.{{ENUM_METHOD}}_type();";
2239           code_ += "  let {{FIELD}} = self.{{FIELD}}.pack(_fbb);";
2240           return;
2241         }
2242         // The rest of the types require special casing around optionalness
2243         // due to "required" annotation.
2244         case ftString: {
2245           MapNativeTableField(field, "_fbb.create_string(x)");
2246           return;
2247         }
2248         case ftStruct: {
2249           // Hold the struct in a variable so we can reference it.
2250           if (field.IsRequired()) {
2251             code_ += "  let {{FIELD}}_tmp = Some(self.{{FIELD}}.pack());";
2252           } else {
2253             code_ +=
2254                 "  let {{FIELD}}_tmp = self.{{FIELD}}"
2255                 ".as_ref().map(|x| x.pack());";
2256           }
2257           code_ += "  let {{FIELD}} = {{FIELD}}_tmp.as_ref();";
2258 
2259           return;
2260         }
2261         case ftTable: {
2262           MapNativeTableField(field, "x.pack(_fbb)");
2263           return;
2264         }
2265         case ftVectorOfEnumKey:
2266         case ftVectorOfInteger:
2267         case ftVectorOfBool:
2268         case ftVectorOfFloat: {
2269           MapNativeTableField(field, "_fbb.create_vector(x)");
2270           return;
2271         }
2272         case ftVectorOfStruct: {
2273           MapNativeTableField(
2274               field,
2275               "let w: Vec<_> = x.iter().map(|t| t.pack()).collect();"
2276               "_fbb.create_vector(&w)");
2277           return;
2278         }
2279         case ftVectorOfString: {
2280           // TODO(cneo): create_vector* should be more generic to avoid
2281           // allocations.
2282 
2283           MapNativeTableField(
2284               field,
2285               "let w: Vec<_> = x.iter().map(|s| s.as_ref()).collect();"
2286               "_fbb.create_vector_of_strings(&w)");
2287           return;
2288         }
2289         case ftVectorOfTable: {
2290           MapNativeTableField(
2291               field,
2292               "let w: Vec<_> = x.iter().map(|t| t.pack(_fbb)).collect();"
2293               "_fbb.create_vector(&w)");
2294           return;
2295         }
2296         case ftVectorOfUnionValue: {
2297           FLATBUFFERS_ASSERT(false && "vectors of unions not yet supported");
2298           return;
2299         }
2300         case ftArrayOfEnum:
2301         case ftArrayOfStruct:
2302         case ftArrayOfBuiltin: {
2303           FLATBUFFERS_ASSERT(false && "arrays are not supported within tables");
2304           return;
2305         }
2306       }
2307     });
2308     code_ += "    {{STRUCT_TY}}::create(_fbb, &{{STRUCT_TY}}Args{";
2309     ForAllObjectTableFields(table, [&](const FieldDef &field) {
2310       (void)field;  // Unused.
2311       code_ += "    {{FIELD}},";
2312     });
2313     code_ += "    })";
2314     code_ += "  }";
2315     code_ += "}";
2316   }
ForAllObjectTableFields(const StructDef & table,std::function<void (const FieldDef &)> cb)2317   void ForAllObjectTableFields(const StructDef &table,
2318                                std::function<void(const FieldDef &)> cb) {
2319     const std::vector<FieldDef *> &v = table.fields.vec;
2320     for (auto it = v.begin(); it != v.end(); it++) {
2321       const FieldDef &field = **it;
2322       if (field.deprecated) continue;
2323       code_.SetValue("FIELD", namer_.Field(field));
2324       code_.SetValue("FIELD_OTY", ObjectFieldType(field, true));
2325       code_.IncrementIdentLevel();
2326       cb(field);
2327       code_.DecrementIdentLevel();
2328     }
2329   }
MapNativeTableField(const FieldDef & field,const std::string & expr)2330   void MapNativeTableField(const FieldDef &field, const std::string &expr) {
2331     if (field.IsOptional()) {
2332       code_ += "  let {{FIELD}} = self.{{FIELD}}.as_ref().map(|x|{";
2333       code_ += "    " + expr;
2334       code_ += "  });";
2335     } else {
2336       // For some reason Args has optional types for required fields.
2337       // TODO(cneo): Fix this... but its a breaking change?
2338       code_ += "  let {{FIELD}} = Some({";
2339       code_ += "    let x = &self.{{FIELD}};";
2340       code_ += "    " + expr;
2341       code_ += "  });";
2342     }
2343   }
2344 
2345   // Generate functions to compare tables and structs by key. This function
2346   // must only be called if the field key is defined.
GenKeyFieldMethods(const FieldDef & field)2347   void GenKeyFieldMethods(const FieldDef &field) {
2348     FLATBUFFERS_ASSERT(field.key);
2349 
2350     code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
2351     code_.SetValue("REF", IsString(field.value.type) ? "" : "&");
2352 
2353     code_ += "#[inline]";
2354     code_ +=
2355         "pub fn key_compare_less_than(&self, o: &{{STRUCT_TY}}) -> "
2356         "bool {";
2357     code_ += "  self.{{FIELD}}() < o.{{FIELD}}()";
2358     code_ += "}";
2359     code_ += "";
2360     code_ += "#[inline]";
2361     code_ +=
2362         "pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> "
2363         "::core::cmp::Ordering {";
2364     code_ += "  let key = self.{{FIELD}}();";
2365     code_ += "  key.cmp({{REF}}val)";
2366     code_ += "}";
2367   }
2368 
2369   // Generate functions for accessing the root table object. This function
2370   // must only be called if the root table is defined.
GenRootTableFuncs(const StructDef & struct_def)2371   void GenRootTableFuncs(const StructDef &struct_def) {
2372     FLATBUFFERS_ASSERT(parser_.root_struct_def_ && "root table not defined");
2373     code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
2374     code_.SetValue("STRUCT_FN", namer_.Function(struct_def));
2375     code_.SetValue("STRUCT_CONST", namer_.Constant(struct_def.name));
2376 
2377     // The root datatype accessors:
2378     code_ += "#[inline]";
2379     code_ +=
2380         "#[deprecated(since=\"2.0.0\", "
2381         "note=\"Deprecated in favor of `root_as...` methods.\")]";
2382     code_ +=
2383         "pub fn get_root_as_{{STRUCT_FN}}<'a>(buf: &'a [u8])"
2384         " -> {{STRUCT_TY}}<'a> {";
2385     code_ +=
2386         "  unsafe { flatbuffers::root_unchecked::<{{STRUCT_TY}}"
2387         "<'a>>(buf) }";
2388     code_ += "}";
2389     code_ += "";
2390 
2391     code_ += "#[inline]";
2392     code_ +=
2393         "#[deprecated(since=\"2.0.0\", "
2394         "note=\"Deprecated in favor of `root_as...` methods.\")]";
2395     code_ +=
2396         "pub fn get_size_prefixed_root_as_{{STRUCT_FN}}"
2397         "<'a>(buf: &'a [u8]) -> {{STRUCT_TY}}<'a> {";
2398     code_ +=
2399         "  unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}"
2400         "<'a>>(buf) }";
2401     code_ += "}";
2402     code_ += "";
2403     // Default verifier root fns.
2404     code_ += "#[inline]";
2405     code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_TY}}`";
2406     code_ += "/// and returns it.";
2407     code_ += "/// Note that verification is still experimental and may not";
2408     code_ += "/// catch every error, or be maximally performant. For the";
2409     code_ += "/// previous, unchecked, behavior use";
2410     code_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
2411     code_ +=
2412         "pub fn root_as_{{STRUCT_FN}}(buf: &[u8]) "
2413         "-> Result<{{STRUCT_TY}}, flatbuffers::InvalidFlatbuffer> {";
2414     code_ += "  flatbuffers::root::<{{STRUCT_TY}}>(buf)";
2415     code_ += "}";
2416     code_ += "#[inline]";
2417     code_ += "/// Verifies that a buffer of bytes contains a size prefixed";
2418     code_ += "/// `{{STRUCT_TY}}` and returns it.";
2419     code_ += "/// Note that verification is still experimental and may not";
2420     code_ += "/// catch every error, or be maximally performant. For the";
2421     code_ += "/// previous, unchecked, behavior use";
2422     code_ += "/// `size_prefixed_root_as_{{STRUCT_FN}}_unchecked`.";
2423     code_ +=
2424         "pub fn size_prefixed_root_as_{{STRUCT_FN}}"
2425         "(buf: &[u8]) -> Result<{{STRUCT_TY}}, "
2426         "flatbuffers::InvalidFlatbuffer> {";
2427     code_ += "  flatbuffers::size_prefixed_root::<{{STRUCT_TY}}>(buf)";
2428     code_ += "}";
2429     // Verifier with options root fns.
2430     code_ += "#[inline]";
2431     code_ += "/// Verifies, with the given options, that a buffer of bytes";
2432     code_ += "/// contains a `{{STRUCT_TY}}` and returns it.";
2433     code_ += "/// Note that verification is still experimental and may not";
2434     code_ += "/// catch every error, or be maximally performant. For the";
2435     code_ += "/// previous, unchecked, behavior use";
2436     code_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
2437     code_ += "pub fn root_as_{{STRUCT_FN}}_with_opts<'b, 'o>(";
2438     code_ += "  opts: &'o flatbuffers::VerifierOptions,";
2439     code_ += "  buf: &'b [u8],";
2440     code_ +=
2441         ") -> Result<{{STRUCT_TY}}<'b>, flatbuffers::InvalidFlatbuffer>"
2442         " {";
2443     code_ += "  flatbuffers::root_with_opts::<{{STRUCT_TY}}<'b>>(opts, buf)";
2444     code_ += "}";
2445     code_ += "#[inline]";
2446     code_ += "/// Verifies, with the given verifier options, that a buffer of";
2447     code_ += "/// bytes contains a size prefixed `{{STRUCT_TY}}` and returns";
2448     code_ += "/// it. Note that verification is still experimental and may not";
2449     code_ += "/// catch every error, or be maximally performant. For the";
2450     code_ += "/// previous, unchecked, behavior use";
2451     code_ += "/// `root_as_{{STRUCT_FN}}_unchecked`.";
2452     code_ +=
2453         "pub fn size_prefixed_root_as_{{STRUCT_FN}}_with_opts"
2454         "<'b, 'o>(";
2455     code_ += "  opts: &'o flatbuffers::VerifierOptions,";
2456     code_ += "  buf: &'b [u8],";
2457     code_ +=
2458         ") -> Result<{{STRUCT_TY}}<'b>, flatbuffers::InvalidFlatbuffer>"
2459         " {";
2460     code_ +=
2461         "  flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_TY}}"
2462         "<'b>>(opts, buf)";
2463     code_ += "}";
2464     // Unchecked root fns.
2465     code_ += "#[inline]";
2466     code_ +=
2467         "/// Assumes, without verification, that a buffer of bytes "
2468         "contains a {{STRUCT_TY}} and returns it.";
2469     code_ += "/// # Safety";
2470     code_ +=
2471         "/// Callers must trust the given bytes do indeed contain a valid"
2472         " `{{STRUCT_TY}}`.";
2473     code_ +=
2474         "pub unsafe fn root_as_{{STRUCT_FN}}_unchecked"
2475         "(buf: &[u8]) -> {{STRUCT_TY}} {";
2476     code_ += "  flatbuffers::root_unchecked::<{{STRUCT_TY}}>(buf)";
2477     code_ += "}";
2478     code_ += "#[inline]";
2479     code_ +=
2480         "/// Assumes, without verification, that a buffer of bytes "
2481         "contains a size prefixed {{STRUCT_TY}} and returns it.";
2482     code_ += "/// # Safety";
2483     code_ +=
2484         "/// Callers must trust the given bytes do indeed contain a valid"
2485         " size prefixed `{{STRUCT_TY}}`.";
2486     code_ +=
2487         "pub unsafe fn size_prefixed_root_as_{{STRUCT_FN}}"
2488         "_unchecked(buf: &[u8]) -> {{STRUCT_TY}} {";
2489     code_ +=
2490         "  flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_TY}}>"
2491         "(buf)";
2492     code_ += "}";
2493 
2494     if (parser_.file_identifier_.length()) {
2495       // Declare the identifier
2496       // (no lifetime needed as constants have static lifetimes by default)
2497       code_ += "pub const {{STRUCT_CONST}}_IDENTIFIER: &str\\";
2498       code_ += " = \"" + parser_.file_identifier_ + "\";";
2499       code_ += "";
2500 
2501       // Check if a buffer has the identifier.
2502       code_ += "#[inline]";
2503       code_ += "pub fn {{STRUCT_FN}}_buffer_has_identifier\\";
2504       code_ += "(buf: &[u8]) -> bool {";
2505       code_ += "  flatbuffers::buffer_has_identifier(buf, \\";
2506       code_ += "{{STRUCT_CONST}}_IDENTIFIER, false)";
2507       code_ += "}";
2508       code_ += "";
2509       code_ += "#[inline]";
2510       code_ += "pub fn {{STRUCT_FN}}_size_prefixed\\";
2511       code_ += "_buffer_has_identifier(buf: &[u8]) -> bool {";
2512       code_ += "  flatbuffers::buffer_has_identifier(buf, \\";
2513       code_ += "{{STRUCT_CONST}}_IDENTIFIER, true)";
2514       code_ += "}";
2515       code_ += "";
2516     }
2517 
2518     if (parser_.file_extension_.length()) {
2519       // Return the extension
2520       code_ += "pub const {{STRUCT_CONST}}_EXTENSION: &str = \\";
2521       code_ += "\"" + parser_.file_extension_ + "\";";
2522       code_ += "";
2523     }
2524 
2525     // Finish a buffer with a given root object:
2526     code_ += "#[inline]";
2527     code_ += "pub fn finish_{{STRUCT_FN}}_buffer<'a, 'b>(";
2528     code_ += "    fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,";
2529     code_ += "    root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {";
2530     if (parser_.file_identifier_.length()) {
2531       code_ += "  fbb.finish(root, Some({{STRUCT_CONST}}_IDENTIFIER));";
2532     } else {
2533       code_ += "  fbb.finish(root, None);";
2534     }
2535     code_ += "}";
2536     code_ += "";
2537     code_ += "#[inline]";
2538     code_ +=
2539         "pub fn finish_size_prefixed_{{STRUCT_FN}}_buffer"
2540         "<'a, 'b>("
2541         "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, "
2542         "root: flatbuffers::WIPOffset<{{STRUCT_TY}}<'a>>) {";
2543     if (parser_.file_identifier_.length()) {
2544       code_ +=
2545           "  fbb.finish_size_prefixed(root, "
2546           "Some({{STRUCT_CONST}}_IDENTIFIER));";
2547     } else {
2548       code_ += "  fbb.finish_size_prefixed(root, None);";
2549     }
2550     code_ += "}";
2551   }
2552 
GenPadding(const FieldDef & field,std::string * code_ptr,int * id,const std::function<void (int bits,std::string * code_ptr,int * id)> & f)2553   static void GenPadding(
2554       const FieldDef &field, std::string *code_ptr, int *id,
2555       const std::function<void(int bits, std::string *code_ptr, int *id)> &f) {
2556     if (field.padding) {
2557       for (int i = 0; i < 4; i++) {
2558         if (static_cast<int>(field.padding) & (1 << i)) {
2559           f((1 << i) * 8, code_ptr, id);
2560         }
2561       }
2562       assert(!(field.padding & ~0xF));
2563     }
2564   }
2565 
PaddingDefinition(int bits,std::string * code_ptr,int * id)2566   static void PaddingDefinition(int bits, std::string *code_ptr, int *id) {
2567     *code_ptr +=
2568         "  padding" + NumToString((*id)++) + "__: u" + NumToString(bits) + ",";
2569   }
2570 
PaddingInitializer(int bits,std::string * code_ptr,int * id)2571   static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
2572     (void)bits;
2573     *code_ptr += "padding" + NumToString((*id)++) + "__: 0,";
2574   }
2575 
ForAllStructFields(const StructDef & struct_def,std::function<void (const FieldDef & field)> cb)2576   void ForAllStructFields(const StructDef &struct_def,
2577                           std::function<void(const FieldDef &field)> cb) {
2578     size_t offset_to_field = 0;
2579     for (auto it = struct_def.fields.vec.begin();
2580          it != struct_def.fields.vec.end(); ++it) {
2581       const auto &field = **it;
2582       code_.SetValue("FIELD_TYPE", GetTypeGet(field.value.type));
2583       code_.SetValue("FIELD_OTY", ObjectFieldType(field, false));
2584       code_.SetValue("FIELD", namer_.Field(field));
2585       code_.SetValue("FIELD_OFFSET", NumToString(offset_to_field));
2586       code_.SetValue(
2587           "REF",
2588           IsStruct(field.value.type) || IsArray(field.value.type) ? "&" : "");
2589       code_.IncrementIdentLevel();
2590       cb(field);
2591       code_.DecrementIdentLevel();
2592       const size_t size = InlineSize(field.value.type);
2593       offset_to_field += size + field.padding;
2594     }
2595   }
2596   // Generate an accessor struct with constructor for a flatbuffers struct.
GenStruct(const StructDef & struct_def)2597   void GenStruct(const StructDef &struct_def) {
2598     const bool is_private = parser_.opts.no_leak_private_annotations &&
2599         (struct_def.attributes.Lookup("private") != nullptr);
2600     code_.SetValue("ACCESS_TYPE", is_private ? "pub(crate)" : "pub");
2601     // Generates manual padding and alignment.
2602     // Variables are private because they contain little endian data on all
2603     // platforms.
2604     GenComment(struct_def.doc_comment);
2605     code_.SetValue("ALIGN", NumToString(struct_def.minalign));
2606     code_.SetValue("STRUCT_TY", namer_.Type(struct_def));
2607     code_.SetValue("STRUCT_SIZE", NumToString(struct_def.bytesize));
2608 
2609     // We represent Flatbuffers-structs in Rust-u8-arrays since the data may be
2610     // of the wrong endianness and alignment 1.
2611     //
2612     // PartialEq is useful to derive because we can correctly compare structs
2613     // for equality by just comparing their underlying byte data. This doesn't
2614     // hold for PartialOrd/Ord.
2615     code_ += "// struct {{STRUCT_TY}}, aligned to {{ALIGN}}";
2616     code_ += "#[repr(transparent)]";
2617     code_ += "#[derive(Clone, Copy, PartialEq)]";
2618     code_ += "{{ACCESS_TYPE}} struct {{STRUCT_TY}}(pub [u8; {{STRUCT_SIZE}}]);";
2619     code_ += "impl Default for {{STRUCT_TY}} { ";
2620     code_ += "  fn default() -> Self { ";
2621     code_ += "    Self([0; {{STRUCT_SIZE}}])";
2622     code_ += "  }";
2623     code_ += "}";
2624 
2625     // Debug for structs.
2626     code_ += "impl core::fmt::Debug for {{STRUCT_TY}} {";
2627     code_ +=
2628         "  fn fmt(&self, f: &mut core::fmt::Formatter"
2629         ") -> core::fmt::Result {";
2630     code_ += "    f.debug_struct(\"{{STRUCT_TY}}\")";
2631     ForAllStructFields(struct_def, [&](const FieldDef &unused) {
2632       (void)unused;
2633       code_ += "    .field(\"{{FIELD}}\", &self.{{FIELD}}())";
2634     });
2635     code_ += "      .finish()";
2636     code_ += "  }";
2637     code_ += "}";
2638     code_ += "";
2639 
2640     // Generate impls for SafeSliceAccess (because all structs are endian-safe),
2641     // Follow for the value type, Follow for the reference type, Push for the
2642     // value type, and Push for the reference type.
2643     code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_TY}} {}";
2644     code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_TY}} {}";
2645     code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_TY}} {";
2646     code_ += "  type Inner = &'a {{STRUCT_TY}};";
2647     code_ += "  #[inline]";
2648     code_ += "  fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
2649     code_ += "    <&'a {{STRUCT_TY}}>::follow(buf, loc)";
2650     code_ += "  }";
2651     code_ += "}";
2652     code_ += "impl<'a> flatbuffers::Follow<'a> for &'a {{STRUCT_TY}} {";
2653     code_ += "  type Inner = &'a {{STRUCT_TY}};";
2654     code_ += "  #[inline]";
2655     code_ += "  fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
2656     code_ += "    flatbuffers::follow_cast_ref::<{{STRUCT_TY}}>(buf, loc)";
2657     code_ += "  }";
2658     code_ += "}";
2659     code_ += "impl<'b> flatbuffers::Push for {{STRUCT_TY}} {";
2660     code_ += "    type Output = {{STRUCT_TY}};";
2661     code_ += "    #[inline]";
2662     code_ += "    fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
2663     code_ += "        let src = unsafe {";
2664     code_ +=
2665         "            ::core::slice::from_raw_parts("
2666         "self as *const {{STRUCT_TY}} as *const u8, Self::size())";
2667     code_ += "        };";
2668     code_ += "        dst.copy_from_slice(src);";
2669     code_ += "    }";
2670     code_ += "}";
2671     code_ += "impl<'b> flatbuffers::Push for &'b {{STRUCT_TY}} {";
2672     code_ += "    type Output = {{STRUCT_TY}};";
2673     code_ += "";
2674     code_ += "    #[inline]";
2675     code_ += "    fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
2676     code_ += "        let src = unsafe {";
2677     code_ +=
2678         "            ::core::slice::from_raw_parts("
2679         "*self as *const {{STRUCT_TY}} as *const u8, Self::size())";
2680     code_ += "        };";
2681     code_ += "        dst.copy_from_slice(src);";
2682     code_ += "    }";
2683     code_ += "}";
2684     code_ += "";
2685 
2686     // Generate verifier: Structs are simple so presence and alignment are
2687     // all that need to be checked.
2688     code_ += "impl<'a> flatbuffers::Verifiable for {{STRUCT_TY}} {";
2689     code_ += "  #[inline]";
2690     code_ += "  fn run_verifier(";
2691     code_ += "    v: &mut flatbuffers::Verifier, pos: usize";
2692     code_ += "  ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
2693     code_ += "    use self::flatbuffers::Verifiable;";
2694     code_ += "    v.in_buffer::<Self>(pos)";
2695     code_ += "  }";
2696     code_ += "}";
2697     code_ += "";
2698 
2699     // Implement serde::Serialize
2700     if (parser_.opts.rust_serialize) {
2701       const auto numFields = struct_def.fields.vec.size();
2702       code_.SetValue("NUM_FIELDS", NumToString(numFields));
2703       code_ += "impl Serialize for {{STRUCT_TY}} {";
2704       code_ +=
2705           "  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>";
2706       code_ += "  where";
2707       code_ += "    S: Serializer,";
2708       code_ += "  {";
2709       if (numFields == 0) {
2710         code_ +=
2711             "    let s = serializer.serialize_struct(\"{{STRUCT_TY}}\", 0)?;";
2712       } else {
2713         code_ +=
2714             "    let mut s = serializer.serialize_struct(\"{{STRUCT_TY}}\", "
2715             "{{NUM_FIELDS}})?;";
2716       }
2717       ForAllStructFields(struct_def, [&](const FieldDef &unused) {
2718         (void)unused;
2719         code_ +=
2720             "    s.serialize_field(\"{{FIELD}}\", "
2721             "&self.{{FIELD}}())?;";
2722       });
2723       code_ += "    s.end()";
2724       code_ += "  }";
2725       code_ += "}";
2726       code_ += "";
2727     }
2728 
2729     // Generate a constructor that takes all fields as arguments.
2730     code_ += "impl<'a> {{STRUCT_TY}} {";
2731     code_ += "  #[allow(clippy::too_many_arguments)]";
2732     code_ += "  pub fn new(";
2733     ForAllStructFields(struct_def, [&](const FieldDef &unused) {
2734       (void)unused;
2735       code_ += "  {{FIELD}}: {{REF}}{{FIELD_TYPE}},";
2736     });
2737     code_ += "  ) -> Self {";
2738     code_ += "    let mut s = Self([0; {{STRUCT_SIZE}}]);";
2739     ForAllStructFields(struct_def, [&](const FieldDef &unused) {
2740       (void)unused;
2741       code_ += "  s.set_{{FIELD}}({{FIELD}});";
2742     });
2743     code_ += "    s";
2744     code_ += "  }";
2745     code_ += "";
2746 
2747     if (parser_.opts.generate_name_strings) {
2748       GenFullyQualifiedNameGetter(struct_def, struct_def.name);
2749     }
2750 
2751     // Generate accessor methods for the struct.
2752     ForAllStructFields(struct_def, [&](const FieldDef &field) {
2753       this->GenComment(field.doc_comment);
2754       // Getter.
2755       if (IsStruct(field.value.type)) {
2756         code_ += "pub fn {{FIELD}}(&self) -> &{{FIELD_TYPE}} {";
2757         code_ +=
2758             "  unsafe {"
2759             " &*(self.0[{{FIELD_OFFSET}}..].as_ptr() as *const"
2760             " {{FIELD_TYPE}}) }";
2761       } else if (IsArray(field.value.type)) {
2762         code_.SetValue("ARRAY_SIZE",
2763                        NumToString(field.value.type.fixed_length));
2764         code_.SetValue("ARRAY_ITEM", GetTypeGet(field.value.type.VectorType()));
2765         code_ +=
2766             "pub fn {{FIELD}}(&'a self) -> "
2767             "flatbuffers::Array<'a, {{ARRAY_ITEM}}, {{ARRAY_SIZE}}> {";
2768         code_ += "  flatbuffers::Array::follow(&self.0, {{FIELD_OFFSET}})";
2769       } else {
2770         code_ += "pub fn {{FIELD}}(&self) -> {{FIELD_TYPE}} {";
2771         code_ +=
2772             "  let mut mem = core::mem::MaybeUninit::"
2773             "<{{FIELD_TYPE}}>::uninit();";
2774         code_ += "  unsafe {";
2775         code_ += "    core::ptr::copy_nonoverlapping(";
2776         code_ += "      self.0[{{FIELD_OFFSET}}..].as_ptr(),";
2777         code_ += "      mem.as_mut_ptr() as *mut u8,";
2778         code_ += "      core::mem::size_of::<{{FIELD_TYPE}}>(),";
2779         code_ += "    );";
2780         code_ += "    mem.assume_init()";
2781         code_ += "  }.from_little_endian()";
2782       }
2783       code_ += "}\n";
2784       // Setter.
2785       if (IsStruct(field.value.type)) {
2786         code_.SetValue("FIELD_SIZE", NumToString(InlineSize(field.value.type)));
2787         code_ += "#[allow(clippy::identity_op)]";  // If FIELD_OFFSET=0.
2788         code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
2789         code_ +=
2790             "  self.0[{{FIELD_OFFSET}}..{{FIELD_OFFSET}} + {{FIELD_SIZE}}]"
2791             ".copy_from_slice(&x.0)";
2792       } else if (IsArray(field.value.type)) {
2793         if (GetFullType(field.value.type) == ftArrayOfBuiltin) {
2794           code_.SetValue("ARRAY_ITEM",
2795                          GetTypeGet(field.value.type.VectorType()));
2796           code_.SetValue(
2797               "ARRAY_ITEM_SIZE",
2798               NumToString(InlineSize(field.value.type.VectorType())));
2799           code_ +=
2800               "pub fn set_{{FIELD}}(&mut self, items: &{{FIELD_TYPE}}) "
2801               "{";
2802           code_ +=
2803               "  flatbuffers::emplace_scalar_array(&mut self.0, "
2804               "{{FIELD_OFFSET}}, items);";
2805         } else {
2806           code_.SetValue("FIELD_SIZE",
2807                          NumToString(InlineSize(field.value.type)));
2808           code_ += "pub fn set_{{FIELD}}(&mut self, x: &{{FIELD_TYPE}}) {";
2809           code_ += "  unsafe {";
2810           code_ += "    core::ptr::copy(";
2811           code_ += "      x.as_ptr() as *const u8,";
2812           code_ += "      self.0.as_mut_ptr().add({{FIELD_OFFSET}}),";
2813           code_ += "      {{FIELD_SIZE}},";
2814           code_ += "    );";
2815           code_ += "  }";
2816         }
2817       } else {
2818         code_ += "pub fn set_{{FIELD}}(&mut self, x: {{FIELD_TYPE}}) {";
2819         code_ += "  let x_le = x.to_little_endian();";
2820         code_ += "  unsafe {";
2821         code_ += "    core::ptr::copy_nonoverlapping(";
2822         code_ += "      &x_le as *const {{FIELD_TYPE}} as *const u8,";
2823         code_ += "      self.0[{{FIELD_OFFSET}}..].as_mut_ptr(),";
2824         code_ += "      core::mem::size_of::<{{FIELD_TYPE}}>(),";
2825         code_ += "    );";
2826         code_ += "  }";
2827       }
2828       code_ += "}\n";
2829 
2830       // Generate a comparison function for this field if it is a key.
2831       if (field.key) { GenKeyFieldMethods(field); }
2832     });
2833 
2834     // Generate Object API unpack method.
2835     if (parser_.opts.generate_object_based_api) {
2836       code_.SetValue("STRUCT_OTY", namer_.ObjectType(struct_def));
2837       code_ += "  pub fn unpack(&self) -> {{STRUCT_OTY}} {";
2838       code_ += "    {{STRUCT_OTY}} {";
2839       ForAllStructFields(struct_def, [&](const FieldDef &field) {
2840         if (IsArray(field.value.type)) {
2841           if (GetFullType(field.value.type) == ftArrayOfStruct) {
2842             code_ +=
2843                 "    {{FIELD}}: { let {{FIELD}} = "
2844                 "self.{{FIELD}}(); flatbuffers::array_init(|i| "
2845                 "{{FIELD}}.get(i).unpack()) },";
2846           } else {
2847             code_ += "    {{FIELD}}: self.{{FIELD}}().into(),";
2848           }
2849         } else {
2850           std::string unpack = IsStruct(field.value.type) ? ".unpack()" : "";
2851           code_ += "    {{FIELD}}: self.{{FIELD}}()" + unpack + ",";
2852         }
2853       });
2854       code_ += "    }";
2855       code_ += "  }";
2856     }
2857 
2858     code_ += "}";  // End impl Struct methods.
2859     code_ += "";
2860 
2861     // Generate Struct Object.
2862     if (parser_.opts.generate_object_based_api) {
2863       // Struct declaration
2864       code_ += "#[derive(Debug, Clone, PartialEq, Default)]";
2865       code_ += "{{ACCESS_TYPE}} struct {{STRUCT_OTY}} {";
2866       ForAllStructFields(struct_def, [&](const FieldDef &field) {
2867         (void)field;  // unused.
2868         code_ += "pub {{FIELD}}: {{FIELD_OTY}},";
2869       });
2870       code_ += "}";
2871       // The `pack` method that turns the native struct into its Flatbuffers
2872       // counterpart.
2873       code_ += "impl {{STRUCT_OTY}} {";
2874       code_ += "  pub fn pack(&self) -> {{STRUCT_TY}} {";
2875       code_ += "    {{STRUCT_TY}}::new(";
2876       ForAllStructFields(struct_def, [&](const FieldDef &field) {
2877         if (IsStruct(field.value.type)) {
2878           code_ += "    &self.{{FIELD}}.pack(),";
2879         } else if (IsArray(field.value.type)) {
2880           if (GetFullType(field.value.type) == ftArrayOfStruct) {
2881             code_ +=
2882                 "    &flatbuffers::array_init(|i| "
2883                 "self.{{FIELD}}[i].pack()),";
2884           } else {
2885             code_ += "    &self.{{FIELD}},";
2886           }
2887         } else {
2888           code_ += "    self.{{FIELD}},";
2889         }
2890       });
2891       code_ += "    )";
2892       code_ += "  }";
2893       code_ += "}";
2894       code_ += "";
2895     }
2896   }
2897 
GenNamespaceImports(const int white_spaces)2898   void GenNamespaceImports(const int white_spaces) {
2899     // DO not use global attributes (i.e. #![...]) since it interferes
2900     // with users who include! generated files.
2901     // See: https://github.com/google/flatbuffers/issues/6261
2902     std::string indent = std::string(white_spaces, ' ');
2903     code_ += "";
2904     if (!parser_.opts.generate_all) {
2905       for (auto it = parser_.included_files_.begin();
2906            it != parser_.included_files_.end(); ++it) {
2907         if (it->second.empty()) continue;
2908         auto noext = flatbuffers::StripExtension(it->second);
2909         auto basename = flatbuffers::StripPath(noext);
2910 
2911         if (parser_.opts.include_prefix.empty()) {
2912           code_ += indent + "use crate::" + basename +
2913                    parser_.opts.filename_suffix + "::*;";
2914         } else {
2915           auto prefix = parser_.opts.include_prefix;
2916           prefix.pop_back();
2917 
2918           code_ += indent + "use crate::" + prefix + "::" + basename +
2919                    parser_.opts.filename_suffix + "::*;";
2920         }
2921       }
2922     }
2923     code_ += indent + "use core::mem;";
2924     code_ += indent + "use core::cmp::Ordering;";
2925     code_ += "";
2926     if (parser_.opts.rust_serialize) {
2927       code_ += indent + "extern crate serde;";
2928       code_ +=
2929           indent +
2930           "use self::serde::ser::{Serialize, Serializer, SerializeStruct};";
2931       code_ += "";
2932     }
2933     code_ += indent + "extern crate flatbuffers;";
2934     code_ += indent + "use self::flatbuffers::{EndianScalar, Follow};";
2935   }
2936 
2937   // Set up the correct namespace. This opens a namespace if the current
2938   // namespace is different from the target namespace. This function
2939   // closes and opens the namespaces only as necessary.
2940   //
2941   // The file must start and end with an empty (or null) namespace so that
2942   // namespaces are properly opened and closed.
SetNameSpace(const Namespace * ns)2943   void SetNameSpace(const Namespace *ns) {
2944     if (cur_name_space_ == ns) { return; }
2945 
2946     // Compute the size of the longest common namespace prefix.
2947     // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
2948     // the common prefix is A::B:: and we have old_size = 4, new_size = 5
2949     // and common_prefix_size = 2
2950     size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
2951     size_t new_size = ns ? ns->components.size() : 0;
2952 
2953     size_t common_prefix_size = 0;
2954     while (common_prefix_size < old_size && common_prefix_size < new_size &&
2955            ns->components[common_prefix_size] ==
2956                cur_name_space_->components[common_prefix_size]) {
2957       common_prefix_size++;
2958     }
2959 
2960     // Close cur_name_space in reverse order to reach the common prefix.
2961     // In the previous example, D then C are closed.
2962     for (size_t j = old_size; j > common_prefix_size; --j) {
2963       code_ += "}  // pub mod " + cur_name_space_->components[j - 1];
2964     }
2965     if (old_size != common_prefix_size) { code_ += ""; }
2966 
2967     // open namespace parts to reach the ns namespace
2968     // in the previous example, E, then F, then G are opened
2969     for (auto j = common_prefix_size; j != new_size; ++j) {
2970       code_ += "#[allow(unused_imports, dead_code)]";
2971       code_ += "pub mod " + namer_.Namespace(ns->components[j]) + " {";
2972       // Generate local namespace imports.
2973       GenNamespaceImports(2);
2974     }
2975     if (new_size != common_prefix_size) { code_ += ""; }
2976 
2977     cur_name_space_ = ns;
2978   }
2979 
2980  private:
2981   IdlNamer namer_;
2982 };
2983 
2984 }  // namespace rust
2985 
GenerateRust(const Parser & parser,const std::string & path,const std::string & file_name)2986 bool GenerateRust(const Parser &parser, const std::string &path,
2987                   const std::string &file_name) {
2988   rust::RustGenerator generator(parser, path, file_name);
2989   return generator.generate();
2990 }
2991 
RustMakeRule(const Parser & parser,const std::string & path,const std::string & file_name)2992 std::string RustMakeRule(const Parser &parser, const std::string &path,
2993                          const std::string &file_name) {
2994   std::string filebase =
2995       flatbuffers::StripPath(flatbuffers::StripExtension(file_name));
2996   rust::RustGenerator generator(parser, path, file_name);
2997   std::string make_rule =
2998       generator.GeneratedFileName(path, filebase, parser.opts) + ": ";
2999 
3000   auto included_files = parser.GetIncludedFilesRecursive(file_name);
3001   for (auto it = included_files.begin(); it != included_files.end(); ++it) {
3002     make_rule += " " + *it;
3003   }
3004   return make_rule;
3005 }
3006 
3007 }  // namespace flatbuffers
3008 
3009 // TODO(rw): Generated code should import other generated files.
3010 // TODO(rw): Generated code should refer to namespaces in included files in a
3011 //           way that makes them referrable.
3012 // TODO(rw): Generated code should indent according to nesting level.
3013 // TODO(rw): Generated code should generate endian-safe Debug impls.
3014 // TODO(rw): Generated code could use a Rust-only enum type to access unions,
3015 //           instead of making the user use _type() to manually switch.
3016 // TODO(maxburke): There should be test schemas added that use language
3017 //           keywords as fields of structs, tables, unions, enums, to make sure
3018 //           that internal code generated references escaped names correctly.
3019 // TODO(maxburke): We should see if there is a more flexible way of resolving
3020 //           module paths for use declarations. Right now if schemas refer to
3021 //           other flatbuffer files, the include paths in emitted Rust bindings
3022 //           are crate-relative which may undesirable.
3023