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