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