• 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 <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 
25 namespace flatbuffers {
26 
27 namespace swift {
28 
GenIndirect(const std::string & reading)29 inline std::string GenIndirect(const std::string &reading) {
30   return "{{ACCESS}}.indirect(" + reading + ")";
31 }
32 
GenArrayMainBody(const std::string & optional)33 inline std::string GenArrayMainBody(const std::string &optional) {
34   return "{{ACCESS_TYPE}} func {{VALUENAME}}(at index: Int32) -> "
35          "{{VALUETYPE}}" +
36          optional + " { ";
37 }
38 
39 class SwiftGenerator : public BaseGenerator {
40  private:
41   CodeWriter code_;
42   std::unordered_set<std::string> keywords_;
43   int namespace_depth;
44 
45  public:
SwiftGenerator(const Parser & parser,const std::string & path,const std::string & file_name)46   SwiftGenerator(const Parser &parser, const std::string &path,
47                  const std::string &file_name)
48       : BaseGenerator(parser, path, file_name, "", "_", "swift") {
49     namespace_depth = 0;
50     code_.SetPadding("  ");
51     static const char *const keywords[] = {
52       "associatedtype",
53       "class",
54       "deinit",
55       "enum",
56       "extension",
57       "fileprivate",
58       "func",
59       "import",
60       "init",
61       "inout",
62       "internal",
63       "let",
64       "open",
65       "operator",
66       "private",
67       "protocol",
68       "public",
69       "rethrows",
70       "static",
71       "struct",
72       "subscript",
73       "typealias",
74       "var",
75       "break",
76       "case",
77       "continue",
78       "default",
79       "defer",
80       "do",
81       "else",
82       "fallthrough",
83       "for",
84       "guard",
85       "if",
86       "in",
87       "repeat",
88       "return",
89       "switch",
90       "where",
91       "while",
92       "Any",
93       "catch",
94       "false",
95       "is",
96       "nil",
97       "super",
98       "self",
99       "Self",
100       "throw",
101       "throws",
102       "true",
103       "try",
104       "associativity",
105       "convenience",
106       "dynamic",
107       "didSet",
108       "final",
109       "get",
110       "infix",
111       "indirect",
112       "lazy",
113       "left",
114       "mutating",
115       "none",
116       "nonmutating",
117       "optional",
118       "override",
119       "postfix",
120       "precedence",
121       "prefix",
122       "Protocol",
123       "required",
124       "right",
125       "set",
126       "Type",
127       "unowned",
128       "weak",
129       "willSet",
130       "Void",
131       nullptr,
132     };
133     for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
134   }
135 
generate()136   bool generate() {
137     code_.Clear();
138     code_.SetValue("ACCESS", "_accessor");
139     code_.SetValue("TABLEOFFSET", "VTOFFSET");
140     code_ += "// " + std::string(FlatBuffersGeneratedWarning());
141     code_ += "// swiftlint:disable all";
142     code_ += "// swiftformat:disable all\n";
143     code_ += "import FlatBuffers\n";
144     // Generate code for all the enum declarations.
145 
146     for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
147          ++it) {
148       const auto &enum_def = **it;
149       if (!enum_def.generated) { GenEnum(enum_def); }
150     }
151 
152     for (auto it = parser_.structs_.vec.begin();
153          it != parser_.structs_.vec.end(); ++it) {
154       const auto &struct_def = **it;
155       if (struct_def.fixed && !struct_def.generated) {
156         GenStructReader(struct_def);
157         GenMutableStructReader(struct_def);
158       }
159     }
160 
161     for (auto it = parser_.structs_.vec.begin();
162          it != parser_.structs_.vec.end(); ++it) {
163       const auto &struct_def = **it;
164       if (!struct_def.fixed && !struct_def.generated) {
165         GenTable(struct_def);
166         if (parser_.opts.generate_object_based_api) {
167           GenObjectAPI(struct_def);
168         }
169       }
170     }
171 
172     const auto filename = GeneratedFileName(path_, file_name_, parser_.opts);
173     const auto final_code = code_.ToString();
174     return SaveFile(filename.c_str(), final_code, false);
175   }
176 
mark(const std::string & str)177   void mark(const std::string &str) {
178     code_.SetValue("MARKVALUE", str);
179     code_ += "\n// MARK: - {{MARKVALUE}}\n";
180   }
181 
182   // MARK: - Generating structs
183 
184   // Generates the reader for swift
GenStructReader(const StructDef & struct_def)185   void GenStructReader(const StructDef &struct_def) {
186     auto is_private_access = struct_def.attributes.Lookup("private");
187     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
188     GenComment(struct_def.doc_comment);
189     code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
190     code_ += "{{ACCESS_TYPE}} struct {{STRUCTNAME}}: NativeStruct\\";
191     if (parser_.opts.generate_object_based_api) code_ += ", NativeObject\\";
192     code_ += " {";
193     code_ += "";
194     Indent();
195     code_ += ValidateFunc();
196     code_ += "";
197     int padding_id = 0;
198     std::string constructor = "";
199     std::vector<std::string> base_constructor;
200     std::vector<std::string> main_constructor;
201 
202     for (auto it = struct_def.fields.vec.begin();
203          it != struct_def.fields.vec.end(); ++it) {
204       auto &field = **it;
205       if (field.deprecated) continue;
206 
207       if (!constructor.empty()) constructor += ", ";
208 
209       auto name = Name(field);
210       auto type = GenType(field.value.type);
211       code_.SetValue("VALUENAME", name);
212       if (IsEnum(field.value.type)) {
213         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
214       }
215       code_.SetValue("VALUETYPE", type);
216       GenComment(field.doc_comment);
217       std::string valueType =
218           IsEnum(field.value.type) ? "{{BASEVALUE}}" : "{{VALUETYPE}}";
219       code_ += "private var _{{VALUENAME}}: " + valueType;
220       auto accessing_value = IsEnum(field.value.type) ? ".value" : "";
221       auto base_value =
222           IsStruct(field.value.type) ? (type + "()") : field.value.constant;
223 
224       main_constructor.push_back("_" + name + " = " + name + accessing_value);
225       base_constructor.push_back("_" + name + " = " + base_value);
226 
227       if (field.padding) { GenPadding(field, &padding_id); }
228       constructor += name + ": " + type;
229     }
230     code_ += "";
231     BuildObjectConstructor(main_constructor, constructor);
232     BuildObjectConstructor(base_constructor, "");
233 
234     if (parser_.opts.generate_object_based_api)
235       GenerateObjectAPIStructConstructor(struct_def);
236 
237     for (auto it = struct_def.fields.vec.begin();
238          it != struct_def.fields.vec.end(); ++it) {
239       auto &field = **it;
240       if (field.deprecated) continue;
241       auto name = Name(field);
242       auto type = GenType(field.value.type);
243       code_.SetValue("VALUENAME", name);
244       code_.SetValue("VALUETYPE", type);
245       GenComment(field.doc_comment);
246       if (!IsEnum(field.value.type)) {
247         code_ += GenReaderMainBody() + "_{{VALUENAME}} }";
248       } else if (IsEnum(field.value.type)) {
249         code_ +=
250             GenReaderMainBody() + "{{VALUETYPE}}(rawValue: _{{VALUENAME}})! }";
251       }
252     }
253     Outdent();
254     code_ += "}\n";
255   }
256 
GenMutableStructReader(const StructDef & struct_def)257   void GenMutableStructReader(const StructDef &struct_def) {
258     GenObjectHeader(struct_def);
259 
260     for (auto it = struct_def.fields.vec.begin();
261          it != struct_def.fields.vec.end(); ++it) {
262       auto &field = **it;
263       if (field.deprecated) continue;
264       auto offset = NumToString(field.value.offset);
265       auto name = Name(field);
266       auto type = GenType(field.value.type);
267       code_.SetValue("VALUENAME", name);
268       if (IsEnum(field.value.type)) {
269         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
270       }
271       code_.SetValue("VALUETYPE", type);
272       code_.SetValue("OFFSET", offset);
273       if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
274         code_ +=
275             GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
276       } else if (IsEnum(field.value.type)) {
277         code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
278         code_ += GenReaderMainBody() + "return " +
279                  GenEnumConstructor("{{OFFSET}}") + "?? " +
280                  GenEnumDefaultValue(field) + " }";
281       } else if (IsStruct(field.value.type)) {
282         code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
283         code_ += GenReaderMainBody() + "return " +
284                  GenConstructor("{{ACCESS}}.postion + {{OFFSET}}");
285       }
286       if (parser_.opts.mutable_buffer && !IsStruct(field.value.type))
287         code_ += GenMutate("{{OFFSET}}", "", IsEnum(field.value.type));
288     }
289 
290     if (parser_.opts.generate_object_based_api) {
291       GenerateObjectAPIExtensionHeader(NameWrappedInNameSpace(struct_def));
292       code_ += "return builder.create(struct: obj)";
293       Outdent();
294       code_ += "}";
295     }
296     Outdent();
297     code_ += "}\n";
298   }
299 
300   // Generates the create function for swift
GenStructWriter(const StructDef & struct_def)301   void GenStructWriter(const StructDef &struct_def) {
302     auto is_private_access = struct_def.attributes.Lookup("private");
303     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
304     code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
305     code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
306     code_ += "extension {{STRUCTNAME}} {";
307     Indent();
308     code_ += "@discardableResult";
309     code_ +=
310         "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(builder: inout "
311         "FlatBufferBuilder, \\";
312     std::string func_header = "";
313     GenerateStructArgs(struct_def, &func_header, "", "");
314     code_ += func_header.substr(0, func_header.size() - 2) + "\\";
315     code_ += ") -> Offset {";
316     Indent();
317     code_ +=
318         "builder.createStructOf(size: {{STRUCTNAME}}.size, alignment: "
319         "{{STRUCTNAME}}.alignment)";
320     code_ += "return builder.endStruct()";
321     Outdent();
322     code_ += "}\n";
323     Outdent();
324     code_ += "}\n";
325   }
326 
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)327   void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr,
328                           const std::string &nameprefix,
329                           const std::string &object_name,
330                           const std::string &obj_api_named = "",
331                           bool is_obj_api = false) {
332     auto &code = *code_ptr;
333     for (auto it = struct_def.fields.vec.begin();
334          it != struct_def.fields.vec.end(); ++it) {
335       auto &field = **it;
336       if (field.deprecated) continue;
337       const auto &field_type = field.value.type;
338       if (IsStruct(field.value.type)) {
339         GenerateStructArgs(
340             *field_type.struct_def, code_ptr, (nameprefix + field.name),
341             (object_name + "." + field.name), obj_api_named, is_obj_api);
342       } else {
343         auto name = Name(field);
344         auto type = GenType(field.value.type);
345         if (!is_obj_api) {
346           code += nameprefix + name + ": " + type;
347           if (!IsEnum(field.value.type)) {
348             code += " = ";
349             auto is_bool = IsBool(field.value.type.base_type);
350             auto constant =
351                 is_bool ? ("0" == field.value.constant ? "false" : "true")
352                         : field.value.constant;
353             code += constant;
354           }
355           code += ", ";
356           continue;
357         }
358         code +=
359             nameprefix + name + ": " + obj_api_named + object_name + "." + name;
360         code += ", ";
361       }
362     }
363   }
364 
365   // MARK: - Table Generator
366 
367   // Generates the reader for swift
GenTable(const StructDef & struct_def)368   void GenTable(const StructDef &struct_def) {
369     auto is_private_access = struct_def.attributes.Lookup("private");
370     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
371 
372     GenObjectHeader(struct_def);
373     GenTableAccessors(struct_def);
374     GenTableReader(struct_def);
375     GenTableWriter(struct_def);
376     if (parser_.opts.generate_object_based_api)
377       GenerateObjectAPITableExtension(struct_def);
378     Outdent();
379     code_ += "}\n";
380   }
381 
382   // Generates the reader for swift
GenTableAccessors(const StructDef & struct_def)383   void GenTableAccessors(const StructDef &struct_def) {
384     // Generate field id constants.
385     if (struct_def.fields.vec.size() > 0) {
386       code_ += "private enum {{TABLEOFFSET}}: VOffset {";
387       Indent();
388       for (auto it = struct_def.fields.vec.begin();
389            it != struct_def.fields.vec.end(); ++it) {
390         const auto &field = **it;
391         if (field.deprecated) { continue; }
392         code_.SetValue("OFFSET_NAME", Name(field));
393         code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset));
394         code_ += "case {{OFFSET_NAME}} = {{OFFSET_VALUE}}";
395       }
396       code_ += "var v: Int32 { Int32(self.rawValue) }";
397       code_ += "var p: VOffset { self.rawValue }";
398       Outdent();
399       code_ += "}";
400       code_ += "";
401     }
402   }
403 
GenObjectHeader(const StructDef & struct_def)404   void GenObjectHeader(const StructDef &struct_def) {
405     GenComment(struct_def.doc_comment);
406 
407     code_.SetValue("SHORT_STRUCTNAME", Name(struct_def));
408     code_.SetValue("STRUCTNAME", NameWrappedInNameSpace(struct_def));
409     code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
410     code_.SetValue("MUTABLE", struct_def.fixed ? Mutable() : "");
411     code_ +=
412         "{{ACCESS_TYPE}} struct {{STRUCTNAME}}{{MUTABLE}}: FlatBufferObject\\";
413     if (!struct_def.fixed && parser_.opts.generate_object_based_api)
414       code_ += ", ObjectAPIPacker\\";
415     code_ += " {\n";
416     Indent();
417     code_ += ValidateFunc();
418     code_ +=
419         "{{ACCESS_TYPE}} var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
420     code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n";
421     if (!struct_def.fixed) {
422       if (parser_.file_identifier_.length()) {
423         code_.SetValue("FILENAME", parser_.file_identifier_);
424         code_ +=
425             "{{ACCESS_TYPE}} static func finish(_ fbb: inout "
426             "FlatBufferBuilder, end: "
427             "Offset, prefix: Bool = false) { fbb.finish(offset: end, "
428             "fileId: "
429             "\"{{FILENAME}}\", addPrefix: prefix) }";
430       }
431       code_ +=
432           "{{ACCESS_TYPE}} static func getRootAs{{SHORT_STRUCTNAME}}(bb: "
433           "ByteBuffer) -> "
434           "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: "
435           "Int32(bb.read(def: UOffset.self, position: bb.reader)) + "
436           "Int32(bb.reader))) }\n";
437       code_ += "private init(_ t: Table) { {{ACCESS}} = t }";
438     }
439     code_ +=
440         "{{ACCESS_TYPE}} init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
441         "{{OBJECTTYPE}}(bb: "
442         "bb, position: o) }";
443     code_ += "";
444   }
445 
GenTableWriter(const StructDef & struct_def)446   void GenTableWriter(const StructDef &struct_def) {
447     flatbuffers::FieldDef *key_field = nullptr;
448     std::vector<std::string> require_fields;
449     std::vector<std::string> create_func_body;
450     std::vector<std::string> create_func_header;
451     auto should_generate_create = struct_def.fields.vec.size() != 0;
452 
453     code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
454     code_ +=
455         "{{ACCESS_TYPE}} static func start{{SHORT_STRUCTNAME}}(_ fbb: inout "
456         "FlatBufferBuilder) -> "
457         "UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
458 
459     for (auto it = struct_def.fields.vec.begin();
460          it != struct_def.fields.vec.end(); ++it) {
461       auto &field = **it;
462       if (field.deprecated) continue;
463       if (field.key) key_field = &field;
464       if (field.IsRequired())
465         require_fields.push_back(NumToString(field.value.offset));
466 
467       GenTableWriterFields(field, &create_func_body, &create_func_header);
468     }
469     code_ +=
470         "{{ACCESS_TYPE}} static func end{{SHORT_STRUCTNAME}}(_ fbb: inout "
471         "FlatBufferBuilder, "
472         "start: "
473         "UOffset) -> Offset { let end = Offset(offset: "
474         "fbb.endTable(at: start))\\";
475     if (require_fields.capacity() != 0) {
476       std::string fields = "";
477       for (auto it = require_fields.begin(); it != require_fields.end(); ++it)
478         fields += *it + ", ";
479       code_.SetValue("FIELDS", fields.substr(0, fields.size() - 2));
480       code_ += "; fbb.require(table: end, fields: [{{FIELDS}}])\\";
481     }
482     code_ += "; return end }";
483 
484     if (should_generate_create) {
485       code_ += "{{ACCESS_TYPE}} static func create{{SHORT_STRUCTNAME}}(";
486       Indent();
487       code_ += "_ fbb: inout FlatBufferBuilder,";
488       for (auto it = create_func_header.begin(); it < create_func_header.end();
489            ++it) {
490         code_ += *it + "\\";
491         if (it < create_func_header.end() - 1) code_ += ",";
492       }
493       code_ += "";
494       Outdent();
495       code_ += ") -> Offset {";
496       Indent();
497       code_ += "let __start = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&fbb)";
498       for (auto it = create_func_body.begin(); it < create_func_body.end();
499            ++it) {
500         code_ += *it;
501       }
502       code_ +=
503           "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&fbb, start: __start)";
504       Outdent();
505       code_ += "}";
506     }
507 
508     std::string spacing = "";
509 
510     if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
511       code_.SetValue("VALUENAME", NameWrappedInNameSpace(struct_def));
512       code_.SetValue("SHORT_VALUENAME", Name(struct_def));
513       code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
514 
515       code_ +=
516           "{{ACCESS_TYPE}} static func "
517           "sortVectorOf{{SHORT_VALUENAME}}(offsets:[Offset], "
518           "_ fbb: inout FlatBufferBuilder) -> Offset {";
519       Indent();
520       code_ += spacing + "var off = offsets";
521       code_ +=
522           spacing +
523           "off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: "
524           "{{VOFFSET}}, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: "
525           "{{VOFFSET}}, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } ";
526       code_ += spacing + "return fbb.createVector(ofOffsets: off)";
527       Outdent();
528       code_ += "}";
529       GenLookup(*key_field);
530     }
531   }
532 
GenTableWriterFields(const FieldDef & field,std::vector<std::string> * create_body,std::vector<std::string> * create_header)533   void GenTableWriterFields(const FieldDef &field,
534                             std::vector<std::string> *create_body,
535                             std::vector<std::string> *create_header) {
536     std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { ";
537     auto &create_func_body = *create_body;
538     auto &create_func_header = *create_header;
539     auto name = Name(field);
540     auto type = GenType(field.value.type);
541     auto opt_scalar =
542         field.IsOptional() && IsScalar(field.value.type.base_type);
543     auto nullable_type = opt_scalar ? type + "?" : type;
544     code_.SetValue("VALUENAME", name);
545     code_.SetValue("VALUETYPE", nullable_type);
546     code_.SetValue("OFFSET", name);
547     code_.SetValue("CONSTANT", field.value.constant);
548     std::string check_if_vector =
549         (IsVector(field.value.type) || IsArray(field.value.type)) ? "VectorOf("
550                                                                   : "(";
551     auto body = "add" + check_if_vector + name + ": ";
552     code_ += "{{ACCESS_TYPE}} static func " + body + "\\";
553 
554     create_func_body.push_back("{{STRUCTNAME}}." + body + name + ", &fbb)");
555 
556     if (IsScalar(field.value.type.base_type) &&
557         !IsBool(field.value.type.base_type)) {
558       std::string is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
559       std::string optional_enum =
560           IsEnum(field.value.type) ? ("?" + is_enum) : "";
561       code_ +=
562           "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\";
563 
564       code_ += field.IsOptional() ? (optional_enum + "\\")
565                                   : (is_enum + ", def: {{CONSTANT}}\\");
566 
567       code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
568 
569       auto default_value =
570           IsEnum(field.value.type)
571               ? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field))
572               : field.value.constant;
573       create_func_header.push_back(
574           "" + name + ": " + nullable_type + " = " +
575           (field.IsOptional() ? "nil" : default_value));
576       return;
577     }
578 
579     if (IsBool(field.value.type.base_type)) {
580       std::string default_value =
581           "0" == field.value.constant ? "false" : "true";
582 
583       code_.SetValue("CONSTANT", default_value);
584       code_.SetValue("VALUETYPE", field.IsOptional() ? "Bool?" : "Bool");
585       code_ += "{{VALUETYPE}}" + builder_string +
586                "fbb.add(element: {{VALUENAME}},\\";
587       code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},";
588       code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
589       create_func_header.push_back(
590           name + ": " + nullable_type + " = " +
591           (field.IsOptional() ? "nil" : default_value));
592       return;
593     }
594 
595     if (IsStruct(field.value.type)) {
596       auto create_struct =
597           "guard let {{VALUENAME}} = {{VALUENAME}} else { return };"
598           " fbb.create(struct: {{VALUENAME}}, position: "
599           "{{TABLEOFFSET}}.{{OFFSET}}.p) }";
600       code_ += type + "?" + builder_string + create_struct;
601       /// Optional hard coded since structs are always optional
602       create_func_header.push_back(name + ": " + type + "? = nil");
603       return;
604     }
605 
606     auto camel_case_name =
607         MakeCamel(name, false) +
608         (IsVector(field.value.type) || IsArray(field.value.type)
609              ? "VectorOffset"
610              : "Offset");
611     create_func_header.push_back(camel_case_name + " " + name + ": " +
612                                  "Offset = Offset()");
613     auto reader_type =
614         IsStruct(field.value.type) && field.value.type.struct_def->fixed
615             ? "structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"
616             : "offset: {{VALUENAME}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }";
617     code_ += "Offset" + builder_string + "fbb.add(" + reader_type;
618 
619     auto vectortype = field.value.type.VectorType();
620 
621     if ((vectortype.base_type == BASE_TYPE_STRUCT &&
622          field.value.type.struct_def->fixed) &&
623         (IsVector(field.value.type) || IsArray(field.value.type))) {
624       auto field_name = NameWrappedInNameSpace(*vectortype.struct_def);
625       code_ += "public static func startVectorOf" + MakeCamel(name, true) +
626                "(_ size: Int, in builder: inout "
627                "FlatBufferBuilder) {";
628       Indent();
629       code_ += "builder.startVector(size * MemoryLayout<" + field_name +
630                ">.size, elementSize: MemoryLayout<" + field_name +
631                ">.alignment)";
632       Outdent();
633       code_ += "}";
634     }
635   }
636 
GenTableReader(const StructDef & struct_def)637   void GenTableReader(const StructDef &struct_def) {
638     for (auto it = struct_def.fields.vec.begin();
639          it != struct_def.fields.vec.end(); ++it) {
640       auto &field = **it;
641       if (field.deprecated) continue;
642       GenTableReaderFields(field);
643     }
644   }
645 
GenTableReaderFields(const FieldDef & field)646   void GenTableReaderFields(const FieldDef &field) {
647     auto offset = NumToString(field.value.offset);
648     auto name = Name(field);
649     auto type = GenType(field.value.type);
650     code_.SetValue("VALUENAME", name);
651     code_.SetValue("VALUETYPE", type);
652     code_.SetValue("OFFSET", name);
653     code_.SetValue("CONSTANT", field.value.constant);
654     std::string def_Val = field.IsDefault() ? "{{CONSTANT}}" : "nil";
655     std::string optional = field.IsOptional() ? "?" : "";
656     auto const_string = "return o == 0 ? " + def_Val + " : ";
657     GenComment(field.doc_comment);
658     if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
659         !IsBool(field.value.type.base_type)) {
660       code_ += GenReaderMainBody(optional) + GenOffset() + const_string +
661                GenReader("VALUETYPE", "o") + " }";
662       if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
663       return;
664     }
665 
666     if (IsBool(field.value.type.base_type)) {
667       std::string default_value =
668           "0" == field.value.constant ? "false" : "true";
669       code_.SetValue("CONSTANT", default_value);
670       code_.SetValue("VALUETYPE", "Bool");
671       code_ += GenReaderMainBody(optional) + "\\";
672       code_.SetValue("VALUETYPE", "Byte");
673       code_ += GenOffset() + "return o == 0 ? {{CONSTANT}} : 0 != " +
674                GenReader("VALUETYPE", "o") + " }";
675       if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
676       return;
677     }
678 
679     if (IsEnum(field.value.type)) {
680       auto default_value =
681           field.IsOptional() ? "nil" : GenEnumDefaultValue(field);
682       code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
683       code_ += GenReaderMainBody(optional) + "\\";
684       code_ += GenOffset() + "return o == 0 ? " + default_value + " : " +
685                GenEnumConstructor("o") + "?? " + default_value + " }";
686       if (parser_.opts.mutable_buffer && !IsUnion(field.value.type))
687         code_ += GenMutate("o", GenOffset(), true);
688       return;
689     }
690 
691     std::string is_required = field.IsRequired() ? "!" : "?";
692     auto required_reader = field.IsRequired() ? "return " : const_string;
693 
694     if (IsStruct(field.value.type) && field.value.type.struct_def->fixed) {
695       code_.SetValue("VALUETYPE", GenType(field.value.type));
696       code_.SetValue("CONSTANT", "nil");
697       code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
698                "{{ACCESS}}.readBuffer(of: {{VALUETYPE}}.self, at: o) }";
699       code_.SetValue("VALUENAME", "mutable" + MakeCamel(name));
700       code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
701       code_.SetValue("CONSTANT", "nil");
702       code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader +
703                GenConstructor("o + {{ACCESS}}.postion");
704       return;
705     }
706     switch (field.value.type.base_type) {
707       case BASE_TYPE_STRUCT:
708         code_.SetValue("VALUETYPE", GenType(field.value.type));
709         code_.SetValue("CONSTANT", "nil");
710         code_ += GenReaderMainBody(is_required) + GenOffset() +
711                  required_reader +
712                  GenConstructor(GenIndirect("o + {{ACCESS}}.postion"));
713         break;
714 
715       case BASE_TYPE_STRING: {
716         auto default_string = "\"" + field.value.constant + "\"";
717         code_.SetValue("VALUETYPE", GenType(field.value.type));
718         code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil");
719         code_ += GenReaderMainBody(is_required) + GenOffset() +
720                  required_reader + "{{ACCESS}}.string(at: o) }";
721         code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}SegmentArray: [UInt8]" +
722                  is_required +
723                  " { return "
724                  "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }";
725         break;
726       }
727       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();  // fall thru
728       case BASE_TYPE_VECTOR: GenTableReaderVectorFields(field); break;
729       case BASE_TYPE_UNION:
730         code_.SetValue("CONSTANT", "nil");
731         code_ +=
732             "{{ACCESS_TYPE}} func {{VALUENAME}}<T: "
733             "FlatbuffersInitializable>(type: "
734             "T.Type) -> T" +
735             is_required + " { " + GenOffset() + required_reader +
736             "{{ACCESS}}.union(o) }";
737         break;
738       default: FLATBUFFERS_ASSERT(0);
739     }
740   }
741 
GenTableReaderVectorFields(const FieldDef & field)742   void GenTableReaderVectorFields(const FieldDef &field) {
743     std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
744     auto vectortype = field.value.type.VectorType();
745     code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
746     code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() +
747              "return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }";
748     code_.SetValue("CONSTANT",
749                    IsScalar(vectortype.base_type) == true ? "0" : "nil");
750     auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?";
751     nullable = IsEnum(vectortype) == true ? "?" : nullable;
752 
753     if (vectortype.base_type != BASE_TYPE_UNION) {
754       code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
755     } else {
756       code_ +=
757           "{{ACCESS_TYPE}} func {{VALUENAME}}<T: FlatbuffersInitializable>(at "
758           "index: "
759           "Int32, type: T.Type) -> T? { " +
760           GenOffset() + "\\";
761     }
762 
763     if (IsBool(vectortype.base_type)) {
764       code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true");
765       code_.SetValue("VALUETYPE", "Bool");
766     }
767 
768     if (!IsEnum(vectortype)) code_ += const_string + "\\";
769 
770     if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) &&
771         !IsBool(field.value.type.base_type)) {
772       code_ +=
773           "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
774           "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
775       code_ +=
776           "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}] { return "
777           "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) ?? [] }";
778       if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
779       return;
780     }
781 
782     if (vectortype.base_type == BASE_TYPE_STRUCT &&
783         field.value.type.struct_def->fixed) {
784       code_ +=
785           "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
786           "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
787       code_.SetValue("VALUENAME", "mutable" + MakeCamel(Name(field)));
788       code_.SetValue("VALUETYPE", GenType(field.value.type) + Mutable());
789       code_ += GenArrayMainBody(nullable) + GenOffset() + const_string +
790                GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
791 
792       return;
793     }
794 
795     if (IsString(vectortype)) {
796       code_ +=
797           "{{ACCESS}}.directString(at: {{ACCESS}}.vector(at: o) + "
798           "index * {{SIZE}}) }";
799       return;
800     }
801 
802     if (IsEnum(vectortype)) {
803       code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false));
804       code_ += "return o == 0 ? {{VALUETYPE}}" + GenEnumDefaultValue(field) +
805                " : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: "
806                "{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + "
807                "index * {{SIZE}})) }";
808       return;
809     }
810     if (vectortype.base_type == BASE_TYPE_UNION) {
811       code_ +=
812           "{{ACCESS}}.directUnion({{ACCESS}}.vector(at: o) + "
813           "index * {{SIZE}}) }";
814       return;
815     }
816 
817     if (vectortype.base_type == BASE_TYPE_STRUCT &&
818         !field.value.type.struct_def->fixed) {
819       code_ += GenConstructor(
820           "{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
821           "{{SIZE}})");
822       auto &sd = *field.value.type.struct_def;
823       auto &fields = sd.fields.vec;
824       for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
825         auto &key_field = **kit;
826         if (key_field.key) {
827           GenByKeyFunctions(key_field);
828           break;
829         }
830       }
831     }
832   }
833 
GenByKeyFunctions(const FieldDef & key_field)834   void GenByKeyFunctions(const FieldDef &key_field) {
835     code_.SetValue("TYPE", GenType(key_field.value.type));
836     code_ +=
837         "{{ACCESS_TYPE}} func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? "
838         "{ \\";
839     code_ += GenOffset() +
840              "return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
841              "{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }";
842   }
843 
GenEnum(const EnumDef & enum_def)844   void GenEnum(const EnumDef &enum_def) {
845     if (enum_def.generated) return;
846     auto is_private_access = enum_def.attributes.Lookup("private");
847     code_.SetValue("ACCESS_TYPE", is_private_access ? "internal" : "public");
848     code_.SetValue("ENUM_NAME", NameWrappedInNameSpace(enum_def));
849     code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
850     GenComment(enum_def.doc_comment);
851     code_ += "{{ACCESS_TYPE}} enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum {";
852     Indent();
853     code_ += "{{ACCESS_TYPE}} typealias T = {{BASE_TYPE}}";
854     code_ +=
855         "{{ACCESS_TYPE}} static var byteSize: Int { return "
856         "MemoryLayout<{{BASE_TYPE}}>.size "
857         "}";
858     code_ +=
859         "{{ACCESS_TYPE}} var value: {{BASE_TYPE}} { return self.rawValue }";
860     for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
861       const auto &ev = **it;
862       auto name = Name(ev);
863       code_.SetValue("KEY", name);
864       code_.SetValue("VALUE", enum_def.ToString(ev));
865       GenComment(ev.doc_comment);
866       code_ += "case {{KEY}} = {{VALUE}}";
867     }
868     code_ += "\n";
869     AddMinOrMaxEnumValue(Name(*enum_def.MaxValue()), "max");
870     AddMinOrMaxEnumValue(Name(*enum_def.MinValue()), "min");
871     Outdent();
872     code_ += "}\n";
873     if (parser_.opts.generate_object_based_api && enum_def.is_union) {
874       code_ += "{{ACCESS_TYPE}} struct {{ENUM_NAME}}Union {";
875       Indent();
876       code_ += "{{ACCESS_TYPE}} var type: {{ENUM_NAME}}";
877       code_ += "{{ACCESS_TYPE}} var value: NativeObject?";
878       code_ +=
879           "{{ACCESS_TYPE}} init(_ v: NativeObject?, type: {{ENUM_NAME}}) {";
880       Indent();
881       code_ += "self.type = type";
882       code_ += "self.value = v";
883       Outdent();
884       code_ += "}";
885       code_ +=
886           "{{ACCESS_TYPE}} func pack(builder: inout FlatBufferBuilder) -> "
887           "Offset {";
888       Indent();
889       BuildUnionEnumSwitchCaseWritter(enum_def);
890       Outdent();
891       code_ += "}";
892       Outdent();
893       code_ += "}";
894     }
895   }
896 
897   // MARK: - Object API
898 
GenerateObjectAPIExtensionHeader(std::string name)899   void GenerateObjectAPIExtensionHeader(std::string name) {
900     code_ += "\n";
901     code_ += "{{ACCESS_TYPE}} mutating func unpack() -> " + name + " {";
902     Indent();
903     code_ += "return " + name + "(&self)";
904     Outdent();
905     code_ += "}";
906     code_ +=
907         "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
908         "obj: "
909         "inout " +
910         name + "?) -> Offset {";
911     Indent();
912     code_ += "guard var obj = obj else { return Offset() }";
913     code_ += "return pack(&builder, obj: &obj)";
914     Outdent();
915     code_ += "}";
916     code_ += "";
917     code_ +=
918         "{{ACCESS_TYPE}} static func pack(_ builder: inout FlatBufferBuilder, "
919         "obj: "
920         "inout " +
921         name + ") -> Offset {";
922     Indent();
923   }
924 
GenerateObjectAPIStructConstructor(const StructDef & struct_def)925   void GenerateObjectAPIStructConstructor(const StructDef &struct_def) {
926     code_ +=
927         "{{ACCESS_TYPE}} init(_ _t: inout {{STRUCTNAME}}" + Mutable() + ") {";
928     Indent();
929     for (auto it = struct_def.fields.vec.begin();
930          it != struct_def.fields.vec.end(); ++it) {
931       auto &field = **it;
932       if (field.deprecated) continue;
933 
934       auto name = Name(field);
935       auto type = GenType(field.value.type);
936       code_.SetValue("VALUENAME", name);
937       if (IsStruct(field.value.type)) {
938         code_ += "var _v{{VALUENAME}} = _t.{{VALUENAME}}";
939         code_ += "_{{VALUENAME}} = _v{{VALUENAME}}.unpack()";
940         continue;
941       }
942       std::string is_enum = IsEnum(field.value.type) ? ".value" : "";
943       code_ += "_{{VALUENAME}} = _t.{{VALUENAME}}" + is_enum;
944     }
945     Outdent();
946     code_ += "}\n";
947   }
948 
GenObjectAPI(const StructDef & struct_def)949   void GenObjectAPI(const StructDef &struct_def) {
950     code_ += "{{ACCESS_TYPE}} class " + ObjectAPIName("{{STRUCTNAME}}") +
951              ": NativeObject {\n";
952     std::vector<std::string> buffer_constructor;
953     std::vector<std::string> base_constructor;
954     Indent();
955     for (auto it = struct_def.fields.vec.begin();
956          it != struct_def.fields.vec.end(); ++it) {
957       auto &field = **it;
958       if (field.deprecated) continue;
959       BuildObjectAPIConstructorBody(field, struct_def.fixed, buffer_constructor,
960                                     base_constructor);
961     }
962     code_ += "";
963     BuildObjectConstructor(buffer_constructor,
964                            "_ _t: inout " + NameWrappedInNameSpace(struct_def));
965     BuildObjectConstructor(base_constructor);
966     if (!struct_def.fixed)
967       code_ +=
968           "{{ACCESS_TYPE}} func serialize() -> ByteBuffer { return "
969           "serialize(type: "
970           "{{STRUCTNAME}}.self) }\n";
971     Outdent();
972     code_ += "}";
973   }
974 
GenerateObjectAPITableExtension(const StructDef & struct_def)975   void GenerateObjectAPITableExtension(const StructDef &struct_def) {
976     GenerateObjectAPIExtensionHeader(ObjectAPIName("{{STRUCTNAME}}"));
977     std::vector<std::string> unpack_body;
978     std::string builder = ", &builder)";
979     for (auto it = struct_def.fields.vec.begin();
980          it != struct_def.fields.vec.end(); ++it) {
981       auto &field = **it;
982       if (field.deprecated) continue;
983       auto name = Name(field);
984       auto type = GenType(field.value.type);
985       std::string check_if_vector =
986           (IsVector(field.value.type) || IsArray(field.value.type))
987               ? "VectorOf("
988               : "(";
989       std::string body = "add" + check_if_vector + name + ": ";
990       switch (field.value.type.base_type) {
991         case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
992         case BASE_TYPE_VECTOR: {
993           GenerateVectorObjectAPITableExtension(field, name, type);
994           unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
995                                 builder);
996           break;
997         }
998         case BASE_TYPE_UNION: {
999           code_ += "let __" + name + " = obj." + name +
1000                    "?.pack(builder: &builder) ?? Offset()";
1001           unpack_body.push_back("if let o = obj." + name + "?.type {");
1002           unpack_body.push_back("  {{STRUCTNAME}}.add(" + name + "Type: o" +
1003                                 builder);
1004           unpack_body.push_back("  {{STRUCTNAME}}." + body + "__" + name +
1005                                 builder);
1006           unpack_body.push_back("}\n");
1007           break;
1008         }
1009         case BASE_TYPE_STRUCT: {
1010           if (field.value.type.struct_def &&
1011               field.value.type.struct_def->fixed) {
1012             // This is a Struct (IsStruct), not a table. We create
1013             // a native swift object in this case.
1014             std::string code;
1015             GenerateStructArgs(*field.value.type.struct_def, &code, "", "",
1016                                "$0", true);
1017             code = code.substr(0, code.size() - 2);
1018             unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
1019                                   builder);
1020           } else {
1021             code_ += "let __" + name + " = " + type +
1022                      ".pack(&builder, obj: &obj." + name + ")";
1023             unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
1024                                   builder);
1025           }
1026           break;
1027         }
1028         case BASE_TYPE_STRING: {
1029           unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
1030                                 builder);
1031           if (field.IsRequired()) {
1032             code_ +=
1033                 "let __" + name + " = builder.create(string: obj." + name + ")";
1034           } else {
1035             BuildingOptionalObjects(name, "builder.create(string: s)");
1036           }
1037           break;
1038         }
1039         case BASE_TYPE_UTYPE: break;
1040         default:
1041           unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
1042                                 builder);
1043       }
1044     }
1045     code_ += "let __root = {{STRUCTNAME}}.start{{SHORT_STRUCTNAME}}(&builder)";
1046     for (auto it = unpack_body.begin(); it < unpack_body.end(); it++)
1047       code_ += *it;
1048     code_ +=
1049         "return {{STRUCTNAME}}.end{{SHORT_STRUCTNAME}}(&builder, start: "
1050         "__root)";
1051     Outdent();
1052     code_ += "}";
1053   }
1054 
GenerateVectorObjectAPITableExtension(const FieldDef & field,const std::string & name,const std::string & type)1055   void GenerateVectorObjectAPITableExtension(const FieldDef &field,
1056                                              const std::string &name,
1057                                              const std::string &type) {
1058     auto vectortype = field.value.type.VectorType();
1059     switch (vectortype.base_type) {
1060       case BASE_TYPE_UNION: {
1061         code_ += "var __" + name + "__: [Offset] = []";
1062         code_ += "for i in obj." + name + " {";
1063         Indent();
1064         code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
1065         code_ += "__" + name + "__.append(off)";
1066         Outdent();
1067         code_ += "}";
1068         code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
1069                  name + "__)";
1070         code_ += "let __" + name + "Type = builder.createVector(obj." + name +
1071                  ".compactMap { $0?.type })";
1072         break;
1073       }
1074       case BASE_TYPE_UTYPE: break;
1075       case BASE_TYPE_STRUCT: {
1076         if (field.value.type.struct_def &&
1077             !field.value.type.struct_def->fixed) {
1078           code_ += "var __" + name + "__: [Offset] = []";
1079           code_ += "for var i in obj." + name + " {";
1080           Indent();
1081           code_ +=
1082               "__" + name + "__.append(" + type + ".pack(&builder, obj: &i))";
1083           Outdent();
1084           code_ += "}";
1085           code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
1086                    name + "__)";
1087         } else {
1088           code_ += "{{STRUCTNAME}}.startVectorOf" + MakeCamel(name, true) +
1089                    "(obj." + name + ".count, in: &builder)";
1090           std::string code;
1091           GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "_o",
1092                              true);
1093           code = code.substr(0, code.size() - 2);
1094           code_ += "for i in obj." + name + " {";
1095           Indent();
1096           code_ += "guard let _o = i else { continue }";
1097           code_ += "builder.create(struct: _o)";
1098           Outdent();
1099           code_ += "}";
1100           code_ += "let __" + name + " = builder.endVector(len: obj." + name +
1101                    ".count)";
1102         }
1103         break;
1104       }
1105       case BASE_TYPE_STRING: {
1106         code_ += "let __" + name + " = builder.createVector(ofStrings: obj." +
1107                  name + ".compactMap({ $0 }) )";
1108         break;
1109       }
1110       default: {
1111         code_ += "let __" + name + " = builder.createVector(obj." + name + ")";
1112         break;
1113       }
1114     }
1115   }
1116 
BuildingOptionalObjects(const std::string & name,const std::string & body_front)1117   void BuildingOptionalObjects(const std::string &name,
1118                                const std::string &body_front) {
1119     code_ += "let __" + name + ": Offset";
1120     code_ += "if let s = obj." + name + " {";
1121     Indent();
1122     code_ += "__" + name + " = " + body_front;
1123     Outdent();
1124     code_ += "} else {";
1125     Indent();
1126     code_ += "__" + name + " = Offset()";
1127     Outdent();
1128     code_ += "}";
1129     code_ += "";
1130   }
1131 
BuildObjectConstructor(const std::vector<std::string> & body,const std::string & header="")1132   void BuildObjectConstructor(const std::vector<std::string> &body,
1133                               const std::string &header = "") {
1134     code_.SetValue("HEADER", header);
1135     code_ += "{{ACCESS_TYPE}} init({{HEADER}}) {";
1136     Indent();
1137     for (auto it = body.begin(); it < body.end(); ++it) code_ += *it;
1138     Outdent();
1139     code_ += "}\n";
1140   }
1141 
BuildObjectAPIConstructorBody(const FieldDef & field,bool is_fixed,std::vector<std::string> & buffer_constructor,std::vector<std::string> & base_constructor)1142   void BuildObjectAPIConstructorBody(
1143       const FieldDef &field, bool is_fixed,
1144       std::vector<std::string> &buffer_constructor,
1145       std::vector<std::string> &base_constructor) {
1146     auto name = Name(field);
1147     auto type = GenType(field.value.type);
1148     code_.SetValue("VALUENAME", name);
1149     code_.SetValue("VALUETYPE", type);
1150     std::string is_required = field.IsRequired() ? "" : "?";
1151 
1152     switch (field.value.type.base_type) {
1153       case BASE_TYPE_STRUCT: {
1154         type = GenType(field.value.type, true);
1155         code_.SetValue("VALUETYPE", type);
1156         auto optional =
1157             (field.value.type.struct_def && field.value.type.struct_def->fixed);
1158         std::string question_mark =
1159             (field.IsRequired() || (optional && is_fixed) ? "" : "?");
1160 
1161         code_ +=
1162             "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + question_mark;
1163         base_constructor.push_back("" + name + " = " + type + "()");
1164 
1165         if (field.value.type.struct_def->fixed) {
1166           buffer_constructor.push_back("" + name + " = _t." + name);
1167         } else {
1168           buffer_constructor.push_back("var __" + name + " = _t." + name);
1169           buffer_constructor.push_back(
1170               "" + name + " = __" + name +
1171               (field.IsRequired() ? "!" : question_mark) + ".unpack()");
1172         }
1173         break;
1174       }
1175       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
1176       case BASE_TYPE_VECTOR: {
1177         BuildObjectAPIConstructorBodyVectors(field, name, buffer_constructor,
1178                                              base_constructor, "    ");
1179         break;
1180       }
1181       case BASE_TYPE_STRING: {
1182         code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required;
1183         buffer_constructor.push_back(name + " = _t." + name);
1184 
1185         if (field.IsRequired()) {
1186           std::string default_value =
1187               field.IsDefault() ? field.value.constant : "";
1188           base_constructor.push_back(name + " = \"" + default_value + "\"");
1189           break;
1190         }
1191         if (field.IsDefault() && !field.IsRequired()) {
1192           std::string value = field.IsDefault() ? field.value.constant : "nil";
1193           base_constructor.push_back(name + " = \"" + value + "\"");
1194         }
1195         break;
1196       }
1197       case BASE_TYPE_UTYPE: break;
1198       case BASE_TYPE_UNION: {
1199         BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
1200                                  buffer_constructor);
1201         break;
1202       }
1203       default: {
1204         buffer_constructor.push_back(name + " = _t." + name);
1205         std::string nullable = field.IsOptional() ? "?" : "";
1206         if (IsScalar(field.value.type.base_type) &&
1207             !IsBool(field.value.type.base_type) && !IsEnum(field.value.type)) {
1208           code_ +=
1209               "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + nullable;
1210           if (!field.IsOptional())
1211             base_constructor.push_back(name + " = " + field.value.constant);
1212           break;
1213         }
1214 
1215         if (IsEnum(field.value.type)) {
1216           auto default_value = IsEnum(field.value.type)
1217                                    ? GenEnumDefaultValue(field)
1218                                    : field.value.constant;
1219           code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}";
1220           base_constructor.push_back(name + " = " + default_value);
1221           break;
1222         }
1223 
1224         if (IsBool(field.value.type.base_type)) {
1225           code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: Bool" + nullable;
1226           std::string default_value =
1227               "0" == field.value.constant ? "false" : "true";
1228           if (!field.IsOptional())
1229             base_constructor.push_back(name + " = " + default_value);
1230         }
1231       }
1232     }
1233   }
1234 
BuildObjectAPIConstructorBodyVectors(const FieldDef & field,const std::string & name,std::vector<std::string> & buffer_constructor,std::vector<std::string> & base_constructor,const std::string & indentation)1235   void BuildObjectAPIConstructorBodyVectors(
1236       const FieldDef &field, const std::string &name,
1237       std::vector<std::string> &buffer_constructor,
1238       std::vector<std::string> &base_constructor,
1239       const std::string &indentation) {
1240     auto vectortype = field.value.type.VectorType();
1241 
1242     if (vectortype.base_type != BASE_TYPE_UTYPE) {
1243       buffer_constructor.push_back(name + " = []");
1244       buffer_constructor.push_back("for index in 0..<_t." + name + "Count {");
1245       base_constructor.push_back(name + " = []");
1246     }
1247 
1248     switch (vectortype.base_type) {
1249       case BASE_TYPE_STRUCT: {
1250         code_.SetValue("VALUETYPE", GenType(vectortype, true));
1251         code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}?]";
1252         if (!vectortype.struct_def->fixed) {
1253           buffer_constructor.push_back(indentation + "var __v_ = _t." + name +
1254                                        "(at: index)");
1255           buffer_constructor.push_back(indentation + name +
1256                                        ".append(__v_?.unpack())");
1257         } else {
1258           buffer_constructor.push_back(indentation + name + ".append(_t." +
1259                                        name + "(at: index))");
1260         }
1261         break;
1262       }
1263       case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
1264       case BASE_TYPE_VECTOR: {
1265         break;
1266       }
1267       case BASE_TYPE_UNION: {
1268         BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
1269                                  buffer_constructor, indentation, true);
1270         break;
1271       }
1272       case BASE_TYPE_UTYPE: break;
1273       default: {
1274         code_.SetValue(
1275             "VALUETYPE",
1276             (IsString(vectortype) ? "String?" : GenType(vectortype)));
1277         code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: [{{VALUETYPE}}]";
1278 
1279         if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) {
1280           auto default_value = IsEnum(field.value.type)
1281                                    ? GenEnumDefaultValue(field)
1282                                    : field.value.constant;
1283           buffer_constructor.push_back(indentation + name + ".append(_t." +
1284                                        name + "(at: index)!)");
1285           break;
1286         }
1287         buffer_constructor.push_back(indentation + name + ".append(_t." + name +
1288                                      "(at: index))");
1289         break;
1290       }
1291     }
1292     if (vectortype.base_type != BASE_TYPE_UTYPE)
1293       buffer_constructor.push_back("}");
1294   }
1295 
BuildUnionEnumSwitchCaseWritter(const EnumDef & ev)1296   void BuildUnionEnumSwitchCaseWritter(const EnumDef &ev) {
1297     auto field_name = Name(ev);
1298     code_.SetValue("VALUETYPE", field_name);
1299     code_ += "switch type {";
1300     for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
1301       auto field = **it;
1302       auto ev_name = Name(field);
1303       auto type = GenType(field.union_type);
1304       auto is_struct = IsStruct(field.union_type) ? type + Mutable() : type;
1305       if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
1306       code_ += "case ." + ev_name + ":";
1307       Indent();
1308       code_ += "var __obj = value as? " + GenType(field.union_type, true);
1309       code_ += "return " + is_struct + ".pack(&builder, obj: &__obj)";
1310       Outdent();
1311     }
1312     code_ += "default: return Offset()";
1313     code_ += "}";
1314   }
1315 
BuildUnionEnumSwitchCase(const EnumDef & ev,const std::string & name,std::vector<std::string> & buffer_constructor,const std::string & indentation="",const bool is_vector=false)1316   void BuildUnionEnumSwitchCase(const EnumDef &ev, const std::string &name,
1317                                 std::vector<std::string> &buffer_constructor,
1318                                 const std::string &indentation = "",
1319                                 const bool is_vector = false) {
1320     auto field_name = NameWrappedInNameSpace(ev);
1321     code_.SetValue("VALUETYPE", field_name);
1322     code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: \\";
1323     code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
1324 
1325     auto vector_reader = is_vector ? "(at: index" : "";
1326     buffer_constructor.push_back(indentation + "switch _t." + name + "Type" +
1327                                  vector_reader + (is_vector ? ")" : "") + " {");
1328 
1329     for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
1330       auto field = **it;
1331       auto ev_name = Name(field);
1332       if (field.union_type.base_type == BASE_TYPE_NONE) { continue; }
1333       auto type = IsStruct(field.union_type)
1334                       ? GenType(field.union_type) + Mutable()
1335                       : GenType(field.union_type);
1336       buffer_constructor.push_back(indentation + "case ." + ev_name + ":");
1337       buffer_constructor.push_back(
1338           indentation + "  var _v = _t." + name + (is_vector ? "" : "(") +
1339           vector_reader + (is_vector ? ", " : "") + "type: " + type + ".self)");
1340       auto constructor =
1341           field_name + "Union(_v?.unpack(), type: ." + ev_name + ")";
1342       buffer_constructor.push_back(
1343           indentation + "  " + name +
1344           (is_vector ? ".append(" + constructor + ")" : " = " + constructor));
1345     }
1346     buffer_constructor.push_back(indentation + "default: break");
1347     buffer_constructor.push_back(indentation + "}");
1348   }
1349 
AddMinOrMaxEnumValue(const std::string & str,const std::string & type)1350   void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
1351     auto current_value = str;
1352     code_.SetValue(type, current_value);
1353     code_ += "{{ACCESS_TYPE}} static var " + type +
1354              ": {{ENUM_NAME}} { return .{{" + type + "}} }";
1355   }
1356 
GenLookup(const FieldDef & key_field)1357   void GenLookup(const FieldDef &key_field) {
1358     code_.SetValue("OFFSET", NumToString(key_field.value.offset));
1359     std::string offset_reader =
1360         "Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
1361         "fbb: fbb)";
1362 
1363     code_.SetValue("TYPE", GenType(key_field.value.type));
1364     code_ +=
1365         "fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
1366         "fbb: "
1367         "ByteBuffer) -> {{VALUENAME}}? {";
1368     Indent();
1369     if (IsString(key_field.value.type))
1370       code_ += "let key = key.utf8.map { $0 }";
1371     code_ += "var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
1372     code_ += "var start: Int32 = 0";
1373     code_ += "while span != 0 {";
1374     Indent();
1375     code_ += "var middle = span / 2";
1376     code_ +=
1377         "let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)";
1378     if (IsString(key_field.value.type)) {
1379       code_ += "let comp = Table.compare(" + offset_reader + ", key, fbb: fbb)";
1380     } else {
1381       code_ += "let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
1382                offset_reader + "))";
1383     }
1384 
1385     code_ += "if comp > 0 {";
1386     Indent();
1387     code_ += "span = middle";
1388     Outdent();
1389     code_ += "} else if comp < 0 {";
1390     Indent();
1391     code_ += "middle += 1";
1392     code_ += "start += middle";
1393     code_ += "span -= middle";
1394     Outdent();
1395     code_ += "} else {";
1396     Indent();
1397     code_ += "return {{VALUENAME}}(fbb, o: tableOffset)";
1398     Outdent();
1399     code_ += "}";
1400     Outdent();
1401     code_ += "}";
1402     code_ += "return nil";
1403     Outdent();
1404     code_ += "}";
1405   }
1406 
GenPadding(const FieldDef & field,int * id)1407   inline void GenPadding(const FieldDef &field, int *id) {
1408     if (field.padding) {
1409       for (int i = 0; i < 4; i++) {
1410         if (static_cast<int>(field.padding) & (1 << i)) {
1411           auto bits = (1 << i) * 8;
1412           code_ += "private let padding" + NumToString((*id)++) + "__: UInt" +
1413                    NumToString(bits) + " = 0";
1414         }
1415       }
1416       FLATBUFFERS_ASSERT(!(field.padding & ~0xF));
1417     }
1418   }
1419 
GenComment(const std::vector<std::string> & dc)1420   void GenComment(const std::vector<std::string> &dc) {
1421     if (dc.begin() == dc.end()) {
1422       // Don't output empty comment blocks with 0 lines of comment content.
1423       return;
1424     }
1425     for (auto it = dc.begin(); it != dc.end(); ++it) { code_ += "/// " + *it; }
1426   }
1427 
GenOffset()1428   std::string GenOffset() {
1429     return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
1430   }
1431 
GenReaderMainBody(const std::string & optional="")1432   std::string GenReaderMainBody(const std::string &optional = "") {
1433     return "{{ACCESS_TYPE}} var {{VALUENAME}}: {{VALUETYPE}}" + optional +
1434            " { ";
1435   }
1436 
GenReader(const std::string & type,const std::string & at="{{OFFSET}}")1437   std::string GenReader(const std::string &type,
1438                         const std::string &at = "{{OFFSET}}") {
1439     return "{{ACCESS}}.readBuffer(of: {{" + type + "}}.self, at: " + at + ")";
1440   }
1441 
GenConstructor(const std::string & offset)1442   std::string GenConstructor(const std::string &offset) {
1443     return "{{VALUETYPE}}({{ACCESS}}.bb, o: " + offset + ") }";
1444   }
1445 
GenMutate(const std::string & offset,const std::string & get_offset,bool isRaw=false)1446   std::string GenMutate(const std::string &offset,
1447                         const std::string &get_offset, bool isRaw = false) {
1448     return "@discardableResult {{ACCESS_TYPE}} func mutate({{VALUENAME}}: "
1449            "{{VALUETYPE}}) -> Bool {" +
1450            get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
1451            (isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
1452   }
1453 
GenMutateArray()1454   std::string GenMutateArray() {
1455     return "{{ACCESS_TYPE}} func mutate({{VALUENAME}}: {{VALUETYPE}}, at "
1456            "index: "
1457            "Int32) -> Bool { " +
1458            GenOffset() +
1459            "return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
1460            "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
1461   }
1462 
GenEnumDefaultValue(const FieldDef & field)1463   std::string GenEnumDefaultValue(const FieldDef &field) {
1464     auto &value = field.value;
1465     FLATBUFFERS_ASSERT(value.type.enum_def);
1466     auto &enum_def = *value.type.enum_def;
1467     // Vector of enum defaults are always "[]" which never works.
1468     const std::string constant = IsVector(value.type) ? "0" : value.constant;
1469     auto enum_val = enum_def.FindByValue(constant);
1470     std::string name;
1471     if (enum_val) {
1472       name = Name(*enum_val);
1473     } else {
1474       const auto &ev = **enum_def.Vals().begin();
1475       name = Name(ev);
1476     }
1477     return "." + name;
1478   }
1479 
GenEnumConstructor(const std::string & at)1480   std::string GenEnumConstructor(const std::string &at) {
1481     return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
1482   }
1483 
ValidateFunc()1484   std::string ValidateFunc() {
1485     return "static func validateVersion() { FlatBuffersVersion_2_0_0() }";
1486   }
1487 
GenType(const Type & type,const bool should_consider_suffix=false) const1488   std::string GenType(const Type &type,
1489                       const bool should_consider_suffix = false) const {
1490     return IsScalar(type.base_type)
1491                ? GenTypeBasic(type)
1492                : (IsArray(type) ? GenType(type.VectorType())
1493                                 : GenTypePointer(type, should_consider_suffix));
1494   }
1495 
GenTypePointer(const Type & type,const bool should_consider_suffix) const1496   std::string GenTypePointer(const Type &type,
1497                              const bool should_consider_suffix) const {
1498     switch (type.base_type) {
1499       case BASE_TYPE_STRING: return "String";
1500       case BASE_TYPE_VECTOR: return GenType(type.VectorType());
1501       case BASE_TYPE_STRUCT: {
1502         auto &struct_ = *type.struct_def;
1503         if (should_consider_suffix && !struct_.fixed) {
1504           return WrapInNameSpace(struct_.defined_namespace,
1505                                  ObjectAPIName(Name(struct_)));
1506         }
1507         return WrapInNameSpace(struct_.defined_namespace, Name(struct_));
1508       }
1509       case BASE_TYPE_UNION:
1510       default: return "FlatbuffersInitializable";
1511     }
1512   }
1513 
GenTypeBasic(const Type & type) const1514   std::string GenTypeBasic(const Type &type) const {
1515     return GenTypeBasic(type, true);
1516   }
1517 
ObjectAPIName(const std::string & name) const1518   std::string ObjectAPIName(const std::string &name) const {
1519     return parser_.opts.object_prefix + name + parser_.opts.object_suffix;
1520   }
1521 
Indent()1522   void Indent() { code_.IncrementIdentLevel(); }
1523 
Outdent()1524   void Outdent() { code_.DecrementIdentLevel(); }
1525 
NameWrappedInNameSpace(const EnumDef & enum_def) const1526   std::string NameWrappedInNameSpace(const EnumDef &enum_def) const {
1527     return WrapInNameSpace(enum_def.defined_namespace, Name(enum_def));
1528   }
1529 
NameWrappedInNameSpace(const StructDef & struct_def) const1530   std::string NameWrappedInNameSpace(const StructDef &struct_def) const {
1531     return WrapInNameSpace(struct_def.defined_namespace, Name(struct_def));
1532   }
1533 
GenTypeBasic(const Type & type,bool can_override) const1534   std::string GenTypeBasic(const Type &type, bool can_override) const {
1535     // clang-format off
1536     static const char * const swift_type[] = {
1537       #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
1538               CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE) \
1539         #STYPE,
1540         FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
1541       #undef FLATBUFFERS_TD
1542     };
1543     // clang-format on
1544     if (can_override) {
1545       if (type.enum_def) return NameWrappedInNameSpace(*type.enum_def);
1546       if (type.base_type == BASE_TYPE_BOOL) return "Bool";
1547     }
1548     return swift_type[static_cast<int>(type.base_type)];
1549   }
1550 
EscapeKeyword(const std::string & name) const1551   std::string EscapeKeyword(const std::string &name) const {
1552     return keywords_.find(name) == keywords_.end() ? name : name + "_";
1553   }
1554 
Mutable() const1555   std::string Mutable() const { return "_Mutable"; }
1556 
Name(const EnumVal & ev) const1557   std::string Name(const EnumVal &ev) const {
1558     auto name = ev.name;
1559     if (isupper(name.front())) {
1560       std::transform(name.begin(), name.end(), name.begin(), CharToLower);
1561     }
1562     return EscapeKeyword(MakeCamel(name, false));
1563   }
1564 
Name(const Definition & def) const1565   std::string Name(const Definition &def) const {
1566     return EscapeKeyword(MakeCamel(def.name, false));
1567   }
1568 };
1569 }  // namespace swift
GenerateSwift(const Parser & parser,const std::string & path,const std::string & file_name)1570 bool GenerateSwift(const Parser &parser, const std::string &path,
1571                    const std::string &file_name) {
1572   swift::SwiftGenerator generator(parser, path, file_name);
1573   return generator.generate();
1574 }
1575 }  // namespace flatbuffers
1576