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 <unordered_set>
18
19 #include "flatbuffers/code_generators.h"
20 #include "flatbuffers/flatbuffers.h"
21 #include "flatbuffers/idl.h"
22 #include "flatbuffers/util.h"
23
24 namespace flatbuffers {
25
26 namespace swift {
27
GenIndirect(const std::string & reading)28 inline std::string GenIndirect(const std::string &reading) {
29 return "{{ACCESS}}.indirect(" + reading + ")";
30 }
31
GenArrayMainBody(const std::string & optional)32 inline std::string GenArrayMainBody(const std::string &optional) {
33 return "\tpublic func {{VALUENAME}}(at index: Int32) -> {{VALUETYPE}}" +
34 optional + " { ";
35 }
36
LowerCase(char c)37 inline char LowerCase(char c) {
38 return static_cast<char>(::tolower(static_cast<unsigned char>(c)));
39 }
40
41 class SwiftGenerator : public BaseGenerator {
42 private:
43 const Namespace *cur_name_space_;
44 CodeWriter code_;
45 std::unordered_set<std::string> keywords_;
46 std::set<std::string> namespaces_;
47 int namespace_depth;
48
49 public:
SwiftGenerator(const Parser & parser,const std::string & path,const std::string & file_name)50 SwiftGenerator(const Parser &parser, const std::string &path,
51 const std::string &file_name)
52 : BaseGenerator(parser, path, file_name, "", ".", "swift"),
53 cur_name_space_(nullptr) {
54 namespace_depth = 0;
55 static const char *const keywords[] = {
56 "associatedtype",
57 "class",
58 "deinit",
59 "enum",
60 "extension",
61 "fileprivate",
62 "func",
63 "import",
64 "init",
65 "inout",
66 "internal",
67 "let",
68 "open",
69 "operator",
70 "private",
71 "protocol",
72 "public",
73 "rethrows",
74 "static",
75 "struct",
76 "subscript",
77 "typealias",
78 "var",
79 "break",
80 "case",
81 "continue",
82 "default",
83 "defer",
84 "do",
85 "else",
86 "fallthrough",
87 "for",
88 "guard",
89 "if",
90 "in",
91 "repeat",
92 "return",
93 "switch",
94 "where",
95 "while",
96 "Any",
97 "catch",
98 "false",
99 "is",
100 "nil",
101 "super",
102 "self",
103 "Self",
104 "throw",
105 "throws",
106 "true",
107 "try",
108 "associativity",
109 "convenience",
110 "dynamic",
111 "didSet",
112 "final",
113 "get",
114 "infix",
115 "indirect",
116 "lazy",
117 "left",
118 "mutating",
119 "none",
120 "nonmutating",
121 "optional",
122 "override",
123 "postfix",
124 "precedence",
125 "prefix",
126 "Protocol",
127 "required",
128 "right",
129 "set",
130 "Type",
131 "unowned",
132 "weak",
133 "willSet",
134 nullptr,
135 };
136 for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
137 }
138
generate()139 bool generate() {
140 code_.Clear();
141 code_.SetValue("ACCESS", "_accessor");
142 code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\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) {
150 SetNameSpace(enum_def.defined_namespace);
151 GenEnum(enum_def);
152 }
153 }
154
155 for (auto it = parser_.structs_.vec.begin();
156 it != parser_.structs_.vec.end(); ++it) {
157 const auto &struct_def = **it;
158 if (struct_def.fixed && !struct_def.generated) {
159 SetNameSpace(struct_def.defined_namespace);
160 GenStructReader(struct_def);
161 }
162 }
163
164 for (auto it = parser_.structs_.vec.begin();
165 it != parser_.structs_.vec.end(); ++it) {
166 const auto &struct_def = **it;
167 if (struct_def.fixed && !struct_def.generated) {
168 SetNameSpace(struct_def.defined_namespace);
169 GenStructWriter(struct_def);
170 }
171 }
172
173 for (auto it = parser_.structs_.vec.begin();
174 it != parser_.structs_.vec.end(); ++it) {
175 const auto &struct_def = **it;
176 if (!struct_def.fixed && !struct_def.generated) {
177 SetNameSpace(struct_def.defined_namespace);
178 GenTable(struct_def);
179 }
180 }
181
182 if (cur_name_space_) SetNameSpace(nullptr);
183
184 const auto filename = GeneratedFileName(path_, file_name_, parser_.opts);
185 const auto final_code = code_.ToString();
186 return SaveFile(filename.c_str(), final_code, false);
187 }
188
mark(const std::string & str)189 void mark(const std::string &str) {
190 code_.SetValue("MARKVALUE", str);
191 code_ += "\n// MARK: - {{MARKVALUE}}\n";
192 }
193
194 // Generates the create function for swift
GenStructWriter(const StructDef & struct_def)195 void GenStructWriter(const StructDef &struct_def) {
196 code_.SetValue("STRUCTNAME", Name(struct_def));
197 std::string static_type = this->namespace_depth == 0 ? "" : "static ";
198 code_ += "public " + static_type + "func create{{STRUCTNAME}}(\\";
199 std::string func_header = "";
200 GenerateStructArgs(struct_def, &func_header, "");
201 code_ += func_header.substr(0, func_header.size() - 2) + "\\";
202 code_ += ") -> UnsafeMutableRawPointer {";
203 code_ +=
204 "\tlet memory = UnsafeMutableRawPointer.allocate(byteCount: "
205 "{{STRUCTNAME}}.size, alignment: {{STRUCTNAME}}.alignment)";
206 code_ +=
207 "\tmemory.initializeMemory(as: UInt8.self, repeating: 0, count: "
208 "{{STRUCTNAME}}.size)";
209 GenerateStructBody(struct_def, "");
210 code_ += "\treturn memory";
211 code_ += "}\n";
212 }
213
GenerateStructBody(const StructDef & struct_def,const std::string & nameprefix,int offset=0)214 void GenerateStructBody(const StructDef &struct_def,
215 const std::string &nameprefix, int offset = 0) {
216 for (auto it = struct_def.fields.vec.begin();
217 it != struct_def.fields.vec.end(); ++it) {
218 auto &field = **it;
219 if (field.deprecated) continue;
220 auto name = nameprefix + Name(field);
221 const auto &field_type = field.value.type;
222 auto type = GenTypeBasic(field_type, false);
223 if (IsStruct(field.value.type)) {
224 GenerateStructBody(*field_type.struct_def, (nameprefix + field.name),
225 static_cast<int>(field.value.offset));
226 } else {
227 auto off = NumToString(offset + field.value.offset);
228 code_ += "\tmemory.storeBytes(of: " + name +
229 (field_type.enum_def ? ".rawValue" : "") +
230 ", toByteOffset: " + off + ", as: " + type + ".self)";
231 }
232 }
233 }
234
GenerateStructArgs(const StructDef & struct_def,std::string * code_ptr,const std::string & nameprefix)235 void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr,
236 const std::string &nameprefix) {
237 auto &code = *code_ptr;
238 for (auto it = struct_def.fields.vec.begin();
239 it != struct_def.fields.vec.end(); ++it) {
240 auto &field = **it;
241 if (field.deprecated) continue;
242 const auto &field_type = field.value.type;
243 if (IsStruct(field.value.type)) {
244 GenerateStructArgs(*field_type.struct_def, code_ptr,
245 (nameprefix + field.name));
246 } else {
247 auto name = Name(field);
248 auto type = GenType(field.value.type);
249 code += nameprefix + name + ": " + type;
250 code += ", ";
251 }
252 }
253 }
254
GenObjectHeader(const StructDef & struct_def)255 void GenObjectHeader(const StructDef &struct_def) {
256 GenComment(struct_def.doc_comment);
257 code_.SetValue("STRUCTNAME", Name(struct_def));
258 code_.SetValue("PROTOCOL",
259 struct_def.fixed ? "Readable" : "FlatBufferObject");
260 code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
261 code_ += "public struct {{STRUCTNAME}}: {{PROTOCOL}} {\n";
262 code_ += ValidateFunc();
263 code_ += "\tpublic var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
264 code_ += "\n\tprivate var {{ACCESS}}: {{OBJECTTYPE}}";
265 if (struct_def.fixed) {
266 code_.SetValue("BYTESIZE", NumToString(struct_def.bytesize));
267 code_.SetValue("MINALIGN", NumToString(struct_def.minalign));
268 code_ += "\tpublic static var size = {{BYTESIZE}}";
269 code_ += "\tpublic static var alignment = {{MINALIGN}}\t";
270 } else {
271 if (parser_.file_identifier_.length()) {
272 code_.SetValue("FILENAME", parser_.file_identifier_);
273 code_ +=
274 "\tpublic static func finish(_ fbb: FlatBufferBuilder, end: "
275 "Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, "
276 "fileId: "
277 "\"{{FILENAME}}\", addPrefix: prefix) }";
278 }
279 code_ +=
280 "\tpublic static func getRootAs{{STRUCTNAME}}(bb: ByteBuffer) -> "
281 "{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: "
282 "Int32(bb.read(def: UOffset.self, position: bb.reader)) + "
283 "Int32(bb.reader))) }\n";
284 code_ += "\tprivate init(_ t: Table) { {{ACCESS}} = t }";
285 }
286 code_ +=
287 "\tpublic init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
288 "{{OBJECTTYPE}}(bb: "
289 "bb, position: o) }";
290 code_ += "";
291 }
292
293 // Generates the reader for swift
GenTable(const StructDef & struct_def)294 void GenTable(const StructDef &struct_def) {
295 GenObjectHeader(struct_def);
296 GenTableReader(struct_def);
297 GenTableWriter(struct_def);
298 code_ += "}\n";
299 }
300
GenTableReader(const StructDef & struct_def)301 void GenTableReader(const StructDef &struct_def) {
302 for (auto it = struct_def.fields.vec.begin();
303 it != struct_def.fields.vec.end(); ++it) {
304 auto &field = **it;
305 if (field.deprecated) continue;
306 GenTableReaderFields(field);
307 }
308 }
309
GenTableWriter(const StructDef & struct_def)310 void GenTableWriter(const StructDef &struct_def) {
311 flatbuffers::FieldDef *key_field = nullptr;
312 std::vector<std::string> require_fields;
313 std::string create_func_body;
314 std::string create_func_header;
315 auto should_generate_create = struct_def.fields.vec.size() != 0;
316
317 code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
318 code_ +=
319 "\tpublic static func start{{STRUCTNAME}}(_ fbb: FlatBufferBuilder) -> "
320 "UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
321
322 for (auto it = struct_def.fields.vec.begin();
323 it != struct_def.fields.vec.end(); ++it) {
324 auto &field = **it;
325 if (field.deprecated) continue;
326 if (field.key) key_field = &field;
327 if (field.required)
328 require_fields.push_back(NumToString(field.value.offset));
329
330 GenTableWriterFields(
331 field, &create_func_body, &create_func_header,
332 static_cast<int>(it - struct_def.fields.vec.begin()));
333 }
334 code_ +=
335 "\tpublic static func end{{STRUCTNAME}}(_ fbb: FlatBufferBuilder, "
336 "start: "
337 "UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: "
338 "fbb.endTable(at: start))\\";
339 if (require_fields.capacity() != 0) {
340 std::string fields = "";
341 for (auto it = require_fields.begin(); it != require_fields.end(); ++it)
342 fields += *it + ", ";
343 code_.SetValue("FIELDS", fields.substr(0, fields.size() - 2));
344 code_ += "; fbb.require(table: end, fields: [{{FIELDS}}])\\";
345 }
346 code_ += "; return end }";
347
348 code_ +=
349 "\tpublic static func create{{STRUCTNAME}}(_ fbb: FlatBufferBuilder\\";
350 if (should_generate_create)
351 code_ += ",\n" +
352 create_func_header.substr(0, create_func_header.size() - 2) +
353 "\\";
354 code_ += ") -> Offset<UOffset> {";
355 code_ += "\t\tlet __start = {{STRUCTNAME}}.start{{STRUCTNAME}}(fbb)";
356 if (should_generate_create)
357 code_ += create_func_body.substr(0, create_func_body.size() - 1);
358 code_ += "\t\treturn {{STRUCTNAME}}.end{{STRUCTNAME}}(fbb, start: __start)";
359 code_ += "\t}";
360
361 std::string spacing = "\t\t";
362
363 if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
364 code_.SetValue("VALUENAME", struct_def.name);
365 code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
366
367 code_ +=
368 "\tpublic static func "
369 "sortVectorOf{{VALUENAME}}(offsets:[Offset<UOffset>], "
370 "_ fbb: FlatBufferBuilder) -> Offset<UOffset> {";
371 code_ += spacing + "var off = offsets";
372 code_ +=
373 spacing +
374 "off.sort { Table.compare(Table.offset(Int32($1.o), vOffset: "
375 "{{VOFFSET}}, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: "
376 "{{VOFFSET}}, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } ";
377 code_ += spacing + "return fbb.createVector(ofOffsets: off)";
378 code_ += "\t}";
379 GenLookup(*key_field);
380 }
381 }
382
GenTableWriterFields(const FieldDef & field,std::string * create_body,std::string * create_header,const int position)383 void GenTableWriterFields(const FieldDef &field, std::string *create_body,
384 std::string *create_header, const int position) {
385 std::string builder_string = ", _ fbb: FlatBufferBuilder) { fbb.add(";
386 auto &create_func_body = *create_body;
387 auto &create_func_header = *create_header;
388 auto name = Name(field);
389 auto type = GenType(field.value.type);
390 code_.SetValue("VALUENAME", name);
391 code_.SetValue("VALUETYPE", type);
392 code_.SetValue("OFFSET", NumToString(position));
393 code_.SetValue("CONSTANT", field.value.constant);
394 std::string check_if_vector =
395 (field.value.type.base_type == BASE_TYPE_VECTOR ||
396 field.value.type.base_type == BASE_TYPE_ARRAY)
397 ? "VectorOf("
398 : "(";
399 std::string body = "add" + check_if_vector + name + ": ";
400 code_ += "\tpublic static func " + body + "\\";
401
402 create_func_body += "\t\t{{STRUCTNAME}}." + body + name + ", fbb)\n";
403
404 if (IsScalar(field.value.type.base_type) &&
405 !IsBool(field.value.type.base_type)) {
406 auto default_value = IsEnum(field.value.type) ? GenEnumDefaultValue(field)
407 : field.value.constant;
408 auto is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
409 code_ += "{{VALUETYPE}}" + builder_string + "element: {{VALUENAME}}" +
410 is_enum + ", def: {{CONSTANT}}, at: {{OFFSET}}) }";
411 create_func_header +=
412 "\t\t" + name + ": " + type + " = " + default_value + ",\n";
413 return;
414 }
415
416 if (IsBool(field.value.type.base_type)) {
417 std::string default_value =
418 "0" == field.value.constant ? "false" : "true";
419 code_.SetValue("VALUETYPE", "Bool");
420 code_.SetValue("CONSTANT", default_value);
421 code_ += "{{VALUETYPE}}" + builder_string +
422 "condition: {{VALUENAME}}, def: {{CONSTANT}}, at: {{OFFSET}}) }";
423 create_func_header +=
424 "\t\t" + name + ": " + type + " = " + default_value + ",\n";
425 return;
426 }
427
428 auto offset_type = field.value.type.base_type == BASE_TYPE_STRING
429 ? "Offset<String>"
430 : "Offset<UOffset>";
431 auto camel_case_name =
432 (field.value.type.base_type == BASE_TYPE_VECTOR ||
433 field.value.type.base_type == BASE_TYPE_ARRAY
434 ? "vectorOf"
435 : "offsetOf") +
436 MakeCamel(name, true);
437 create_func_header += "\t\t" + camel_case_name + " " + name + ": " +
438 offset_type + " = Offset(),\n";
439 auto reader_type =
440 IsStruct(field.value.type) && field.value.type.struct_def->fixed
441 ? "structOffset: {{OFFSET}}) }"
442 : "offset: {{VALUENAME}}, at: {{OFFSET}}) }";
443 code_ += offset_type + builder_string + reader_type;
444 }
445
GenTableReaderFields(const FieldDef & field)446 void GenTableReaderFields(const FieldDef &field) {
447 auto offset = NumToString(field.value.offset);
448 auto name = Name(field);
449 auto type = GenType(field.value.type);
450 code_.SetValue("VALUENAME", name);
451 code_.SetValue("VALUETYPE", type);
452 code_.SetValue("OFFSET", offset);
453 code_.SetValue("CONSTANT", field.value.constant);
454 std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
455 GenComment(field.doc_comment, "\t");
456 if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
457 !IsBool(field.value.type.base_type)) {
458 code_ += GenReaderMainBody() + GenOffset() + const_string +
459 GenReader("VALUETYPE", "o") + " }";
460 if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
461 return;
462 }
463
464 if (IsBool(field.value.type.base_type)) {
465 code_.SetValue("VALUETYPE", "Bool");
466 code_ += GenReaderMainBody() + "\\";
467 code_.SetValue("VALUETYPE", "Byte");
468 code_ += GenOffset() +
469 "return o == 0 ? false : 0 != " + GenReader("VALUETYPE", "o") +
470 " }";
471 if (parser_.opts.mutable_buffer) code_ += GenMutate("o", GenOffset());
472 return;
473 }
474
475 if (IsEnum(field.value.type)) {
476 auto default_value = GenEnumDefaultValue(field);
477 code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
478 code_ += GenReaderMainBody() + "\\";
479 code_ += GenOffset() + "return o == 0 ? " + default_value + " : " +
480 GenEnumConstructor("o") + "?? " + default_value + " }";
481 if (parser_.opts.mutable_buffer && !IsUnion(field.value.type))
482 code_ += GenMutate("o", GenOffset(), true);
483 return;
484 }
485
486 if (IsStruct(field.value.type) && field.value.type.struct_def->fixed) {
487 code_.SetValue("VALUETYPE", GenType(field.value.type));
488 code_.SetValue("CONSTANT", "nil");
489 code_ += GenReaderMainBody("?") + GenOffset() + const_string +
490 GenConstructor("o + {{ACCESS}}.postion");
491 return;
492 }
493 switch (field.value.type.base_type) {
494 case BASE_TYPE_STRUCT:
495 code_.SetValue("VALUETYPE", GenType(field.value.type));
496 code_.SetValue("CONSTANT", "nil");
497 code_ += GenReaderMainBody("?") + GenOffset() + const_string +
498 GenConstructor(GenIndirect("o + {{ACCESS}}.postion"));
499 break;
500
501 case BASE_TYPE_STRING:
502 code_.SetValue("VALUETYPE", GenType(field.value.type));
503 code_.SetValue("CONSTANT", "nil");
504 code_ += GenReaderMainBody("?") + GenOffset() + const_string +
505 "{{ACCESS}}.string(at: o) }";
506 code_ +=
507 "\tpublic var {{VALUENAME}}SegmentArray: [UInt8]? { return "
508 "{{ACCESS}}.getVector(at: {{OFFSET}}) }";
509 break;
510
511 case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
512 case BASE_TYPE_VECTOR:
513 GenTableReaderVectorFields(field, const_string);
514 break;
515 case BASE_TYPE_UNION:
516 code_.SetValue("CONSTANT", "nil");
517 code_ +=
518 "\tpublic func {{VALUENAME}}<T: FlatBufferObject>(type: "
519 "T.Type) -> T? { " +
520 GenOffset() + const_string + "{{ACCESS}}.union(o) }";
521 break;
522 default: FLATBUFFERS_ASSERT(0);
523 }
524 }
525
GenTableReaderVectorFields(const FieldDef & field,const std::string & const_string)526 void GenTableReaderVectorFields(const FieldDef &field,
527 const std::string &const_string) {
528 auto vectortype = field.value.type.VectorType();
529 code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
530 code_ += "\tpublic var {{VALUENAME}}Count: Int32 { " + GenOffset() +
531 const_string + "{{ACCESS}}.vector(count: o) }";
532 code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) == true
533 ? field.value.constant
534 : "nil");
535 auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?";
536 nullable = IsEnum(vectortype) == true ? "?" : nullable;
537 if (vectortype.base_type != BASE_TYPE_UNION) {
538 code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
539 } else {
540 code_ +=
541 "\tpublic func {{VALUENAME}}<T: FlatBufferObject>(at index: "
542 "Int32, type: T.Type) -> T? { " +
543 GenOffset() + "\\";
544 }
545
546 if (IsBool(vectortype.base_type)) {
547 code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true");
548 code_.SetValue("VALUETYPE", "Byte");
549 }
550 if (!IsEnum(vectortype))
551 code_ +=
552 const_string + (IsBool(vectortype.base_type) ? "0 != " : "") + "\\";
553
554 if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) &&
555 !IsBool(field.value.type.base_type)) {
556 code_ +=
557 "{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
558 "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
559 code_ +=
560 "\tpublic var {{VALUENAME}}: [{{VALUETYPE}}] { return "
561 "{{ACCESS}}.getVector(at: {{OFFSET}}) ?? [] }";
562 if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
563 return;
564 }
565 if (vectortype.base_type == BASE_TYPE_STRUCT &&
566 field.value.type.struct_def->fixed) {
567 code_ += GenConstructor("{{ACCESS}}.vector(at: o) + index * {{SIZE}}");
568 return;
569 }
570
571 if (vectortype.base_type == BASE_TYPE_STRING) {
572 code_ +=
573 "{{ACCESS}}.directString(at: {{ACCESS}}.vector(at: o) + "
574 "index * {{SIZE}}) }";
575 return;
576 }
577
578 if (IsEnum(vectortype)) {
579 code_.SetValue("BASEVALUE", GenTypeBasic(vectortype, false));
580 code_ += "return o == 0 ? {{VALUETYPE}}" + GenEnumDefaultValue(field) +
581 " : {{VALUETYPE}}(rawValue: {{ACCESS}}.directRead(of: "
582 "{{BASEVALUE}}.self, offset: {{ACCESS}}.vector(at: o) + "
583 "index * {{SIZE}})) }";
584 return;
585 }
586 if (vectortype.base_type == BASE_TYPE_UNION) {
587 code_ +=
588 "{{ACCESS}}.directUnion({{ACCESS}}.vector(at: o) + "
589 "index * {{SIZE}}) }";
590 return;
591 }
592
593 if (vectortype.base_type == BASE_TYPE_STRUCT &&
594 !field.value.type.struct_def->fixed) {
595 code_ += GenConstructor(
596 "{{ACCESS}}.indirect({{ACCESS}}.vector(at: o) + index * "
597 "{{SIZE}})");
598 auto &sd = *field.value.type.struct_def;
599 auto &fields = sd.fields.vec;
600 for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
601 auto &key_field = **kit;
602 if (key_field.key) {
603 GenByKeyFunctions(key_field);
604 break;
605 }
606 }
607 }
608 }
609
GenByKeyFunctions(const FieldDef & key_field)610 void GenByKeyFunctions(const FieldDef &key_field) {
611 code_.SetValue("TYPE", GenType(key_field.value.type));
612 code_ +=
613 "\tpublic func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? { \\";
614 code_ += GenOffset() +
615 "return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
616 "{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }";
617 }
618
619 // Generates the reader for swift
GenStructReader(const StructDef & struct_def)620 void GenStructReader(const StructDef &struct_def) {
621 GenObjectHeader(struct_def);
622 for (auto it = struct_def.fields.vec.begin();
623 it != struct_def.fields.vec.end(); ++it) {
624 auto &field = **it;
625 if (field.deprecated) continue;
626 auto offset = NumToString(field.value.offset);
627 auto name = Name(field);
628 auto type = GenType(field.value.type);
629 code_.SetValue("VALUENAME", name);
630 code_.SetValue("VALUETYPE", type);
631 code_.SetValue("OFFSET", offset);
632 GenComment(field.doc_comment, "\t");
633 if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
634 code_ +=
635 GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
636 if (parser_.opts.mutable_buffer) code_ += GenMutate("{{OFFSET}}", "");
637 } else if (IsEnum(field.value.type)) {
638 code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false));
639 code_ += GenReaderMainBody() + "return " +
640 GenEnumConstructor("{{OFFSET}}") + "?? " +
641 GenEnumDefaultValue(field) + " }";
642 } else if (IsStruct(field.value.type)) {
643 code_.SetValue("VALUETYPE", GenType(field.value.type));
644 code_ += GenReaderMainBody() + "return " +
645 GenConstructor("{{ACCESS}}.postion + {{OFFSET}}");
646 }
647 }
648
649 code_ += "}\n";
650 }
651
GenEnum(const EnumDef & enum_def)652 void GenEnum(const EnumDef &enum_def) {
653 if (enum_def.generated) return;
654 code_.SetValue("ENUM_NAME", Name(enum_def));
655 code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
656 GenComment(enum_def.doc_comment);
657 code_ += "public enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum { ";
658 code_ += "\tpublic typealias T = {{BASE_TYPE}}";
659 code_ +=
660 "\tpublic static var byteSize: Int { return "
661 "MemoryLayout<{{BASE_TYPE}}>.size "
662 "}";
663 code_ += "\tpublic var value: {{BASE_TYPE}} { return self.rawValue }";
664
665 for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
666 const auto &ev = **it;
667 auto name = Name(ev);
668 std::transform(name.begin(), name.end(), name.begin(), LowerCase);
669 code_.SetValue("KEY", name);
670 code_.SetValue("VALUE", enum_def.ToString(ev));
671 GenComment(ev.doc_comment, "\t");
672 code_ += "\tcase {{KEY}} = {{VALUE}}";
673 }
674 code_ += "\n";
675 AddMinOrMaxEnumValue(enum_def.MaxValue()->name, "max");
676 AddMinOrMaxEnumValue(enum_def.MinValue()->name, "min");
677 code_ += "}\n";
678 }
679
AddMinOrMaxEnumValue(const std::string & str,const std::string & type)680 void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
681 auto current_value = str;
682 std::transform(current_value.begin(), current_value.end(),
683 current_value.begin(), LowerCase);
684 code_.SetValue(type, current_value);
685 code_ += "\tpublic static var " + type + ": {{ENUM_NAME}} { return .{{" +
686 type + "}} }";
687 }
688
GenLookup(const FieldDef & key_field)689 void GenLookup(const FieldDef &key_field) {
690 code_.SetValue("OFFSET", NumToString(key_field.value.offset));
691 auto offset_reader =
692 "Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
693 "fbb: fbb)";
694 std::string spacing = "\t\t";
695 std::string double_spacing = spacing + "\t";
696
697 code_.SetValue("TYPE", GenType(key_field.value.type));
698 code_ +=
699 "\tfileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
700 "fbb: "
701 "ByteBuffer) -> {{VALUENAME}}? {";
702
703 if (key_field.value.type.base_type == BASE_TYPE_STRING)
704 code_ += spacing + "let key = key.utf8.map { $0 }";
705 code_ += spacing +
706 "var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
707 code_ += spacing + "var start: Int32 = 0";
708 code_ += spacing + "while span != 0 {";
709 code_ += double_spacing + "var middle = span / 2";
710 code_ +=
711 double_spacing +
712 "let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)";
713 if (key_field.value.type.base_type == BASE_TYPE_STRING) {
714 code_ += double_spacing + "let comp = Table.compare(" + offset_reader +
715 ", key, fbb: fbb)";
716 } else {
717 code_ += double_spacing +
718 "let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
719 offset_reader + "))";
720 }
721
722 code_ += double_spacing + "if comp > 0 {";
723 code_ += double_spacing + "\tspan = middle";
724 code_ += double_spacing + "} else if comp < 0 {";
725 code_ += double_spacing + "\tmiddle += 1";
726 code_ += double_spacing + "\tstart += middle";
727 code_ += double_spacing + "\tspan -= middle";
728 code_ += double_spacing + "} else {";
729 code_ += double_spacing + "\treturn {{VALUENAME}}(fbb, o: tableOffset)";
730 code_ += double_spacing + "}";
731 code_ += spacing + "}";
732 code_ += spacing + "return nil";
733 code_ += "\t}";
734 }
735
GenComment(const std::vector<std::string> & dc,const char * prefix="")736 void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
737 std::string text;
738 ::flatbuffers::GenComment(dc, &text, nullptr, prefix);
739 code_ += text + "\\";
740 }
741
GenOffset()742 std::string GenOffset() { return "let o = {{ACCESS}}.offset({{OFFSET}}); "; }
743
GenReaderMainBody(const std::string & optional="")744 std::string GenReaderMainBody(const std::string &optional = "") {
745 return "\tpublic var {{VALUENAME}}: {{VALUETYPE}}" + optional + " { ";
746 }
747
GenReader(const std::string & type,const std::string & at="{{OFFSET}}")748 std::string GenReader(const std::string &type,
749 const std::string &at = "{{OFFSET}}") {
750 return "{{ACCESS}}.readBuffer(of: {{" + type + "}}.self, at: " + at + ")";
751 }
752
GenConstructor(const std::string & offset)753 std::string GenConstructor(const std::string &offset) {
754 return "{{VALUETYPE}}({{ACCESS}}.bb, o: " + offset + ") }";
755 }
756
GenMutate(const std::string & offset,const std::string & get_offset,bool isRaw=false)757 std::string GenMutate(const std::string &offset,
758 const std::string &get_offset, bool isRaw = false) {
759 return "\tpublic func mutate({{VALUENAME}}: {{VALUETYPE}}) -> Bool {" +
760 get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
761 (isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
762 }
763
GenMutateArray()764 std::string GenMutateArray() {
765 return "\tpublic func mutate({{VALUENAME}}: {{VALUETYPE}}, at index: "
766 "Int32) -> Bool { " +
767 GenOffset() +
768 "return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
769 "{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
770 }
771
GenEnumDefaultValue(const FieldDef & field)772 std::string GenEnumDefaultValue(const FieldDef &field) {
773 auto &value = field.value;
774 FLATBUFFERS_ASSERT(value.type.enum_def);
775 auto &enum_def = *value.type.enum_def;
776 auto enum_val = enum_def.FindByValue(value.constant);
777 std::string name;
778 if (enum_val) {
779 name = enum_val->name;
780 } else {
781 const auto &ev = **enum_def.Vals().begin();
782 name = ev.name;
783 }
784 std::transform(name.begin(), name.end(), name.begin(), LowerCase);
785 return "." + name;
786 }
787
GenEnumConstructor(const std::string & at)788 std::string GenEnumConstructor(const std::string &at) {
789 return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
790 }
791
ValidateFunc()792 std::string ValidateFunc() {
793 return "\tstatic func validateVersion() { FlatBuffersVersion_1_12_0() }";
794 }
795
GenType(const Type & type) const796 std::string GenType(const Type &type) const {
797 return IsScalar(type.base_type)
798 ? GenTypeBasic(type)
799 : (IsArray(type) ? GenType(type.VectorType())
800 : GenTypePointer(type));
801 }
802
GenTypePointer(const Type & type) const803 std::string GenTypePointer(const Type &type) const {
804 switch (type.base_type) {
805 case BASE_TYPE_STRING: return "String";
806 case BASE_TYPE_VECTOR: return GenType(type.VectorType());
807 case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def);
808 case BASE_TYPE_UNION:
809 default: return "FlatBufferObject";
810 }
811 }
812
GenTypeBasic(const Type & type) const813 std::string GenTypeBasic(const Type &type) const {
814 return GenTypeBasic(type, true);
815 }
816
GenTypeBasic(const Type & type,bool can_override) const817 std::string GenTypeBasic(const Type &type, bool can_override) const {
818 // clang-format off
819 static const char * const swift_type[] = {
820 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
821 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE, STYPE) \
822 #STYPE,
823 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
824 #undef FLATBUFFERS_TD
825 };
826 // clang-format on
827 if (can_override) {
828 if (type.enum_def)
829 return WrapInNameSpace(type.enum_def->defined_namespace,
830 Name(*type.enum_def));
831 if (type.base_type == BASE_TYPE_BOOL) return "Bool";
832 }
833 return swift_type[static_cast<int>(type.base_type)];
834 }
835
EscapeKeyword(const std::string & name) const836 std::string EscapeKeyword(const std::string &name) const {
837 return keywords_.find(name) == keywords_.end() ? name : name + "_";
838 }
839
Name(const EnumVal & ev) const840 std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
841
Name(const Definition & def) const842 std::string Name(const Definition &def) const {
843 return EscapeKeyword(MakeCamel(def.name, false));
844 }
845
846 // MARK: - Copied from the cpp implementation, needs revisiting
SetNameSpace(const Namespace * ns)847 void SetNameSpace(const Namespace *ns) {
848 if (cur_name_space_ == ns) { return; }
849 // Compute the size of the longest common namespace prefix.
850 // If cur_name_space is A::B::C::D and ns is A::B::E::F::G,
851 // the common prefix is A::B:: and we have old_size = 4, new_size = 5
852 // and common_prefix_size = 2
853 size_t old_size = cur_name_space_ ? cur_name_space_->components.size() : 0;
854 size_t new_size = ns ? ns->components.size() : 0;
855
856 size_t common_prefix_size = 0;
857 while (common_prefix_size < old_size && common_prefix_size < new_size &&
858 ns->components[common_prefix_size] ==
859 cur_name_space_->components[common_prefix_size]) {
860 common_prefix_size++;
861 }
862
863 // Close cur_name_space in reverse order to reach the common prefix.
864 // In the previous example, D then C are closed.
865 for (size_t j = old_size; j > common_prefix_size; --j) {
866 if (namespace_depth != 0) {
867 code_ += "}";
868 namespace_depth -= 1;
869 }
870 mark(cur_name_space_->components[j - 1]);
871 }
872 if (old_size != common_prefix_size) { code_ += ""; }
873
874 // open namespace parts to reach the ns namespace
875 // in the previous example, E, then F, then G are opened
876 bool is_extension = false;
877 for (auto j = common_prefix_size; j < new_size; ++j) {
878 std::string name = ns->components[j];
879 if (namespaces_.find(name) == namespaces_.end()) {
880 code_ += "public enum " + name + " {";
881 namespace_depth += 1;
882 namespaces_.insert(name);
883 } else {
884 code_ += "}";
885 is_extension = true;
886 }
887 }
888 if (is_extension) {
889 code_.SetValue("EXTENSION", FullNamespace(".", *ns));
890 code_ += "extension {{EXTENSION}} {";
891 }
892 if (new_size != common_prefix_size) { code_ += ""; }
893 cur_name_space_ = ns;
894 }
895 };
896 } // namespace swift
GenerateSwift(const Parser & parser,const std::string & path,const std::string & file_name)897 bool GenerateSwift(const Parser &parser, const std::string &path,
898 const std::string &file_name) {
899 swift::SwiftGenerator generator(parser, path, file_name);
900 return generator.generate();
901 }
902 } // namespace flatbuffers
903