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