xref: /aosp_15_r20/external/flatbuffers/src/idl_gen_swift.cpp (revision 890232f25432b36107d06881e0a25aaa6b473652)
1 /*
2  * Copyright 2020 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cctype>
18 #include <unordered_set>
19 
20 #include "flatbuffers/code_generators.h"
21 #include "flatbuffers/flatbuffers.h"
22 #include "flatbuffers/idl.h"
23 #include "flatbuffers/util.h"
24 #include "idl_namer.h"
25 
26 namespace flatbuffers {
27 
28 namespace swift {
29 
30 namespace {
31 
SwiftDefaultConfig()32 static Namer::Config SwiftDefaultConfig() {
33   return { /*types=*/Case::kKeep,
34            /*constants=*/Case::kLowerCamel,
35            /*methods=*/Case::kLowerCamel,
36            /*functions=*/Case::kLowerCamel,
37            /*fields=*/Case::kLowerCamel,
38            /*variables=*/Case::kLowerCamel,
39            /*variants=*/Case::kLowerCamel,
40            /*enum_variant_seperator=*/".",
41            /*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
42            /*namespaces=*/Case::kKeep,
43            /*namespace_seperator=*/"_",
44            /*object_prefix=*/"",
45            /*object_suffix=*/"T",
46            /*keyword_prefix=*/"",
47            /*keyword_suffix=*/"_",
48            /*filenames=*/Case::kKeep,
49            /*directories=*/Case::kKeep,
50            /*output_path=*/"",
51            /*filename_suffix=*/"_generated",
52            /*filename_extension=*/".swift" };
53 }
54 
SwiftKeywords()55 static std::set<std::string> SwiftKeywords() {
56   return {
57     "associatedtype",
58     "class",
59     "deinit",
60     "enum",
61     "extension",
62     "fileprivate",
63     "func",
64     "import",
65     "init",
66     "inout",
67     "internal",
68     "let",
69     "open",
70     "operator",
71     "private",
72     "protocol",
73     "public",
74     "rethrows",
75     "static",
76     "struct",
77     "subscript",
78     "typealias",
79     "var",
80     "break",
81     "case",
82     "continue",
83     "default",
84     "defer",
85     "do",
86     "else",
87     "fallthrough",
88     "for",
89     "guard",
90     "if",
91     "in",
92     "repeat",
93     "return",
94     "switch",
95     "where",
96     "while",
97     "Any",
98     "catch",
99     "false",
100     "is",
101     "nil",
102     "super",
103     "self",
104     "Self",
105     "throw",
106     "throws",
107     "true",
108     "try",
109     "associativity",
110     "convenience",
111     "dynamic",
112     "didSet",
113     "final",
114     "get",
115     "infix",
116     "indirect",
117     "lazy",
118     "left",
119     "mutating",
120     "none",
121     "nonmutating",
122     "optional",
123     "override",
124     "postfix",
125     "precedence",
126     "prefix",
127     "Protocol",
128     "required",
129     "right",
130     "set",
131     "Type",
132     "unowned",
133     "weak",
134     "willSet",
135     "Void",
136   };
137 }
138 
GenIndirect(const std::string & reading)139 static std::string GenIndirect(const std::string &reading) {
140   return "{{ACCESS}}.indirect(" + reading + ")";
141 }
142 
GenArrayMainBody(const std::string & optional)143 static std::string GenArrayMainBody(const std::string &optional) {
144   return "{{ACCESS_TYPE}} func {{FIELDMETHOD}}(at index: Int32) -> "
145          "{{VALUETYPE}}" +
146          optional + " { ";
147 }
148 
149 } // namespace
150 
151 class SwiftGenerator : public BaseGenerator {
152  private:
153   CodeWriter code_;
154   std::unordered_set<std::string> keywords_;
155   int namespace_depth;
156 
157  public:
SwiftGenerator(const Parser & parser,const std::string & path,const std::string & file_name)158   SwiftGenerator(const Parser &parser, const std::string &path,
159                  const std::string &file_name)
160       : BaseGenerator(parser, path, file_name, "", "_", "swift"),
161         namer_(WithFlagOptions(SwiftDefaultConfig(), parser.opts, path),
162                SwiftKeywords()) {
163     namespace_depth = 0;
164     code_.SetPadding("  ");
165   }
166 
generate()167   bool generate() {
168     code_.Clear();
169     code_.SetValue("ACCESS", "_accessor");
170     code_.SetValue("TABLEOFFSET", "VTOFFSET");
171     code_ += "// " + std::string(FlatBuffersGeneratedWarning());
172     code_ += "// swiftlint:disable all";
173     code_ += "// swiftformat:disable all\n";
174     if (parser_.opts.include_dependence_headers || parser_.opts.generate_all) {
175       if (parser_.opts.swift_implementation_only)
176         code_ += "@_implementationOnly \\";
177 
178       code_ += "import FlatBuffers\n";
179     }
180 
181     // Generate code for all the enum declarations.
182     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
183          ++it) {
184       const auto &enum_def = **it;
185       if (!enum_def.generated) { GenEnum(enum_def); }
186     }
187 
188     for (auto it = parser_.structs_.vec.begin();
189          it != parser_.structs_.vec.end(); ++it) {
190       const auto &struct_def = **it;
191       if (struct_def.fixed && !struct_def.generated) {
192         GenStructReader(struct_def);
193         GenMutableStructReader(struct_def);
194       }
195     }
196 
197     for (auto it = parser_.structs_.vec.begin();
198          it != parser_.structs_.vec.end(); ++it) {
199       const auto &struct_def = **it;
200       if (!struct_def.fixed && !struct_def.generated) {
201         GenTable(struct_def);
202         if (parser_.opts.generate_object_based_api) {
203           GenObjectAPI(struct_def);
204         }
205       }
206     }
207 
208     const auto filename = GeneratedFileName(path_, file_name_, parser_.opts);
209     const auto final_code = code_.ToString();
210     return SaveFile(filename.c_str(), final_code, false);
211   }
212 
mark(const std::string & str)213   void mark(const std::string &str) {
214     code_.SetValue("MARKVALUE", str);
215     code_ += "\n// MARK: - {{MARKVALUE}}\n";
216   }
217 
218   // MARK: - Generating structs
219 
220   // Generates the reader for swift
GenStructReader(const StructDef & struct_def)221   void GenStructReader(const StructDef &struct_def) {
222     const bool is_private_access =
223         parser_.opts.swift_implementation_only ||
224         struct_def.attributes.Lookup("private") != nullptr;
225     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
226     GenComment(struct_def.doc_comment);
227     code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
228     code_ +=
229         "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct, Verifiable, "
230         "FlatbuffersInitializable\\";
231     if (parser_.opts.generate_object_based_api) code_ += ", NativeObject\\";
232     code_ += " {";
233     code_ += "";
234     Indent();
235     code_ += ValidateFunc();
236     code_ += "";
237     int padding_id = 0;
238     std::string constructor = "";
239     std::vector<std::string> base_constructor;
240     std::vector<std::string> main_constructor;
241 
242     for (auto it = struct_def.fields.vec.begin();
243          it != struct_def.fields.vec.end(); ++it) {
244       const auto &field = **it;
245       if (field.deprecated) continue;
246 
247       if (!constructor.empty()) constructor += ", ";
248 
249       const auto field_var = namer_.Variable(field);
250       const auto type = GenType(field.value.type);
251       code_.SetValue("FIELDVAR", field_var);
252       if (IsEnum(field.value.type)) {
253         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
254       }
255       code_.SetValue("VALUETYPE", type);
256       GenComment(field.doc_comment);
257       std::string valueType =
258           IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}";
259       code_ += "private var _{{FIELDVAR}}: " + valueType;
260       const auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
261       const auto is_bool = IsBool(field.value.type.base_type);
262       const auto base_value =
263           IsStruct(field.value.type) ? (type + "()")
264           : is_bool ? ("0" == field.value.constant ? "false" : "true")
265                     : field.value.constant;
266 
267       main_constructor.push_back("_" + field_var + " = " + field_var +
268                                  accessing_value);
269       base_constructor.push_back("_" + field_var + " = " + base_value);
270 
271       if (field.padding) { GenPadding(field, &padding_id); }
272       constructor += field_var + ": " + type;
273     }
274     code_ += "";
275     BuildStructConstructor(struct_def);
276     BuildObjectConstructor(main_constructor, constructor);
277     BuildObjectConstructor(base_constructor, "");
278 
279     if (parser_.opts.generate_object_based_api)
280       GenerateObjectAPIStructConstructor(struct_def);
281 
282     for (auto it = struct_def.fields.vec.begin();
283          it != struct_def.fields.vec.end(); ++it) {
284       const auto &field = **it;
285       if (field.deprecated) continue;
286       code_.SetValue("FIELDVAR", namer_.Variable(field));
287       code_.SetValue("VALUETYPE", GenType(field.value.type));
288       GenComment(field.doc_comment);
289       if (!IsEnum(field.value.type)) {
290         code_ += GenReaderMainBody() + "_{{FIELDVAR}} }";
291       } else if (IsEnum(field.value.type)) {
292         code_ +=
293             GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{FIELDVAR}})! }";
294       }
295     }
296     code_ += "";
297     code_ +=
298         "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
299         "position: "
300         "Int, of type: T.Type) throws where T: Verifiable {";
301     Indent();
302     code_ +=
303         "try verifier.inBuffer(position: position, of: {{STRUCTNAME}}.self)";
304     Outdent();
305     code_ += "}";
306     Outdent();
307     code_ += "}\n";
308     if (parser_.opts.gen_json_coders) GenerateJSONEncodingAPIs(struct_def);
309   }
310 
BuildStructConstructor(const StructDef & struct_def)311   void BuildStructConstructor(const StructDef &struct_def) {
312     code_ += "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) {";
313     Indent();
314     code_ += "let {{ACCESS}} = Struct(bb: bb, position: o)";
315     for (auto it = struct_def.fields.vec.begin();
316          it != struct_def.fields.vec.end(); ++it) {
317       const auto &field = **it;
318       if (field.deprecated) continue;
319       const auto type = field.value.type;
320       code_.SetValue("FIELDVAR", namer_.Variable(field));
321       code_.SetValue("VALUETYPE", GenType(type));
322       code_.SetValue("OFFSET", NumToString(field.value.offset));
323       if (IsScalar(type.base_type)) {
324         if (IsEnum(type))
325           code_.SetValue("VALUETYPE", GenTypeBasic(field.value.type, false));
326         code_ +=
327             "_{{FIELDVAR}} = {{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, "
328             "at: {{OFFSET}})";
329       } else {
330         code_ +=
331             "_{{FIELDVAR}} = {{VALUETYPE}}({{ACCESS}}.bb, o: "
332             "{{ACCESS}}.postion + {{OFFSET}})";
333       }
334     }
335     Outdent();
336     code_ += "}\n";
337   }
338 
GenMutableStructReader(const StructDef & struct_def)339   void GenMutableStructReader(const StructDef &struct_def) {
340     GenObjectHeader(struct_def);
341 
342     for (auto it = struct_def.fields.vec.begin();
343          it != struct_def.fields.vec.end(); ++it) {
344       const auto &field = **it;
345       if (field.deprecated) continue;
346       const auto offset = NumToString(field.value.offset);
347       const auto type = GenType(field.value.type);
348       code_.SetValue("FIELDVAR", namer_.Variable(field));
349       if (IsEnum(field.value.type)) {
350         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
351       }
352       code_.SetValue("VALUETYPE", type);
353       code_.SetValue("OFFSET", offset);
354       if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
355         code_ +=
356             GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
357       } else if (IsEnum(field.value.type)) {
358         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
359         code_ += GenReaderMainBody() + "return " +
360                  GenEnumConstructor("{{OFFSET}}") + "?? " +
361                  GenEnumDefaultValue(field) + " }";
362       } else if (IsStruct(field.value.type)) {
363         code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
364         code_ += GenReaderMainBody() + "return " +
365                  GenConstructor("{{ACCESS}}.postion + {{OFFSET}}");
366       }
367       if (parser_.opts.mutable_buffer && !IsStruct(field.value.type))
368         code_ += GenMutate("{{OFFSET}}", "", IsEnum(field.value.type));
369     }
370 
371     if (parser_.opts.generate_object_based_api) {
372       GenerateObjectAPIExtensionHeader(namer_.NamespacedType(struct_def));
373       code_ += "return builder.create(struct: obj)";
374       Outdent();
375       code_ += "}";
376     }
377     Outdent();
378     code_ += "}\n";
379   }
380 
381   // Generates the create function for swift
GenStructWriter(const StructDef & struct_def)382   void GenStructWriter(const StructDef &struct_def) {
383     const bool is_private_access =
384         parser_.opts.swift_implementation_only ||
385         struct_def.attributes.Lookup("private") != nullptr;
386     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
387     code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
388     code_.SetValue("SHORT_STRUCTNAME", namer_.Method(struct_def));
389     code_ += "extension {{STRUCTNAME}} {";
390     Indent();
391     code_ += "@discardableResult";
392     code_ +=
393         "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(builder: inout "
394         "FlatBufferBuilder, \\";
395     std::string func_header = "";
396     GenerateStructArgs(struct_def, &func_header, "", "");
397     code_ += func_header.substr(0, func_header.size() - 2) + "\\";
398     code_ += ") -> Offset {";
399     Indent();
400     code_ +=
401         "builder.createStructOf(size: {{STRUCTNAME}}.size, alignment: "
402         "{{STRUCTNAME}}.alignment)";
403     code_ += "return builder.endStruct()";
404     Outdent();
405     code_ += "}\n";
406     Outdent();
407     code_ += "}\n";
408   }
409 
GenerateStructArgs(const StructDef & struct_def,std::string * code_ptr,const std::string & nameprefix,const std::string & object_name,const std::string & obj_api_named="",bool is_obj_api=false)410   void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr,
411                           const std::string &nameprefix,
412                           const std::string &object_name,
413                           const std::string &obj_api_named = "",
414                           bool is_obj_api = false) {
415     auto &code = *code_ptr;
416     for (auto it = struct_def.fields.vec.begin();
417          it != struct_def.fields.vec.end(); ++it) {
418       const auto &field = **it;
419       if (field.deprecated) continue;
420       const auto &field_type = field.value.type;
421       if (IsStruct(field.value.type)) {
422         GenerateStructArgs(
423             *field_type.struct_def, code_ptr, (nameprefix + field.name),
424             (object_name + "." + field.name), obj_api_named, is_obj_api);
425       } else {
426         const auto field_var = namer_.Variable(field);
427         const auto field_field = namer_.Field(field);
428         const auto type = GenType(field.value.type);
429         if (!is_obj_api) {
430           code += nameprefix + field_var + ": " + type;
431           if (!IsEnum(field.value.type)) {
432             code += " = ";
433             const auto is_bool = IsBool(field.value.type.base_type);
434             const auto constant =
435                 is_bool ? ("0" == field.value.constant ? "false" : "true")
436                         : field.value.constant;
437             code += constant;
438           }
439           code += ", ";
440           continue;
441         }
442         code += nameprefix + field_var + ": " + obj_api_named + object_name +
443                 "." + field_field;
444         code += ", ";
445       }
446     }
447   }
448 
449   // MARK: - Table Generator
450 
451   // Generates the reader for swift
GenTable(const StructDef & struct_def)452   void GenTable(const StructDef &struct_def) {
453     const bool is_private_access =
454         parser_.opts.swift_implementation_only ||
455         struct_def.attributes.Lookup("private") != nullptr;
456     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
457     GenObjectHeader(struct_def);
458     GenTableAccessors(struct_def);
459     GenTableReader(struct_def);
460     GenTableWriter(struct_def);
461     if (parser_.opts.generate_object_based_api)
462       GenerateObjectAPITableExtension(struct_def);
463     code_ += "";
464     GenerateVerifier(struct_def);
465     Outdent();
466     code_ += "}\n";
467     if (parser_.opts.gen_json_coders) GenerateJSONEncodingAPIs(struct_def);
468   }
469 
470   // Generates the reader for swift
GenTableAccessors(const StructDef & struct_def)471   void GenTableAccessors(const StructDef &struct_def) {
472     // Generate field id constants.
473     if (struct_def.fields.vec.size() > 0) {
474       code_ += "private enum {{TABLEOFFSET}}: VOffset {";
475       Indent();
476       for (auto it = struct_def.fields.vec.begin();
477            it != struct_def.fields.vec.end(); ++it) {
478         const auto &field = **it;
479         if (field.deprecated) { continue; }
480         code_.SetValue("OFFSET_NAME", namer_.Variable(field));
481         code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
482         code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
483       }
484       code_ += "var v: Int32 { Int32(self.rawValue) }";
485       code_ += "var p: VOffset { self.rawValue }";
486       Outdent();
487       code_ += "}";
488       code_ += "";
489     }
490   }
491 
GenObjectHeader(const StructDef & struct_def)492   void GenObjectHeader(const StructDef &struct_def) {
493     GenComment(struct_def.doc_comment);
494 
495     code_.SetValue("SHORT_STRUCTNAME", namer_.Type(struct_def));
496     code_.SetValue("STRUCTNAME", namer_.NamespacedType(struct_def));
497     code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
498     code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
499     code_ +=
500         "{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: FlatBufferObject\\";
501     if (!struct_def.fixed) code_ += ", Verifiable\\";
502     if (!struct_def.fixed && parser_.opts.generate_object_based_api)
503       code_ += ", ObjectAPIPacker\\";
504     code_ += " {\n";
505     Indent();
506     code_ += ValidateFunc();
507     code_ +=
508         "{{ACCESS_TYPE}} var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
509     code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n";
510     if (!struct_def.fixed) {
511       if (parser_.file_identifier_.length()) {
512         code_.SetValue("FILENAME", parser_.file_identifier_);
513         code_ += "{{ACCESS_TYPE}} static var id: String { \"{{FILENAME}}\" } ";
514         code_ +=
515             "{{ACCESS_TYPE}} static func finish(_ fbb: inout "
516             "FlatBufferBuilder, end: "
517             "Offset, prefix: Bool = false) { fbb.finish(offset: end, "
518             "fileId: "
519             "{{STRUCTNAME}}.id, addPrefix: prefix) }";
520       }
521       code_ +=
522           "{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: "
523           "ByteBuffer) -> "
524           "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: "
525           "Int32(bb.read(def: UOffset.self, position: bb.reader)) + "
526           "Int32(bb.reader))) }\n";
527       code_ += "private init(_ t: Table) { {{ACCESS}} = t }";
528     }
529     code_ +=
530         "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
531         "{{OBJECTTYPE}}(bb: "
532         "bb, position: o) }";
533     code_ += "";
534   }
535 
GenTableWriter(const StructDef & struct_def)536   void GenTableWriter(const StructDef &struct_def) {
537     flatbuffers::FieldDef *key_field = nullptr;
538     std::vector<std::string> require_fields;
539     std::vector<std::string> create_func_body;
540     std::vector<std::string> create_func_header;
541     const auto should_generate_create = struct_def.fields.vec.size() != 0;
542 
543     code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
544     code_ +=
545         "{{ACCESS_TYPE}} static func start{{SHORT_STRUCTNAME}}(_ fbb: inout "
546         "FlatBufferBuilder) -> "
547         "UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
548 
549     for (auto it = struct_def.fields.vec.begin();
550          it != struct_def.fields.vec.end(); ++it) {
551       auto &field = **it;
552       if (field.deprecated) continue;
553       if (field.key) key_field = &field;
554       if (field.IsRequired())
555         require_fields.push_back(NumToString(field.value.offset));
556 
557       GenTableWriterFields(field, &create_func_body, &create_func_header);
558     }
559     code_ +=
560         "{{ACCESS_TYPE}} static func end{{SHORT_STRUCTNAME}}(_ fbb: inout "
561         "FlatBufferBuilder, "
562         "start: "
563         "UOffset) -> Offset { let end = Offset(offset: "
564         "fbb.endTable(at: start))\\";
565     if (require_fields.capacity() != 0) {
566       std::string fields = "";
567       for (auto it = require_fields.begin(); it != require_fields.end(); ++it)
568         fields += *it + ", ";
569       code_.SetValue("FIELDS", fields.substr(0, fields.size() - 2));
570       code_ += "; fbb.require(table: end, fields: [{{FIELDS}}])\\";
571     }
572     code_ += "; return end }";
573 
574     if (should_generate_create) {
575       code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(";
576       Indent();
577       code_ += "_ fbb: inout FlatBufferBuilder,";
578       for (auto it = create_func_header.begin(); it < create_func_header.end();
579            ++it) {
580         code_ += *it + "\\";
581         if (it < create_func_header.end() - 1) code_ += ",";
582       }
583       code_ += "";
584       Outdent();
585       code_ += ") -> Offset {";
586       Indent();
587       code_ += "let __start = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&fbb)";
588       for (auto it = create_func_body.begin(); it < create_func_body.end();
589            ++it) {
590         code_ += *it;
591       }
592       code_ +=
593           "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&fbb, start: __start)";
594       Outdent();
595       code_ += "}";
596     }
597 
598     std::string spacing = "";
599 
600     if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
601       code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
602 
603       code_ += "{{ACCESS_TYPE}} static func " +
604                namer_.Method("sort_vector_of", struct_def) +
605                "(offsets:[Offset], "
606                "_ fbb: inout FlatBufferBuilder) -> Offset {";
607       Indent();
608       code_ += spacing + "var off = offsets";
609       code_ +=
610           spacing +
611           "off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: "
612           "{{VOFFSET}}, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: "
613           "{{VOFFSET}}, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } ";
614       code_ += spacing + "return fbb.createVector(ofOffsets: off)";
615       Outdent();
616       code_ += "}";
617       GenLookup(*key_field, namer_.NamespacedType(struct_def));
618     }
619   }
620 
GenTableWriterFields(const FieldDef & field,std::vector<std::string> * create_body,std::vector<std::string> * create_header)621   void GenTableWriterFields(const FieldDef &field,
622                             std::vector<std::string> *create_body,
623                             std::vector<std::string> *create_header) {
624     std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { ";
625     auto &create_func_body = *create_body;
626     auto &create_func_header = *create_header;
627     const auto field_field = namer_.Field(field);
628     const auto field_var = namer_.Variable(field);
629     const auto type = GenType(field.value.type);
630     const auto opt_scalar =
631         field.IsOptional() && IsScalar(field.value.type.base_type);
632     const auto nullable_type = opt_scalar ? type + "?" : type;
633     code_.SetValue("FIELDVAR", namer_.Variable(field));
634     code_.SetValue("VALUETYPE", nullable_type);
635     code_.SetValue("OFFSET", namer_.Field(field));
636     code_.SetValue("CONSTANT", field.value.constant);
637     std::string check_if_vector =
638         (IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf("
639                                                                   : "(";
640     const auto body = "add" + check_if_vector + field_field + ": ";
641     code_ += "{{ACCESS_TYPE}} static func " + body + "\\";
642 
643     create_func_body.push_back("{{STRUCTNAME}}." + body + field_field +
644                                ", &fbb)");
645 
646     if (IsScalar(field.value.type.base_type) &&
647         !IsBool(field.value.type.base_type)) {
648       const std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
649       const std::string optional_enum =
650           IsEnum(field.value.type) ? ("?" + is_enum) : "";
651       code_ +=
652           "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}}\\";
653 
654       code_ += field.IsOptional() ? (optional_enum + "\\")
655                                   : (is_enum + ", def: {{CONSTANT}}\\");
656 
657       code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
658 
659       const auto default_value =
660           IsEnum(field.value.type)
661               ? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
662               : field.value.constant;
663       create_func_header.push_back(
664           "" + field_field + ": " + nullable_type + " = " +
665           (field.IsOptional() ? "nil" : default_value));
666       return;
667     }
668 
669     if (IsBool(field.value.type.base_type)) {
670       std::string default_value =
671           "0" == field.value.constant ? "false" : "true";
672 
673       code_.SetValue("CONSTANT", default_value);
674       code_.SetValue("VALUETYPE", field.IsOptional() ? "Bool?" : "Bool");
675       code_ +=
676           "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{FIELDVAR}},\\";
677       code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
678       code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
679       create_func_header.push_back(
680           field_var + ": " + nullable_type + " = " +
681           (field.IsOptional() ? "nil" : default_value));
682       return;
683     }
684 
685     if (IsStruct(field.value.type)) {
686       const auto create_struct =
687           "guard let {{FIELDVAR}} = {{FIELDVAR}} else { return };"
688           " fbb.create(struct: {{FIELDVAR}}, position: "
689           "{{TABLEOFFSET}}.{{OFFSET}}.p) }";
690       code_ += type + "?" + builder_string + create_struct;
691       /// Optional hard coded since structs are always optional
692       create_func_header.push_back(field_var + ": " + type +
693                                    (field.IsOptional() ? "? = nil" : ""));
694       return;
695     }
696 
697     const auto arg_label =
698         namer_.Variable(field) +
699         (IsVector(field.value.type) || IsArray(field.value.type)
700              ? "VectorOffset"
701              : "Offset");
702     create_func_header.push_back(arg_label + " " + field_var + ": " + "Offset" +
703                                  (field.IsRequired() ? "" : " = Offset()"));
704     const auto reader_type =
705         IsStruct(field.value.type) && field.value.type.struct_def->fixed
706             ? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
707             : "offset: {{FIELDVAR}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
708     code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
709 
710     const auto vectortype = field.value.type.VectorType();
711 
712     if ((vectortype.base_type == BASE_TYPE_STRUCT &&
713          field.value.type.struct_def->fixed) &&
714         (IsVector(field.value.type) || IsArray(field.value.type))) {
715       const auto field_name = namer_.NamespacedType(*vectortype.struct_def);
716       code_ += "{{ACCESS_TYPE}} static func " +
717                namer_.Method("start_vector_of", field_var) +
718                "(_ size: Int, in builder: inout "
719                "FlatBufferBuilder) {";
720       Indent();
721       code_ += "builder.startVector(size * MemoryLayout<" + field_name +
722                ">.size, elementSize: MemoryLayout<" + field_name +
723                ">.alignment)";
724       Outdent();
725       code_ += "}";
726     }
727   }
728 
GenTableReader(const StructDef & struct_def)729   void GenTableReader(const StructDef &struct_def) {
730     for (auto it = struct_def.fields.vec.begin();
731          it != struct_def.fields.vec.end(); ++it) {
732       const auto &field = **it;
733       if (field.deprecated) continue;
734       GenTableReaderFields(field);
735     }
736   }
737 
GenTableReaderFields(const FieldDef & field)738   void GenTableReaderFields(const FieldDef &field) {
739     const auto offset = NumToString(field.value.offset);
740     const auto field_field = namer_.Field(field);
741     const auto type = GenType(field.value.type);
742     code_.SetValue("FIELDVAR", namer_.Variable(field));
743     code_.SetValue("FIELDMETHOD", namer_.Method(field));
744     code_.SetValue("VALUETYPE", type);
745     code_.SetValue("OFFSET", namer_.Constant(field.name));
746     code_.SetValue("CONSTANT", field.value.constant);
747     bool opt_scalar =
748         field.IsOptional() && IsScalar(field.value.type.base_type);
749     std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}";
750     std::string optional = opt_scalar ? "?" : "";
751     const auto const_string = "return o == 0 ? " + def_Val + " : ";
752     GenComment(field.doc_comment);
753     if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
754         !IsBool(field.value.type.base_type)) {
755       code_ += GenReaderMainBody(optional) + GenOffset() + const_string +
756                GenReader("VALUETYPE", "o") + " }";
757       if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
758       return;
759     }
760 
761     if (IsBool(field.value.type.base_type)) {
762       std::string default_value =
763           field.IsOptional() ? "nil"
764                              : ("0" == field.value.constant ? "false" : "true");
765       code_.SetValue("CONSTANT", default_value);
766       code_.SetValue("VALUETYPE", "Bool");
767       code_ += GenReaderMainBody(optional) + "\\";
768       code_.SetValue("VALUETYPE", "Byte");
769       code_ += GenOffset() + "return o == 0 ? {{CONSTANT}} : 0 != " +
770                GenReader("VALUETYPE", "o") + " }";
771       if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
772       return;
773     }
774 
775     if (IsEnum(field.value.type)) {
776       const auto default_value =
777           field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
778       code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
779       code_ += GenReaderMainBody(optional) + "\\";
780       code_ += GenOffset() + "return o == 0 ? " + default_value + " : " +
781                GenEnumConstructor("o") + "?? " + default_value + " }";
782       if (parser_.opts.mutable_buffer && !IsUnion(field.value.type))
783         code_ += GenMutate("o", GenOffset(), true);
784       return;
785     }
786 
787     const std::string is_required = field.IsRequired() ? "!" : "?";
788     const auto required_reader = field.IsRequired() ? "return " : const_string;
789 
790     if (IsStruct(field.value.type) && field.value.type.struct_def->fixed) {
791       code_.SetValue("VALUETYPE", GenType(field.value.type));
792       code_.SetValue("CONSTANT", "nil");
793       code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
794                "{{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, at: o) }";
795       code_.SetValue("FIELDVAR", namer_.Variable("mutable", field_field));
796       code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
797       code_.SetValue("CONSTANT", "nil");
798       code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
799                GenConstructor("o + {{ACCESS}}.postion");
800       return;
801     }
802     switch (field.value.type.base_type) {
803       case BASE_TYPE_STRUCT:
804         code_.SetValue("VALUETYPE", GenType(field.value.type));
805         code_.SetValue("CONSTANT", "nil");
806         code_ += GenReaderMainBody(is_required) + GenOffset() +
807                  required_reader +
808                  GenConstructor(GenIndirect("o + {{ACCESS}}.postion"));
809         break;
810 
811       case BASE_TYPE_STRING: {
812         const auto default_string = "\"" + field.value.constant + "\"";
813         code_.SetValue("VALUETYPE", GenType(field.value.type));
814         code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
815         code_ += GenReaderMainBody(is_required) + GenOffset() +
816                  required_reader + "{{ACCESS}}.string(at: o) }";
817         code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}SegmentArray: [UInt8]" +
818                  is_required +
819                  " { return "
820                  "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
821         break;
822       }
823       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();  // fall thru
824       case BASE_TYPE_VECTOR: GenTableReaderVectorFields(field); break;
825       case BASE_TYPE_UNION:
826         code_.SetValue("CONSTANT", "nil");
827         code_ +=
828             "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: "
829             "FlatbuffersInitializable>(type: "
830             "T.Type) -> T" +
831             is_required + " { " + GenOffset() + required_reader +
832             "{{ACCESS}}.union(o) }";
833         break;
834       default: FLATBUFFERS_ASSERT(0);
835     }
836   }
837 
GenTableReaderVectorFields(const FieldDef & field)838   void GenTableReaderVectorFields(const FieldDef &field) {
839     std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
840     const auto vectortype = field.value.type.VectorType();
841     code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
842     code_.SetValue("HAS_FIELDVAR", namer_.Variable("has", field));
843     code_ += "{{ACCESS_TYPE}} var {{HAS_FIELDVAR}}: Bool { " + GenOffset() +
844              "return o == 0 ? false : true }";
845     code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}Count: Int32 { " + GenOffset() +
846              "return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }";
847     code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) ? "0" : "nil");
848     const auto nullable =
849         IsScalar(vectortype.base_type) && !IsEnum(vectortype) ? "" : "?";
850 
851     if (vectortype.base_type != BASE_TYPE_UNION) {
852       code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
853     } else {
854       code_ +=
855           "{{ACCESS_TYPE}} func {{FIELDVAR}}<T: FlatbuffersInitializable>(at "
856           "index: "
857           "Int32, type: T.Type) -> T? { " +
858           GenOffset() + "\\";
859     }
860 
861     if (IsBool(vectortype.base_type)) {
862       code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true");
863       code_.SetValue("VALUETYPE", "Bool");
864     }
865 
866     if (!IsEnum(vectortype)) code_ += const_string + "\\";
867 
868     if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) &&
869         !IsBool(field.value.type.base_type)) {
870       code_ +=
871           "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
872           "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
873       code_ +=
874           "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}] { return "
875           "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) ?? [] }";
876       if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
877       return;
878     }
879 
880     if (vectortype.base_type == BASE_TYPE_STRUCT &&
881         field.value.type.struct_def->fixed) {
882       code_ +=
883           "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
884           "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
885       code_.SetValue("FIELDMETHOD", namer_.Method("mutable", field));
886       code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
887       code_ += GenArrayMainBody(nullable) + GenOffset() + const_string +
888                GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
889 
890       return;
891     }
892 
893     if (IsString(vectortype)) {
894       code_ +=
895           "{{ACCESS}}.directString(at: {{ACCESS}}.vector(at: o) + "
896           "index * {{SIZE}}) }";
897       return;
898     }
899 
900     if (IsEnum(vectortype)) {
901       code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false));
902       code_ += "return o == 0 ? {{VALUETYPE}}" + GenEnumDefaultValue(field) +
903                " : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: "
904                "{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + "
905                "index * {{SIZE}})) }";
906       return;
907     }
908     if (vectortype.base_type == BASE_TYPE_UNION) {
909       code_ +=
910           "{{ACCESS}}.directUnion({{ACCESS}}.vector(at: o) + "
911           "index * {{SIZE}}) }";
912       return;
913     }
914 
915     if (vectortype.base_type == BASE_TYPE_STRUCT &&
916         !field.value.type.struct_def->fixed) {
917       code_ += GenConstructor(
918           "{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
919           "{{SIZE}})");
920       const auto &sd = *field.value.type.struct_def;
921       const auto &fields = sd.fields.vec;
922       for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
923         const auto &key_field = **kit;
924         if (key_field.key) {
925           GenByKeyFunctions(key_field);
926           break;
927         }
928       }
929     }
930   }
931 
GenerateCodingKeys(const StructDef & struct_def)932   void GenerateCodingKeys(const StructDef &struct_def) {
933     code_ += "enum CodingKeys: String, CodingKey {";
934     Indent();
935     for (auto it = struct_def.fields.vec.begin();
936          it != struct_def.fields.vec.end(); ++it) {
937       const auto &field = **it;
938       if (field.deprecated) continue;
939 
940       code_.SetValue("RAWVALUENAME", field.name);
941       code_.SetValue("FIELDVAR", namer_.Variable(field));
942       code_ += "case {{FIELDVAR}} = \"{{RAWVALUENAME}}\"";
943     }
944     Outdent();
945     code_ += "}";
946   }
947 
GenerateEncoderUnionBody(const FieldDef & field)948   void GenerateEncoderUnionBody(const FieldDef &field) {
949     EnumDef &union_def = *field.value.type.enum_def;
950     const auto is_vector = field.value.type.base_type == BASE_TYPE_VECTOR ||
951                            field.value.type.base_type == BASE_TYPE_ARRAY;
952     if (field.value.type.base_type == BASE_TYPE_UTYPE ||
953         (is_vector &&
954          field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
955       return;
956     if (is_vector) {
957       code_ +=
958           "var enumsEncoder = container.nestedUnkeyedContainer(forKey: "
959           ".{{FIELDVAR}}Type)";
960       code_ +=
961           "var contentEncoder = container.nestedUnkeyedContainer(forKey: "
962           ".{{FIELDVAR}})";
963       code_ += "for index in 0..<{{FIELDVAR}}Count {";
964       Indent();
965       code_ += "guard let type = {{FIELDVAR}}Type(at: index) else { continue }";
966       code_ += "try enumsEncoder.encode(type)";
967       code_ += "switch type {";
968       for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
969            ++it) {
970         const auto &ev = **it;
971         const auto type = GenType(ev.union_type);
972         code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
973         code_.SetValue("VALUETYPE", type);
974         if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
975         code_ += "case .{{KEY}}:";
976         Indent();
977         code_ += "let _v = {{FIELDVAR}}(at: index, type: {{VALUETYPE}}.self)";
978         code_ += "try contentEncoder.encode(_v)";
979         Outdent();
980       }
981       code_ += "default: break;";
982       code_ += "}";
983       Outdent();
984       code_ += "}";
985       return;
986     }
987 
988     code_ += "switch {{FIELDVAR}}Type {";
989     for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
990          ++it) {
991       const auto &ev = **it;
992       const auto type = GenType(ev.union_type);
993       code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
994       code_.SetValue("VALUETYPE", type);
995       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
996       code_ += "case .{{KEY}}:";
997       Indent();
998       code_ += "let _v = {{FIELDVAR}}(type: {{VALUETYPE}}.self)";
999       code_ += "try container.encodeIfPresent(_v, forKey: .{{FIELDVAR}})";
1000       Outdent();
1001     }
1002     code_ += "default: break;";
1003     code_ += "}";
1004   }
1005 
GenerateEncoderBody(const StructDef & struct_def)1006   void GenerateEncoderBody(const StructDef &struct_def) {
1007     code_ += "var container = encoder.container(keyedBy: CodingKeys.self)";
1008     for (auto it = struct_def.fields.vec.begin();
1009          it != struct_def.fields.vec.end(); ++it) {
1010       const auto &field = **it;
1011       if (field.deprecated) continue;
1012       const auto type = field.value.type;
1013 
1014       const auto is_non_union_vector =
1015           (field.value.type.base_type == BASE_TYPE_ARRAY ||
1016            field.value.type.base_type == BASE_TYPE_VECTOR) &&
1017           field.value.type.VectorType().base_type != BASE_TYPE_UTYPE;
1018 
1019       code_.SetValue("FIELDVAR", namer_.Variable(field));
1020       code_.SetValue("CONSTANT", field.value.constant);
1021       bool should_indent = true;
1022       if (is_non_union_vector) {
1023         code_ += "if {{FIELDVAR}}Count > 0 {";
1024       } else if (IsEnum(type) && !field.IsOptional()) {
1025         code_.SetValue("CONSTANT", GenEnumDefaultValue(field));
1026         code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
1027       } else if (IsScalar(type.base_type) && !IsEnum(type) &&
1028                  !IsBool(type.base_type) && !field.IsOptional()) {
1029         code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
1030       } else if (IsBool(type.base_type) && !field.IsOptional()) {
1031         std::string default_value =
1032             "0" == field.value.constant ? "false" : "true";
1033         code_.SetValue("CONSTANT", default_value);
1034         code_ += "if {{FIELDVAR}} != {{CONSTANT}} {";
1035       } else {
1036         should_indent = false;
1037       }
1038       if (should_indent) Indent();
1039 
1040       if (IsUnion(type) && !IsEnum(type)) {
1041         GenerateEncoderUnionBody(field);
1042       } else if (is_non_union_vector &&
1043                  (!IsScalar(type.VectorType().base_type) ||
1044                   IsEnum(type.VectorType()))) {
1045         code_ +=
1046             "var contentEncoder = container.nestedUnkeyedContainer(forKey: "
1047             ".{{FIELDVAR}})";
1048         code_ += "for index in 0..<{{FIELDVAR}}Count {";
1049         Indent();
1050         code_ += "guard let type = {{FIELDVAR}}(at: index) else { continue }";
1051         code_ += "try contentEncoder.encode(type)";
1052         Outdent();
1053         code_ += "}";
1054       } else {
1055         code_ +=
1056             "try container.encodeIfPresent({{FIELDVAR}}, forKey: "
1057             ".{{FIELDVAR}})";
1058       }
1059       if (should_indent) Outdent();
1060 
1061       if (is_non_union_vector ||
1062           (IsScalar(type.base_type) && !field.IsOptional())) {
1063         code_ += "}";
1064       }
1065     }
1066   }
1067 
GenerateJSONEncodingAPIs(const StructDef & struct_def)1068   void GenerateJSONEncodingAPIs(const StructDef &struct_def) {
1069     code_ += "extension {{STRUCTNAME}}: Encodable {";
1070     Indent();
1071     code_ += "";
1072     if (struct_def.fields.vec.empty() == false) GenerateCodingKeys(struct_def);
1073 
1074     code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
1075     Indent();
1076     if (struct_def.fields.vec.empty() == false) GenerateEncoderBody(struct_def);
1077     Outdent();
1078     code_ += "}";
1079     Outdent();
1080     code_ += "}";
1081     code_ += "";
1082   }
1083 
GenerateVerifier(const StructDef & struct_def)1084   void GenerateVerifier(const StructDef &struct_def) {
1085     code_ +=
1086         "{{ACCESS_TYPE}} static func verify<T>(_ verifier: inout Verifier, at "
1087         "position: "
1088         "Int, of type: T.Type) throws where T: Verifiable {";
1089     Indent();
1090     code_ += "var _v = try verifier.visitTable(at: position)";
1091     for (auto it = struct_def.fields.vec.begin();
1092          it != struct_def.fields.vec.end(); ++it) {
1093       const auto &field = **it;
1094       if (field.deprecated) continue;
1095       const auto offset = NumToString(field.value.offset);
1096 
1097       code_.SetValue("FIELDVAR", namer_.Variable(field));
1098       code_.SetValue("VALUETYPE", GenerateVerifierType(field));
1099       code_.SetValue("OFFSET", namer_.Field(field));
1100       code_.SetValue("ISREQUIRED", field.IsRequired() ? "true" : "false");
1101 
1102       if (IsUnion(field.value.type)) {
1103         GenerateUnionTypeVerifier(field);
1104         continue;
1105       }
1106 
1107       code_ +=
1108           "try _v.visit(field: {{TABLEOFFSET}}.{{OFFSET}}.p, fieldName: "
1109           "\"{{FIELDVAR}}\", required: {{ISREQUIRED}}, type: "
1110           "{{VALUETYPE}}.self)";
1111     }
1112     code_ += "_v.finish()";
1113     Outdent();
1114     code_ += "}";
1115   }
1116 
GenerateUnionTypeVerifier(const FieldDef & field)1117   void GenerateUnionTypeVerifier(const FieldDef &field) {
1118     const auto is_vector =
1119         IsVector(field.value.type) || IsArray(field.value.type);
1120     if (field.value.type.base_type == BASE_TYPE_UTYPE ||
1121         (is_vector &&
1122          field.value.type.VectorType().base_type == BASE_TYPE_UTYPE))
1123       return;
1124     EnumDef &union_def = *field.value.type.enum_def;
1125     code_.SetValue("VALUETYPE", namer_.NamespacedType(union_def));
1126     code_.SetValue("FUNCTION_NAME", is_vector ? "visitUnionVector" : "visit");
1127     code_ +=
1128         "try _v.{{FUNCTION_NAME}}(unionKey: {{TABLEOFFSET}}.{{OFFSET}}Type.p, "
1129         "unionField: {{TABLEOFFSET}}.{{OFFSET}}.p, unionKeyName: "
1130         "\"{{FIELDVAR}}Type\", fieldName: \"{{FIELDVAR}}\", required: "
1131         "{{ISREQUIRED}}, completion: { (verifier, key: {{VALUETYPE}}, pos) in";
1132     Indent();
1133     code_ += "switch key {";
1134     for (auto it = union_def.Vals().begin(); it != union_def.Vals().end();
1135          ++it) {
1136       const auto &ev = **it;
1137       const auto type = GenType(ev.union_type);
1138       code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
1139       code_.SetValue("VALUETYPE", type);
1140       code_ += "case .{{KEY}}:";
1141       Indent();
1142       if (ev.union_type.base_type == BASE_TYPE_NONE) {
1143         code_ += "break // NOTE - SWIFT doesnt support none";
1144       } else if (ev.union_type.base_type == BASE_TYPE_STRING) {
1145         code_ +=
1146             "try ForwardOffset<String>.verify(&verifier, at: pos, of: "
1147             "String.self)";
1148       } else {
1149         code_.SetValue("MAINTYPE", ev.union_type.struct_def->fixed
1150                                        ? type
1151                                        : "ForwardOffset<" + type + ">");
1152         code_ +=
1153             "try {{MAINTYPE}}.verify(&verifier, at: pos, of: "
1154             "{{VALUETYPE}}.self)";
1155       }
1156       Outdent();
1157     }
1158     code_ += "}";
1159     Outdent();
1160     code_ += "})";
1161   }
1162 
GenerateVerifierType(const FieldDef & field)1163   std::string GenerateVerifierType(const FieldDef &field) {
1164     const auto type = field.value.type;
1165     const auto is_vector = IsVector(type) || IsArray(type);
1166 
1167     if (is_vector) {
1168       const auto vector_type = field.value.type.VectorType();
1169       return "ForwardOffset<Vector<" +
1170              GenerateNestedVerifierTypes(vector_type) + ", " +
1171              GenType(vector_type) + ">>";
1172     }
1173 
1174     return GenerateNestedVerifierTypes(field.value.type);
1175   }
1176 
GenerateNestedVerifierTypes(const Type & type)1177   std::string GenerateNestedVerifierTypes(const Type &type) {
1178     const auto string_type = GenType(type);
1179 
1180     if (IsScalar(type.base_type)) { return string_type; }
1181 
1182     if (IsString(type)) { return "ForwardOffset<" + string_type + ">"; }
1183 
1184     if (type.struct_def && type.struct_def->fixed) { return string_type; }
1185 
1186     return "ForwardOffset<" + string_type + ">";
1187   }
1188 
GenByKeyFunctions(const FieldDef & key_field)1189   void GenByKeyFunctions(const FieldDef &key_field) {
1190     code_.SetValue("TYPE", GenType(key_field.value.type));
1191     code_ +=
1192         "{{ACCESS_TYPE}} func {{FIELDVAR}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
1193         "{ \\";
1194     code_ += GenOffset() +
1195              "return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
1196              "{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }";
1197   }
1198 
GenEnum(const EnumDef & enum_def)1199   void GenEnum(const EnumDef &enum_def) {
1200     if (enum_def.generated) return;
1201     const auto is_private_access = enum_def.attributes.Lookup("private");
1202     code_.SetValue("ENUM_TYPE",
1203                    enum_def.is_union ? "UnionEnum" : "Enum, Verifiable");
1204     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
1205     code_.SetValue("ENUM_NAME", namer_.NamespacedType(enum_def));
1206     code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
1207     GenComment(enum_def.doc_comment);
1208     code_ +=
1209         "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, {{ENUM_TYPE}} {";
1210     Indent();
1211     code_ += "{{ACCESS_TYPE}} typealias T = {{BASE_TYPE}}";
1212     if (enum_def.is_union) {
1213       code_ += "";
1214       code_ += "{{ACCESS_TYPE}} init?(value: T) {";
1215       Indent();
1216       code_ += "self.init(rawValue: value)";
1217       Outdent();
1218       code_ += "}\n";
1219     }
1220     code_ +=
1221         "{{ACCESS_TYPE}} static var byteSize: Int { return "
1222         "MemoryLayout<{{BASE_TYPE}}>.size "
1223         "}";
1224     code_ +=
1225         "{{ACCESS_TYPE}} var value: {{BASE_TYPE}} { return self.rawValue }";
1226     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1227       const auto &ev = **it;
1228       code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
1229       code_.SetValue("VALUE", enum_def.ToString(ev));
1230       GenComment(ev.doc_comment);
1231       code_ += "case {{KEY}} = {{VALUE}}";
1232     }
1233     code_ += "";
1234     AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MaxValue()),
1235                          "max");
1236     AddMinOrMaxEnumValue(namer_.LegacySwiftVariant(*enum_def.MinValue()),
1237                          "min");
1238     Outdent();
1239     code_ += "}\n";
1240     if (parser_.opts.gen_json_coders) EnumEncoder(enum_def);
1241     code_ += "";
1242     if (parser_.opts.generate_object_based_api && enum_def.is_union) {
1243       code_ += "{{ACCESS_TYPE}} struct {{ENUM_NAME}}Union {";
1244       Indent();
1245       code_ += "{{ACCESS_TYPE}} var type: {{ENUM_NAME}}";
1246       code_ += "{{ACCESS_TYPE}} var value: NativeObject?";
1247       code_ +=
1248           "{{ACCESS_TYPE}} init(_ v: NativeObject?, type: {{ENUM_NAME}}) {";
1249       Indent();
1250       code_ += "self.type = type";
1251       code_ += "self.value = v";
1252       Outdent();
1253       code_ += "}";
1254       code_ +=
1255           "{{ACCESS_TYPE}} func pack(builder: inout FlatBufferBuilder) -> "
1256           "Offset {";
1257       Indent();
1258       BuildUnionEnumSwitchCaseWritter(enum_def);
1259       Outdent();
1260       code_ += "}";
1261       Outdent();
1262       code_ += "}";
1263     }
1264   }
1265 
EnumEncoder(const EnumDef & enum_def)1266   void EnumEncoder(const EnumDef &enum_def) {
1267     code_ += "extension {{ENUM_NAME}}: Encodable {";
1268     Indent();
1269     code_ += "{{ACCESS_TYPE}} func encode(to encoder: Encoder) throws {";
1270     Indent();
1271     code_ += "var container = encoder.singleValueContainer()";
1272     code_ += "switch self {";
1273     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
1274       const auto &ev = **it;
1275       code_.SetValue("KEY", namer_.LegacySwiftVariant(ev));
1276       code_.SetValue("RAWKEY", ev.name);
1277       code_ += "case .{{KEY}}: try container.encode(\"{{RAWKEY}}\")";
1278     }
1279     code_ += "}";
1280     Outdent();
1281     code_ += "}";
1282     Outdent();
1283     code_ += "}";
1284   }
1285 
1286   // MARK: - Object API
1287 
GenerateObjectAPIExtensionHeader(std::string type_name)1288   void GenerateObjectAPIExtensionHeader(std::string type_name) {
1289     code_ += "\n";
1290     code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + type_name + " {";
1291     Indent();
1292     code_ += "return " + type_name + "(&self)";
1293     Outdent();
1294     code_ += "}";
1295     code_ +=
1296         "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
1297         "obj: "
1298         "inout " +
1299         type_name + "?) -> Offset {";
1300     Indent();
1301     code_ += "guard var obj = obj else { return Offset() }";
1302     code_ += "return pack(&builder, obj: &obj)";
1303     Outdent();
1304     code_ += "}";
1305     code_ += "";
1306     code_ +=
1307         "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
1308         "obj: "
1309         "inout " +
1310         type_name + ") -> Offset {";
1311     Indent();
1312   }
1313 
GenerateObjectAPIStructConstructor(const StructDef & struct_def)1314   void GenerateObjectAPIStructConstructor(const StructDef &struct_def) {
1315     code_ +=
1316         "{{ACCESS_TYPE}} init(_ _t: inout {{STRUCTNAME}}" + Mutable() + ") {";
1317     Indent();
1318     for (auto it = struct_def.fields.vec.begin();
1319          it != struct_def.fields.vec.end(); ++it) {
1320       const auto &field = **it;
1321       if (field.deprecated) continue;
1322 
1323       const auto type = GenType(field.value.type);
1324       code_.SetValue("FIELDVAR", namer_.Variable(field));
1325       if (IsStruct(field.value.type)) {
1326         code_ += "var _v{{FIELDVAR}} = _t.{{FIELDVAR}}";
1327         code_ += "_{{FIELDVAR}} = _v{{FIELDVAR}}.unpack()";
1328         continue;
1329       }
1330       std::string is_enum = IsEnum(field.value.type) ? ".value" : "";
1331       code_ += "_{{FIELDVAR}} = _t.{{FIELDVAR}}" + is_enum;
1332     }
1333     Outdent();
1334     code_ += "}\n";
1335   }
1336 
GenObjectAPI(const StructDef & struct_def)1337   void GenObjectAPI(const StructDef &struct_def) {
1338     code_ += "{{ACCESS_TYPE}} class " +
1339              namer_.NamespacedObjectType(struct_def) + ": NativeObject {\n";
1340     std::vector<std::string> buffer_constructor;
1341     std::vector<std::string> base_constructor;
1342     Indent();
1343     for (auto it = struct_def.fields.vec.begin();
1344          it != struct_def.fields.vec.end(); ++it) {
1345       const auto &field = **it;
1346       if (field.deprecated) continue;
1347       BuildObjectAPIConstructorBody(field, struct_def.fixed, buffer_constructor,
1348                                     base_constructor);
1349     }
1350     code_ += "";
1351     BuildObjectConstructor(buffer_constructor,
1352                            "_ _t: inout " + namer_.NamespacedType(struct_def));
1353     BuildObjectConstructor(base_constructor);
1354     if (!struct_def.fixed)
1355       code_ +=
1356           "{{ACCESS_TYPE}} func serialize() -> ByteBuffer { return "
1357           "serialize(type: "
1358           "{{STRUCTNAME}}.self) }\n";
1359     Outdent();
1360     code_ += "}";
1361   }
1362 
GenerateObjectAPITableExtension(const StructDef & struct_def)1363   void GenerateObjectAPITableExtension(const StructDef &struct_def) {
1364     GenerateObjectAPIExtensionHeader(namer_.NamespacedObjectType(struct_def));
1365     std::vector<std::string> unpack_body;
1366     std::string builder = ", &builder)";
1367     for (auto it = struct_def.fields.vec.begin();
1368          it != struct_def.fields.vec.end(); ++it) {
1369       const auto &field = **it;
1370       if (field.deprecated) continue;
1371       const auto field_var = namer_.Variable(field);
1372       const auto field_field = namer_.Field(field);
1373       const auto field_method = namer_.Method(field);
1374       const auto type = GenType(field.value.type);
1375       std::string check_if_vector =
1376           (IsVector(field.value.type) || IsArray(field.value.type))
1377               ? "VectorOf("
1378               : "(";
1379       std::string body = "add" + check_if_vector + field_method + ": ";
1380       switch (field.value.type.base_type) {
1381         case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
1382         case BASE_TYPE_VECTOR: {
1383           GenerateVectorObjectAPITableExtension(field);
1384           unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
1385                                 builder);
1386           break;
1387         }
1388         case BASE_TYPE_UNION: {
1389           code_ += "let __" + field_var + " = obj." + field_var +
1390                    "?.pack(builder: &builder) ?? Offset()";
1391           unpack_body.push_back("if let o = obj." + field_var + "?.type {");
1392           unpack_body.push_back("  {{STRUCTNAME}}.add(" + field_var +
1393                                 "Type: o" + builder);
1394           unpack_body.push_back("  {{STRUCTNAME}}." + body + "__" + field_var +
1395                                 builder);
1396           unpack_body.push_back("}\n");
1397           break;
1398         }
1399         case BASE_TYPE_STRUCT: {
1400           if (field.value.type.struct_def &&
1401               field.value.type.struct_def->fixed) {
1402             // This is a Struct (IsStruct), not a table. We create
1403             // a native swift object in this case.
1404             std::string code;
1405             GenerateStructArgs(*field.value.type.struct_def, &code, "", "",
1406                                "$0", true);
1407             code = code.substr(0, code.size() - 2);
1408             unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
1409                                   field_field + builder);
1410           } else {
1411             code_ += "let __" + field_var + " = " + type +
1412                      ".pack(&builder, obj: &obj." + field_field + ")";
1413             unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
1414                                   builder);
1415           }
1416           break;
1417         }
1418         case BASE_TYPE_STRING: {
1419           unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + field_var +
1420                                 builder);
1421           if (field.IsRequired()) {
1422             code_ += "let __" + field_var + " = builder.create(string: obj." +
1423                      field_field + ")";
1424           } else {
1425             BuildingOptionalObjects(field_field, "builder.create(string: s)");
1426           }
1427           break;
1428         }
1429         case BASE_TYPE_UTYPE: break;
1430         default:
1431           unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." +
1432                                 field_field + builder);
1433       }
1434     }
1435     code_ += "let __root = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&builder)";
1436     for (auto it = unpack_body.begin(); it < unpack_body.end(); it++)
1437       code_ += *it;
1438     code_ +=
1439         "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&builder, start: "
1440         "__root)";
1441     Outdent();
1442     code_ += "}";
1443   }
1444 
GenerateVectorObjectAPITableExtension(const FieldDef & field_def)1445   void GenerateVectorObjectAPITableExtension(const FieldDef &field_def) {
1446     const Type &field_type = field_def.value.type;
1447     const auto type = GenType(field_type);
1448     const auto var = namer_.Variable(field_def);
1449     const auto field = namer_.Field(field_def);
1450 
1451     const auto vectortype = field_type.VectorType();
1452     switch (vectortype.base_type) {
1453       case BASE_TYPE_UNION: {
1454         code_ += "var __" + var + "__: [Offset] = []";
1455         code_ += "for i in obj." + var + " {";
1456         Indent();
1457         code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
1458         code_ += "__" + var + "__.append(off)";
1459         Outdent();
1460         code_ += "}";
1461         code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
1462                  var + "__)";
1463         code_ += "let __" + var + "Type = builder.createVector(obj." + field +
1464                  ".compactMap { $0?.type })";
1465         break;
1466       }
1467       case BASE_TYPE_UTYPE: break;
1468       case BASE_TYPE_STRUCT: {
1469         if (field_type.struct_def && !field_type.struct_def->fixed) {
1470           code_ += "var __" + var + "__: [Offset] = []";
1471           code_ += "for var i in obj." + var + " {";
1472           Indent();
1473           code_ +=
1474               "__" + var + "__.append(" + type + ".pack(&builder, obj: &i))";
1475           Outdent();
1476           code_ += "}";
1477           code_ += "let __" + var + " = builder.createVector(ofOffsets: __" +
1478                    var + "__)";
1479         } else {
1480           code_ += "{{STRUCTNAME}}." + namer_.Method("start_vector_of", var) +
1481                    "(obj." + field + ".count, in: &builder)";
1482           std::string code;
1483           GenerateStructArgs(*field_type.struct_def, &code, "", "", "_o", true);
1484           code = code.substr(0, code.size() - 2);
1485           code_ += "for i in obj." + field + " {";
1486           Indent();
1487           code_ += "guard let _o = i else { continue }";
1488           code_ += "builder.create(struct: _o)";
1489           Outdent();
1490           code_ += "}";
1491           code_ += "let __" + var + " = builder.endVector(len: obj." + field +
1492                    ".count)";
1493         }
1494         break;
1495       }
1496       case BASE_TYPE_STRING: {
1497         code_ += "let __" + var + " = builder.createVector(ofStrings: obj." +
1498                  var + ".compactMap({ $0 }) )";
1499         break;
1500       }
1501       default: {
1502         code_ += "let __" + var + " = builder.createVector(obj." + field + ")";
1503         break;
1504       }
1505     }
1506   }
1507 
BuildingOptionalObjects(const std::string & var,const std::string & body_front)1508   void BuildingOptionalObjects(const std::string &var,
1509                                const std::string &body_front) {
1510     code_ += "let __" + var + ": Offset";
1511     code_ += "if let s = obj." + var + " {";
1512     Indent();
1513     code_ += "__" + var + " = " + body_front;
1514     Outdent();
1515     code_ += "} else {";
1516     Indent();
1517     code_ += "__" + var + " = Offset()";
1518     Outdent();
1519     code_ += "}";
1520     code_ += "";
1521   }
1522 
BuildObjectConstructor(const std::vector<std::string> & body,const std::string & header="")1523   void BuildObjectConstructor(const std::vector<std::string> &body,
1524                               const std::string &header = "") {
1525     code_.SetValue("HEADER", header);
1526     code_ += "{{ACCESS_TYPE}} init({{HEADER}}) {";
1527     Indent();
1528     for (auto it = body.begin(); it < body.end(); ++it) code_ += *it;
1529     Outdent();
1530     code_ += "}\n";
1531   }
1532 
BuildObjectAPIConstructorBody(const FieldDef & field,bool is_fixed,std::vector<std::string> & buffer_constructor,std::vector<std::string> & base_constructor)1533   void BuildObjectAPIConstructorBody(
1534       const FieldDef &field, bool is_fixed,
1535       std::vector<std::string> &buffer_constructor,
1536       std::vector<std::string> &base_constructor) {
1537     const auto field_field = namer_.Field(field);
1538     const auto field_var = namer_.Variable(field);
1539     const auto type = GenType(field.value.type);
1540     code_.SetValue("FIELDVAR", field_field);
1541     code_.SetValue("VALUETYPE", type);
1542     std::string is_required = field.IsRequired() ? "" : "?";
1543 
1544     switch (field.value.type.base_type) {
1545       case BASE_TYPE_STRUCT: {
1546         const auto objtype = GenType(field.value.type, true);
1547         code_.SetValue("VALUETYPE", objtype);
1548         const auto optional =
1549             (field.value.type.struct_def && field.value.type.struct_def->fixed);
1550         std::string question_mark =
1551             (field.IsRequired() || (optional && is_fixed) ? "" : "?");
1552 
1553         code_ +=
1554             "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + question_mark;
1555         base_constructor.push_back("" + field_var + " = " + objtype + "()");
1556 
1557         if (field.value.type.struct_def->fixed) {
1558           buffer_constructor.push_back("" + field_var + " = _t." + field_field);
1559         } else {
1560           buffer_constructor.push_back("var __" + field_var + " = _t." +
1561                                        field_field);
1562           buffer_constructor.push_back(
1563               "" + field_var + " = __" + field_var +
1564               (field.IsRequired() ? "!" : question_mark) + ".unpack()");
1565         }
1566         break;
1567       }
1568       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
1569       case BASE_TYPE_VECTOR: {
1570         BuildObjectAPIConstructorBodyVectors(field, buffer_constructor,
1571                                              base_constructor, "    ");
1572         break;
1573       }
1574       case BASE_TYPE_STRING: {
1575         code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: String" + is_required;
1576         buffer_constructor.push_back(field_var + " = _t." + field_field);
1577 
1578         if (field.IsRequired()) {
1579           std::string default_value =
1580               field.IsDefault() ? field.value.constant : "";
1581           base_constructor.push_back(field_var + " = \"" + default_value +
1582                                      "\"");
1583           break;
1584         }
1585         if (field.IsDefault() && !field.IsRequired()) {
1586           std::string value = field.IsDefault() ? field.value.constant : "nil";
1587           base_constructor.push_back(field_var + " = \"" + value + "\"");
1588         }
1589         break;
1590       }
1591       case BASE_TYPE_UTYPE: break;
1592       case BASE_TYPE_UNION: {
1593         BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
1594                                  buffer_constructor);
1595         break;
1596       }
1597       default: {
1598         buffer_constructor.push_back(field_var + " = _t." + field_field);
1599         std::string nullable = field.IsOptional() ? "?" : "";
1600         if (IsScalar(field.value.type.base_type) &&
1601             !IsBool(field.value.type.base_type) && !IsEnum(field.value.type)) {
1602           code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + nullable;
1603           if (!field.IsOptional())
1604             base_constructor.push_back(field_var + " = " +
1605                                        field.value.constant);
1606           break;
1607         }
1608 
1609         if (IsEnum(field.value.type)) {
1610           const auto default_value = IsEnum(field.value.type)
1611                                          ? GenEnumDefaultValue(field)
1612                                          : field.value.constant;
1613           code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}";
1614           base_constructor.push_back(field_var + " = " + default_value);
1615           break;
1616         }
1617 
1618         if (IsBool(field.value.type.base_type)) {
1619           code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: Bool" + nullable;
1620           std::string default_value =
1621               "0" == field.value.constant ? "false" : "true";
1622           if (!field.IsOptional())
1623             base_constructor.push_back(field_var + " = " + default_value);
1624         }
1625       }
1626     }
1627   }
1628 
BuildObjectAPIConstructorBodyVectors(const FieldDef & field,std::vector<std::string> & buffer_constructor,std::vector<std::string> & base_constructor,const std::string & indentation)1629   void BuildObjectAPIConstructorBodyVectors(
1630       const FieldDef &field, std::vector<std::string> &buffer_constructor,
1631       std::vector<std::string> &base_constructor,
1632       const std::string &indentation) {
1633     const auto vectortype = field.value.type.VectorType();
1634     const auto field_var = namer_.Field(field);
1635     const auto field_field = namer_.Field(field);
1636 
1637     if (vectortype.base_type != BASE_TYPE_UTYPE) {
1638       buffer_constructor.push_back(field_var + " = []");
1639       buffer_constructor.push_back("for index in 0..<_t." + field_field +
1640                                    "Count {");
1641       base_constructor.push_back(field_var + " = []");
1642     }
1643 
1644     switch (vectortype.base_type) {
1645       case BASE_TYPE_STRUCT: {
1646         code_.SetValue("VALUETYPE", GenType(vectortype, true));
1647         code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}?]";
1648         if (!vectortype.struct_def->fixed) {
1649           buffer_constructor.push_back(indentation + "var __v_ = _t." +
1650                                        field_field + "(at: index)");
1651           buffer_constructor.push_back(indentation + field_var +
1652                                        ".append(__v_?.unpack())");
1653         } else {
1654           buffer_constructor.push_back(indentation + field_var + ".append(_t." +
1655                                        field_var + "(at: index))");
1656         }
1657         break;
1658       }
1659       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
1660       case BASE_TYPE_VECTOR: {
1661         break;
1662       }
1663       case BASE_TYPE_UNION: {
1664         BuildUnionEnumSwitchCase(*field.value.type.enum_def, field_var,
1665                                  buffer_constructor, indentation, true);
1666         break;
1667       }
1668       case BASE_TYPE_UTYPE: break;
1669       default: {
1670         code_.SetValue(
1671             "VALUETYPE",
1672             (IsString(vectortype) ? "String?" : GenType(vectortype)));
1673         code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: [{{VALUETYPE}}]";
1674 
1675         if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) {
1676           const auto default_value = IsEnum(field.value.type)
1677                                          ? GenEnumDefaultValue(field)
1678                                          : field.value.constant;
1679           buffer_constructor.push_back(indentation + field_var + ".append(_t." +
1680                                        field_field + "(at: index)!)");
1681           break;
1682         }
1683         buffer_constructor.push_back(indentation + field_var + ".append(_t." +
1684                                      field_field + "(at: index))");
1685         break;
1686       }
1687     }
1688     if (vectortype.base_type != BASE_TYPE_UTYPE)
1689       buffer_constructor.push_back("}");
1690   }
1691 
BuildUnionEnumSwitchCaseWritter(const EnumDef & ed)1692   void BuildUnionEnumSwitchCaseWritter(const EnumDef &ed) {
1693     code_ += "switch type {";
1694     for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
1695       const auto ev = **it;
1696       const auto variant = namer_.LegacySwiftVariant(ev);
1697       const auto type = GenType(ev.union_type);
1698       const auto is_struct = IsStruct(ev.union_type) ? type + Mutable() : type;
1699       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
1700       code_ += "case ." + variant + ":";
1701       Indent();
1702       code_ += "var __obj = value as? " + GenType(ev.union_type, true);
1703       code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)";
1704       Outdent();
1705     }
1706     code_ += "default: return Offset()";
1707     code_ += "}";
1708   }
1709 
BuildUnionEnumSwitchCase(const EnumDef & ed,const std::string & field,std::vector<std::string> & buffer_constructor,const std::string & indentation="",const bool is_vector=false)1710   void BuildUnionEnumSwitchCase(const EnumDef &ed, const std::string &field,
1711                                 std::vector<std::string> &buffer_constructor,
1712                                 const std::string &indentation = "",
1713                                 const bool is_vector = false) {
1714     const auto ns_type = namer_.NamespacedType(ed);
1715     code_.SetValue("VALUETYPE", ns_type);
1716     code_ += "{{ACCESS_TYPE}} var {{FIELDVAR}}: \\";
1717     code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
1718 
1719     const auto vector_reader = is_vector ? "(at: index" : "";
1720     buffer_constructor.push_back(indentation + "switch _t." + field + "Type" +
1721                                  vector_reader + (is_vector ? ")" : "") + " {");
1722 
1723     for (auto it = ed.Vals().begin(); it < ed.Vals().end(); ++it) {
1724       const auto ev = **it;
1725       const auto variant = namer_.LegacySwiftVariant(ev);
1726       if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; }
1727       const auto type = IsStruct(ev.union_type)
1728                             ? GenType(ev.union_type) + Mutable()
1729                             : GenType(ev.union_type);
1730       buffer_constructor.push_back(indentation + "case ." + variant + ":");
1731       buffer_constructor.push_back(
1732           indentation + "  var _v = _t." + field + (is_vector ? "" : "(") +
1733           vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)");
1734       const auto constructor =
1735           ns_type + "Union(_v?.unpack(), type: ." + variant + ")";
1736       buffer_constructor.push_back(
1737           indentation + "  " + field +
1738           (is_vector ? ".append(" + constructor + ")" : " = " + constructor));
1739     }
1740     buffer_constructor.push_back(indentation + "default: break");
1741     buffer_constructor.push_back(indentation + "}");
1742   }
1743 
AddMinOrMaxEnumValue(const std::string & str,const std::string & type)1744   void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
1745     const auto current_value = str;
1746     code_.SetValue(type, current_value);
1747     code_ += "{{ACCESS_TYPE}} static var " + type +
1748              ": {{ENUM_NAME}} { return .{{" + type + "}} }";
1749   }
1750 
GenLookup(const FieldDef & key_field,const std::string & struct_type)1751   void GenLookup(const FieldDef &key_field, const std::string &struct_type) {
1752     code_.SetValue("STRUCTTYPE", struct_type);
1753     code_.SetValue("OFFSET", NumToString(key_field.value.offset));
1754     std::string offset_reader =
1755         "Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
1756         "fbb: fbb)";
1757 
1758     code_.SetValue("TYPE", GenType(key_field.value.type));
1759     code_ +=
1760         "fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
1761         "fbb: "
1762         "ByteBuffer) -> {{STRUCTTYPE}}? {";
1763     Indent();
1764     if (IsString(key_field.value.type))
1765       code_ += "let key = key.utf8.map { $0 }";
1766     code_ += "var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
1767     code_ += "var start: Int32 = 0";
1768     code_ += "while span != 0 {";
1769     Indent();
1770     code_ += "var middle = span / 2";
1771     code_ +=
1772         "let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)";
1773     if (IsString(key_field.value.type)) {
1774       code_ += "let comp = Table.compare(" + offset_reader + ", key, fbb: fbb)";
1775     } else {
1776       code_ += "let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
1777                offset_reader + "))";
1778     }
1779 
1780     code_ += "if comp > 0 {";
1781     Indent();
1782     code_ += "span = middle";
1783     Outdent();
1784     code_ += "} else if comp < 0 {";
1785     Indent();
1786     code_ += "middle += 1";
1787     code_ += "start += middle";
1788     code_ += "span -= middle";
1789     Outdent();
1790     code_ += "} else {";
1791     Indent();
1792     code_ += "return {{STRUCTTYPE}}(fbb, o: tableOffset)";
1793     Outdent();
1794     code_ += "}";
1795     Outdent();
1796     code_ += "}";
1797     code_ += "return nil";
1798     Outdent();
1799     code_ += "}";
1800   }
1801 
GenPadding(const FieldDef & field,int * id)1802   inline void GenPadding(const FieldDef &field, int *id) {
1803     if (field.padding) {
1804       for (int i = 0; i < 4; i++) {
1805         if (static_cast<int>(field.padding) & (1 << i)) {
1806           const auto bits = (1 << i) * 8;
1807           code_ += "private let padding" + NumToString((*id)++) + "__: UInt" +
1808                    NumToString(bits) + " = 0";
1809         }
1810       }
1811       FLATBUFFERS_ASSERT(!(field.padding & ~0xF));
1812     }
1813   }
1814 
GenComment(const std::vector<std::string> & dc)1815   void GenComment(const std::vector<std::string> &dc) {
1816     if (dc.begin() == dc.end()) {
1817       // Don't output empty comment blocks with 0 lines of comment content.
1818       return;
1819     }
1820     for (auto it = dc.begin(); it != dc.end(); ++it) { code_ += "/// " + *it; }
1821   }
1822 
GenOffset()1823   std::string GenOffset() {
1824     return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
1825   }
1826 
GenReaderMainBody(const std::string & optional="")1827   std::string GenReaderMainBody(const std::string &optional = "") {
1828     return "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + optional + " { ";
1829   }
1830 
GenReader(const std::string & type,const std::string & at="{{OFFSET}}")1831   std::string GenReader(const std::string &type,
1832                         const std::string &at = "{{OFFSET}}") {
1833     return "{{ACCESS}}.readBuffer(of: {{" + type + "}}.self, at: " + at + ")";
1834   }
1835 
GenConstructor(const std::string & offset)1836   std::string GenConstructor(const std::string &offset) {
1837     return "{{VALUETYPE}}({{ACCESS}}.bb, o: " + offset + ") }";
1838   }
1839 
GenMutate(const std::string & offset,const std::string & get_offset,bool isRaw=false)1840   std::string GenMutate(const std::string &offset,
1841                         const std::string &get_offset, bool isRaw = false) {
1842     return "@discardableResult {{ACCESS_TYPE}} func mutate({{FIELDVAR}}: "
1843            "{{VALUETYPE}}) -> Bool {" +
1844            get_offset + " return {{ACCESS}}.mutate({{FIELDVAR}}" +
1845            (isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
1846   }
1847 
GenMutateArray()1848   std::string GenMutateArray() {
1849     return "{{ACCESS_TYPE}} func mutate({{FIELDVAR}}: {{VALUETYPE}}, at "
1850            "index: Int32) -> Bool { " +
1851            GenOffset() +
1852            "return {{ACCESS}}.directMutate({{FIELDVAR}}, index: "
1853            "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
1854   }
1855 
GenEnumDefaultValue(const FieldDef & field)1856   std::string GenEnumDefaultValue(const FieldDef &field) {
1857     const auto &value = field.value;
1858     FLATBUFFERS_ASSERT(value.type.enum_def);
1859     const auto &enum_def = *value.type.enum_def;
1860     // Vector of enum defaults are always "[]" which never works.
1861     const std::string constant = IsVector(value.type) ? "0" : value.constant;
1862     const auto enum_val = enum_def.FindByValue(constant);
1863     if (enum_val) {
1864       return "." + namer_.LegacySwiftVariant(*enum_val);
1865     } else {
1866       const auto &ev = **enum_def.Vals().begin();
1867       return "." + namer_.LegacySwiftVariant(ev);
1868     }
1869   }
1870 
GenEnumConstructor(const std::string & at)1871   std::string GenEnumConstructor(const std::string &at) {
1872     return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
1873   }
1874 
ValidateFunc()1875   std::string ValidateFunc() {
1876     return "static func validateVersion() { FlatBuffersVersion_2_0_0() }";
1877   }
1878 
GenType(const Type & type,const bool should_consider_suffix=false) const1879   std::string GenType(const Type &type,
1880                       const bool should_consider_suffix = false) const {
1881     return IsScalar(type.base_type) ? GenTypeBasic(type)
1882            : IsArray(type)          ? GenType(type.VectorType())
1883                            : GenTypePointer(type, should_consider_suffix);
1884   }
1885 
GenTypePointer(const Type & type,const bool should_consider_suffix) const1886   std::string GenTypePointer(const Type &type,
1887                              const bool should_consider_suffix) const {
1888     switch (type.base_type) {
1889       case BASE_TYPE_STRING: return "String";
1890       case BASE_TYPE_VECTOR: return GenType(type.VectorType());
1891       case BASE_TYPE_STRUCT: {
1892         const auto &sd = *type.struct_def;
1893         if (should_consider_suffix && !sd.fixed) {
1894           return namer_.NamespacedObjectType(sd);
1895         }
1896         return namer_.NamespacedType(sd);
1897       }
1898       case BASE_TYPE_UNION:
1899       default: return "FlatbuffersInitializable";
1900     }
1901   }
1902 
GenTypeBasic(const Type & type) const1903   std::string GenTypeBasic(const Type &type) const {
1904     return GenTypeBasic(type, true);
1905   }
1906 
Indent()1907   void Indent() { code_.IncrementIdentLevel(); }
1908 
Outdent()1909   void Outdent() { code_.DecrementIdentLevel(); }
1910 
GenTypeBasic(const Type & type,bool can_override) const1911   std::string GenTypeBasic(const Type &type, bool can_override) const {
1912     // clang-format off
1913     static const char * const swift_type[] = {
1914       #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1915               CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE) \
1916         #STYPE,
1917         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1918       #undef FLATBUFFERS_TD
1919     };
1920     // clang-format on
1921     if (can_override) {
1922       if (type.enum_def) return namer_.NamespacedType(*type.enum_def);
1923       if (type.base_type == BASE_TYPE_BOOL) return "Bool";
1924     }
1925     return swift_type[static_cast<int>(type.base_type)];
1926   }
1927 
Mutable() const1928   std::string Mutable() const { return "_Mutable"; }
1929 
1930   IdlNamer namer_;
1931 };
1932 }  // namespace swift
GenerateSwift(const Parser & parser,const std::string & path,const std::string & file_name)1933 bool GenerateSwift(const Parser &parser, const std::string &path,
1934                    const std::string &file_name) {
1935   swift::SwiftGenerator generator(parser, path, file_name);
1936   return generator.generate();
1937 }
1938 }  // namespace flatbuffers
1939