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