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