...

Text file src/github.com/google/flatbuffers/src/idl_gen_swift.cpp

Documentation: github.com/google/flatbuffers/src

     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
    28namespace flatbuffers {
    29
    30namespace swift {
    31
    32namespace {
    33
    34static 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
    57static 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
   141static std::string GenIndirect(const std::string &reading) {
   142  return "{{ACCESS}}.indirect(" + reading + ")";
   143}
   144
   145static 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
   153class SwiftGenerator : public BaseGenerator {
   154 private:
   155  CodeWriter code_;
   156  std::unordered_set<std::string> keywords_;
   157  int namespace_depth;
   158
   159 public:
   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
   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
   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
   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
   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}}.postion + {{OFFSET}})";
   332      }
   333    }
   334    Outdent();
   335    code_ += "}\n";
   336  }
   337
   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}}.postion + {{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
   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
   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
   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
   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
   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
   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
   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
   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}}.postion");
   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}}.postion"));
   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
   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
   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
   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
   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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  1783  std::string GenOffset() {
  1784    return "let o = {{ACCESS}}.offset({{TABLEOFFSET}}.{{OFFSET}}.v); ";
  1785  }
  1786
  1787  std::string GenReaderMainBody(const std::string &optional = "") {
  1788    return "{{ACCESS_TYPE}} var {{FIELDVAR}}: {{VALUETYPE}}" + optional + " { ";
  1789  }
  1790
  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
  1796  std::string GenConstructor(const std::string &offset) {
  1797    return "{{VALUETYPE}}({{ACCESS}}.bb, o: " + offset + ") }";
  1798  }
  1799
  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
  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
  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
  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
  1843  std::string GenEnumConstructor(const std::string &at) {
  1844    return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
  1845  }
  1846
  1847  std::string ValidateFunc() {
  1848    return "static func validateVersion() { FlatBuffersVersion_23_5_26() }";
  1849  }
  1850
  1851  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
  1858  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
  1875  std::string GenTypeBasic(const Type &type) const {
  1876    return GenTypeBasic(type, true);
  1877  }
  1878
  1879  void Indent() { code_.IncrementIdentLevel(); }
  1880
  1881  void Outdent() { code_.DecrementIdentLevel(); }
  1882
  1883  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
  1900  std::string Mutable() const { return "_Mutable"; }
  1901
  1902  IdlNamer namer_;
  1903};
  1904}  // namespace swift
  1905
  1906static 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
  1912namespace {
  1913
  1914class SwiftCodeGenerator : public CodeGenerator {
  1915 public:
  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
  1922  Status GenerateCode(const uint8_t *, int64_t,
  1923                      const CodeGenOptions &) override {
  1924    return Status::NOT_IMPLEMENTED;
  1925  }
  1926
  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
  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
  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
  1950  bool IsSchemaOnly() const override { return true; }
  1951
  1952  bool SupportsBfbsGeneration() const override { return false; }
  1953
  1954  bool SupportsRootFileGeneration() const override { return false; }
  1955
  1956  IDLOptions::Language Language() const override { return IDLOptions::kSwift; }
  1957
  1958  std::string LanguageName() const override { return "Swift"; }
  1959};
  1960}  // namespace
  1961
  1962std::unique_ptr<CodeGenerator> NewSwiftCodeGenerator() {
  1963  return std::unique_ptr<SwiftCodeGenerator>(new SwiftCodeGenerator());
  1964}
  1965
  1966}  // namespace flatbuffers

View as plain text