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