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