[Swift] Object API support (#5826)

* Adds Object-api support to swift

* Fixed indentation issues

* Removed indentation within namespaces
This commit is contained in:
mustiikhalil
2020-04-13 19:28:56 +03:00
committed by GitHub
parent 003e164057
commit cb4d0f72e3
14 changed files with 2323 additions and 865 deletions

View File

@@ -22,7 +22,7 @@ Feature | C++ | Java | C# | Go | Python | JS
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ------- | ------
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | Yes
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes

View File

@@ -76,6 +76,10 @@ class CodeWriter {
if (cur_ident_lvl_) cur_ident_lvl_--;
}
void SetPadding(const std::string &padding) {
pad_ = padding;
}
private:
std::map<std::string, std::string> value_map_;
std::stringstream stream_;

View File

@@ -30,7 +30,7 @@ inline std::string GenIndirect(const std::string &reading) {
}
inline std::string GenArrayMainBody(const std::string &optional) {
return "\tpublic func {{VALUENAME}}(at index: Int32) -> {{VALUETYPE}}" +
return "public func {{VALUENAME}}(at index: Int32) -> {{VALUETYPE}}" +
optional + " { ";
}
@@ -52,6 +52,7 @@ class SwiftGenerator : public BaseGenerator {
: BaseGenerator(parser, path, file_name, "", ".", "swift"),
cur_name_space_(nullptr) {
namespace_depth = 0;
code_.SetPadding(" ");
static const char *const keywords[] = {
"associatedtype",
"class",
@@ -158,6 +159,9 @@ class SwiftGenerator : public BaseGenerator {
if (struct_def.fixed && !struct_def.generated) {
SetNameSpace(struct_def.defined_namespace);
GenStructReader(struct_def);
if (parser_.opts.generate_object_based_api) {
GenObjectAPI(struct_def);
}
}
}
@@ -176,6 +180,9 @@ class SwiftGenerator : public BaseGenerator {
if (!struct_def.fixed && !struct_def.generated) {
SetNameSpace(struct_def.defined_namespace);
GenTable(struct_def);
if (parser_.opts.generate_object_based_api) {
GenObjectAPI(struct_def);
}
}
}
@@ -197,17 +204,19 @@ class SwiftGenerator : public BaseGenerator {
std::string static_type = this->namespace_depth == 0 ? "" : "static ";
code_ += "public " + static_type + "func create{{STRUCTNAME}}(\\";
std::string func_header = "";
GenerateStructArgs(struct_def, &func_header, "");
GenerateStructArgs(struct_def, &func_header, "", "");
code_ += func_header.substr(0, func_header.size() - 2) + "\\";
code_ += ") -> UnsafeMutableRawPointer {";
Indent();
code_ +=
"\tlet memory = UnsafeMutableRawPointer.allocate(byteCount: "
"let memory = UnsafeMutableRawPointer.allocate(byteCount: "
"{{STRUCTNAME}}.size, alignment: {{STRUCTNAME}}.alignment)";
code_ +=
"\tmemory.initializeMemory(as: UInt8.self, repeating: 0, count: "
"memory.initializeMemory(as: UInt8.self, repeating: 0, count: "
"{{STRUCTNAME}}.size)";
GenerateStructBody(struct_def, "");
code_ += "\treturn memory";
code_ += "return memory";
Outdent();
code_ += "}\n";
}
@@ -225,7 +234,7 @@ class SwiftGenerator : public BaseGenerator {
static_cast<int>(field.value.offset));
} else {
auto off = NumToString(offset + field.value.offset);
code_ += "\tmemory.storeBytes(of: " + name +
code_ += "memory.storeBytes(of: " + name +
(field_type.enum_def ? ".rawValue" : "") +
", toByteOffset: " + off + ", as: " + type + ".self)";
}
@@ -233,7 +242,10 @@ class SwiftGenerator : public BaseGenerator {
}
void GenerateStructArgs(const StructDef &struct_def, std::string *code_ptr,
const std::string &nameprefix) {
const std::string &nameprefix,
const std::string &object_name,
const std::string &obj_api_named = "",
bool is_obj_api = false) {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@@ -241,13 +253,20 @@ class SwiftGenerator : public BaseGenerator {
if (field.deprecated) continue;
const auto &field_type = field.value.type;
if (IsStruct(field.value.type)) {
GenerateStructArgs(*field_type.struct_def, code_ptr,
(nameprefix + field.name));
GenerateStructArgs(
*field_type.struct_def, code_ptr, (nameprefix + field.name),
(object_name + "." + field.name), obj_api_named, is_obj_api);
} else {
auto name = Name(field);
auto type = GenType(field.value.type);
if (!is_obj_api) {
code += nameprefix + name + ": " + type;
code += ", ";
continue;
}
code +=
nameprefix + name + ": " + obj_api_named + object_name + "." + name;
code += ", ";
}
}
}
@@ -259,32 +278,33 @@ class SwiftGenerator : public BaseGenerator {
struct_def.fixed ? "Readable" : "FlatBufferObject");
code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
code_ += "public struct {{STRUCTNAME}}: {{PROTOCOL}} {\n";
Indent();
code_ += ValidateFunc();
code_ += "\tpublic var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
code_ += "\n\tprivate var {{ACCESS}}: {{OBJECTTYPE}}";
code_ += "public var __buffer: ByteBuffer! { return {{ACCESS}}.bb }";
code_ += "private var {{ACCESS}}: {{OBJECTTYPE}}\n";
if (struct_def.fixed) {
code_.SetValue("BYTESIZE", NumToString(struct_def.bytesize));
code_.SetValue("MINALIGN", NumToString(struct_def.minalign));
code_ += "\tpublic static var size = {{BYTESIZE}}";
code_ += "\tpublic static var alignment = {{MINALIGN}}\t";
code_ += "public static var size = {{BYTESIZE}}";
code_ += "public static var alignment = {{MINALIGN}}";
} else {
if (parser_.file_identifier_.length()) {
code_.SetValue("FILENAME", parser_.file_identifier_);
code_ +=
"\tpublic static func finish(_ fbb: inout FlatBufferBuilder, end: "
"public static func finish(_ fbb: inout FlatBufferBuilder, end: "
"Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, "
"fileId: "
"\"{{FILENAME}}\", addPrefix: prefix) }";
}
code_ +=
"\tpublic static func getRootAs{{STRUCTNAME}}(bb: ByteBuffer) -> "
"public static func getRootAs{{STRUCTNAME}}(bb: ByteBuffer) -> "
"{{STRUCTNAME}} { return {{STRUCTNAME}}(Table(bb: bb, position: "
"Int32(bb.read(def: UOffset.self, position: bb.reader)) + "
"Int32(bb.reader))) }\n";
code_ += "\tprivate init(_ t: Table) { {{ACCESS}} = t }";
code_ += "private init(_ t: Table) { {{ACCESS}} = t }";
}
code_ +=
"\tpublic init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
"public init(_ bb: ByteBuffer, o: Int32) { {{ACCESS}} = "
"{{OBJECTTYPE}}(bb: "
"bb, position: o) }";
code_ += "";
@@ -295,9 +315,38 @@ class SwiftGenerator : public BaseGenerator {
GenObjectHeader(struct_def);
GenTableReader(struct_def);
GenTableWriter(struct_def);
if (parser_.opts.generate_object_based_api)
GenerateObjectAPITableExtension(struct_def);
Outdent();
code_ += "}\n";
}
void GenerateObjectAPIExtensionHeader() {
code_ += "\n";
code_ += "public mutating func unpack() -> {{STRUCTNAME}}T {";
Indent();
code_ += "return {{STRUCTNAME}}T(&self)";
Outdent();
code_ += "}";
code_ +=
"public static func pack(_ builder: inout FlatBufferBuilder, obj: "
"inout {{STRUCTNAME}}T?) -> Offset<UOffset> {";
Indent();
code_ += "guard let obj = obj else { return Offset<UOffset>() }";
code_ += "";
}
void GenerateObjectAPIStructExtension(const StructDef &struct_def) {
GenerateObjectAPIExtensionHeader();
std::string code;
GenerateStructArgs(struct_def, &code, "", "", "obj", true);
code_ += "return builder.create(struct: create{{STRUCTNAME}}(\\";
code_ += code.substr(0, code.size() - 2) + "\\";
code_ += "), type: {{STRUCTNAME}}.self)";
Outdent();
code_ += "}";
}
void GenTableReader(const StructDef &struct_def) {
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
@@ -310,13 +359,14 @@ class SwiftGenerator : public BaseGenerator {
void GenTableWriter(const StructDef &struct_def) {
flatbuffers::FieldDef *key_field = nullptr;
std::vector<std::string> require_fields;
std::string create_func_body;
std::string create_func_header;
std::vector<std::string> create_func_body;
std::vector<std::string> create_func_header;
auto should_generate_create = struct_def.fields.vec.size() != 0;
code_.SetValue("NUMBEROFFIELDS", NumToString(struct_def.fields.vec.size()));
code_ +=
"\tpublic static func start{{STRUCTNAME}}(_ fbb: inout FlatBufferBuilder) -> "
"public static func start{{STRUCTNAME}}(_ fbb: inout "
"FlatBufferBuilder) -> "
"UOffset { fbb.startTable(with: {{NUMBEROFFIELDS}}) }";
for (auto it = struct_def.fields.vec.begin();
@@ -332,7 +382,8 @@ class SwiftGenerator : public BaseGenerator {
static_cast<int>(it - struct_def.fields.vec.begin()));
}
code_ +=
"\tpublic static func end{{STRUCTNAME}}(_ fbb: inout FlatBufferBuilder, "
"public static func end{{STRUCTNAME}}(_ fbb: inout "
"FlatBufferBuilder, "
"start: "
"UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: "
"fbb.endTable(at: start))\\";
@@ -345,29 +396,38 @@ class SwiftGenerator : public BaseGenerator {
}
code_ += "; return end }";
if (should_generate_create) {
code_ +=
"\tpublic static func create{{STRUCTNAME}}(_ fbb: inout FlatBufferBuilder\\";
if (should_generate_create)
code_ += ",\n" +
create_func_header.substr(0, create_func_header.size() - 2) +
"\\";
"public static func create{{STRUCTNAME}}(_ fbb: inout "
"FlatBufferBuilder,";
for (auto it = create_func_header.begin(); it < create_func_header.end();
++it) {
code_ += *it + "\\";
if (it < create_func_header.end() - 1) code_ += ",";
}
code_ += ") -> Offset<UOffset> {";
code_ += "\t\tlet __start = {{STRUCTNAME}}.start{{STRUCTNAME}}(&fbb)";
if (should_generate_create)
code_ += create_func_body.substr(0, create_func_body.size() - 1);
code_ += "\t\treturn {{STRUCTNAME}}.end{{STRUCTNAME}}(&fbb, start: __start)";
code_ += "\t}";
Indent();
code_ += "let __start = {{STRUCTNAME}}.start{{STRUCTNAME}}(&fbb)";
for (auto it = create_func_body.begin(); it < create_func_body.end();
++it) {
code_ += *it;
}
code_ += "return {{STRUCTNAME}}.end{{STRUCTNAME}}(&fbb, start: __start)";
Outdent();
code_ += "}";
}
std::string spacing = "\t\t";
std::string spacing = "";
if (key_field != nullptr && !struct_def.fixed && struct_def.has_key) {
code_.SetValue("VALUENAME", struct_def.name);
code_.SetValue("VOFFSET", NumToString(key_field->value.offset));
code_ +=
"\tpublic static func "
"public static func "
"sortVectorOf{{VALUENAME}}(offsets:[Offset<UOffset>], "
"_ fbb: inout FlatBufferBuilder) -> Offset<UOffset> {";
Indent();
code_ += spacing + "var off = offsets";
code_ +=
spacing +
@@ -375,13 +435,16 @@ class SwiftGenerator : public BaseGenerator {
"{{VOFFSET}}, fbb: fbb.buffer), Table.offset(Int32($0.o), vOffset: "
"{{VOFFSET}}, fbb: fbb.buffer), fbb: fbb.buffer) < 0 } ";
code_ += spacing + "return fbb.createVector(ofOffsets: off)";
code_ += "\t}";
Outdent();
code_ += "}";
GenLookup(*key_field);
}
}
void GenTableWriterFields(const FieldDef &field, std::string *create_body,
std::string *create_header, const int position) {
void GenTableWriterFields(const FieldDef &field,
std::vector<std::string> *create_body,
std::vector<std::string> *create_header,
const int position) {
std::string builder_string = ", _ fbb: inout FlatBufferBuilder) { fbb.add(";
auto &create_func_body = *create_body;
auto &create_func_header = *create_header;
@@ -396,10 +459,10 @@ class SwiftGenerator : public BaseGenerator {
field.value.type.base_type == BASE_TYPE_ARRAY)
? "VectorOf("
: "(";
std::string body = "add" + check_if_vector + name + ": ";
code_ += "\tpublic static func " + body + "\\";
auto body = "add" + check_if_vector + name + ": ";
code_ += "public static func " + body + "\\";
create_func_body += "\t\t{{STRUCTNAME}}." + body + name + ", &fbb)\n";
create_func_body.push_back("{{STRUCTNAME}}." + body + name + ", &fbb)");
if (IsScalar(field.value.type.base_type) &&
!IsBool(field.value.type.base_type)) {
@@ -408,8 +471,8 @@ class SwiftGenerator : public BaseGenerator {
auto is_enum = IsEnum(field.value.type) ? ".rawValue" : "";
code_ += "{{VALUETYPE}}" + builder_string + "element: {{VALUENAME}}" +
is_enum + ", def: {{CONSTANT}}, at: {{OFFSET}}) }";
create_func_header +=
"\t\t" + name + ": " + type + " = " + default_value + ",\n";
create_func_header.push_back("" + name + ": " + type + " = " +
default_value);
return;
}
@@ -420,8 +483,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("CONSTANT", default_value);
code_ += "{{VALUETYPE}}" + builder_string +
"condition: {{VALUENAME}}, def: {{CONSTANT}}, at: {{OFFSET}}) }";
create_func_header +=
"\t\t" + name + ": " + type + " = " + default_value + ",\n";
create_func_header.push_back(name + ": " + type + " = " + default_value);
return;
}
@@ -434,8 +496,8 @@ class SwiftGenerator : public BaseGenerator {
? "vectorOf"
: "offsetOf") +
MakeCamel(name, true);
create_func_header += "\t\t" + camel_case_name + " " + name + ": " +
offset_type + " = Offset(),\n";
create_func_header.push_back(camel_case_name + " " + name + ": " +
offset_type + " = Offset()");
auto reader_type =
IsStruct(field.value.type) && field.value.type.struct_def->fixed
? "structOffset: {{OFFSET}}) }"
@@ -452,7 +514,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("OFFSET", offset);
code_.SetValue("CONSTANT", field.value.constant);
std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
GenComment(field.doc_comment, "\t");
GenComment(field.doc_comment);
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
!IsBool(field.value.type.base_type)) {
code_ += GenReaderMainBody() + GenOffset() + const_string +
@@ -504,7 +566,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += GenReaderMainBody("?") + GenOffset() + const_string +
"{{ACCESS}}.string(at: o) }";
code_ +=
"\tpublic var {{VALUENAME}}SegmentArray: [UInt8]? { return "
"public var {{VALUENAME}}SegmentArray: [UInt8]? { return "
"{{ACCESS}}.getVector(at: {{OFFSET}}) }";
break;
@@ -515,7 +577,7 @@ class SwiftGenerator : public BaseGenerator {
case BASE_TYPE_UNION:
code_.SetValue("CONSTANT", "nil");
code_ +=
"\tpublic func {{VALUENAME}}<T: FlatBufferObject>(type: "
"public func {{VALUENAME}}<T: FlatBufferObject>(type: "
"T.Type) -> T? { " +
GenOffset() + const_string + "{{ACCESS}}.union(o) }";
break;
@@ -527,7 +589,7 @@ class SwiftGenerator : public BaseGenerator {
const std::string &const_string) {
auto vectortype = field.value.type.VectorType();
code_.SetValue("SIZE", NumToString(InlineSize(vectortype)));
code_ += "\tpublic var {{VALUENAME}}Count: Int32 { " + GenOffset() +
code_ += "public var {{VALUENAME}}Count: Int32 { " + GenOffset() +
const_string + "{{ACCESS}}.vector(count: o) }";
code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) == true
? field.value.constant
@@ -538,7 +600,7 @@ class SwiftGenerator : public BaseGenerator {
code_ += GenArrayMainBody(nullable) + GenOffset() + "\\";
} else {
code_ +=
"\tpublic func {{VALUENAME}}<T: FlatBufferObject>(at index: "
"public func {{VALUENAME}}<T: FlatBufferObject>(at index: "
"Int32, type: T.Type) -> T? { " +
GenOffset() + "\\";
}
@@ -557,7 +619,7 @@ class SwiftGenerator : public BaseGenerator {
"{{ACCESS}}.directRead(of: {{VALUETYPE}}.self, offset: "
"{{ACCESS}}.vector(at: o) + index * {{SIZE}}) }";
code_ +=
"\tpublic var {{VALUENAME}}: [{{VALUETYPE}}] { return "
"public var {{VALUENAME}}: [{{VALUETYPE}}] { return "
"{{ACCESS}}.getVector(at: {{OFFSET}}) ?? [] }";
if (parser_.opts.mutable_buffer) code_ += GenMutateArray();
return;
@@ -610,7 +672,7 @@ class SwiftGenerator : public BaseGenerator {
void GenByKeyFunctions(const FieldDef &key_field) {
code_.SetValue("TYPE", GenType(key_field.value.type));
code_ +=
"\tpublic func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? { \\";
"public func {{VALUENAME}}By(key: {{TYPE}}) -> {{VALUETYPE}}? { \\";
code_ += GenOffset() +
"return o == 0 ? nil : {{VALUETYPE}}.lookupByKey(vector: "
"{{ACCESS}}.vector(at: o), key: key, fbb: {{ACCESS}}.bb) }";
@@ -629,7 +691,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUENAME", name);
code_.SetValue("VALUETYPE", type);
code_.SetValue("OFFSET", offset);
GenComment(field.doc_comment, "\t");
GenComment(field.doc_comment);
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
code_ +=
GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
@@ -645,7 +707,9 @@ class SwiftGenerator : public BaseGenerator {
GenConstructor("{{ACCESS}}.postion + {{OFFSET}}");
}
}
if (parser_.opts.generate_object_based_api)
GenerateObjectAPIStructExtension(struct_def);
Outdent();
code_ += "}\n";
}
@@ -655,26 +719,412 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
GenComment(enum_def.doc_comment);
code_ += "public enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum { ";
code_ += "\tpublic typealias T = {{BASE_TYPE}}";
Indent();
code_ += "public typealias T = {{BASE_TYPE}}";
code_ +=
"\tpublic static var byteSize: Int { return "
"public static var byteSize: Int { return "
"MemoryLayout<{{BASE_TYPE}}>.size "
"}";
code_ += "\tpublic var value: {{BASE_TYPE}} { return self.rawValue }";
code_ += "public var value: {{BASE_TYPE}} { return self.rawValue }";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
const auto &ev = **it;
auto name = Name(ev);
std::transform(name.begin(), name.end(), name.begin(), LowerCase);
code_.SetValue("KEY", name);
code_.SetValue("VALUE", enum_def.ToString(ev));
GenComment(ev.doc_comment, "\t");
code_ += "\tcase {{KEY}} = {{VALUE}}";
GenComment(ev.doc_comment);
code_ += "case {{KEY}} = {{VALUE}}";
}
code_ += "\n";
AddMinOrMaxEnumValue(enum_def.MaxValue()->name, "max");
AddMinOrMaxEnumValue(enum_def.MinValue()->name, "min");
Outdent();
code_ += "}\n";
if (parser_.opts.generate_object_based_api && enum_def.is_union) {
code_ += "struct {{ENUM_NAME}}Union {";
Indent();
code_ += "var type: {{ENUM_NAME}}";
code_ += "var value: NativeTable?";
code_ += "init(_ v: NativeTable?, type: {{ENUM_NAME}}) {";
Indent();
code_ += "self.type = type";
code_ += "self.value = v";
Outdent();
code_ += "}";
code_ +=
"func pack(builder: inout FlatBufferBuilder) -> Offset<UOffset> {";
Indent();
BuildUnionEnumSwitchCaseWritter(enum_def);
Outdent();
code_ += "}";
Outdent();
code_ += "}";
}
}
void GenObjectAPI(const StructDef &struct_def) {
code_ += "public class {{STRUCTNAME}}T: NativeTable {\n";
std::vector<std::string> buffer_constructor;
std::vector<std::string> base_constructor;
Indent();
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
BuildObjectAPIConstructorBody(field, struct_def.fixed, buffer_constructor,
base_constructor);
}
code_ += "";
BuildObjectAPIConstructor(buffer_constructor,
"_ _t: inout " + struct_def.name);
BuildObjectAPIConstructor(base_constructor);
Outdent();
code_ += "}";
}
void GenerateObjectAPITableExtension(const StructDef &struct_def) {
GenerateObjectAPIExtensionHeader();
std::vector<std::string> unpack_body;
std::string builder = ", &builder)";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto name = Name(field);
auto type = GenType(field.value.type);
std::string check_if_vector =
(field.value.type.base_type == BASE_TYPE_VECTOR ||
field.value.type.base_type == BASE_TYPE_ARRAY)
? "VectorOf("
: "(";
std::string body = "add" + check_if_vector + name + ": ";
switch (field.value.type.base_type) {
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
GenerateVectorObjectAPITableExtension(field, name, type);
unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
builder);
break;
}
case BASE_TYPE_UNION: {
code_ += "let __" + name + " = obj." + name +
"?.pack(builder: &builder) ?? Offset()";
unpack_body.push_back("if let o = obj." + name + "?.type {");
unpack_body.push_back(" {{STRUCTNAME}}.add(" + name + "Type: o" +
builder);
unpack_body.push_back(" {{STRUCTNAME}}." + body + "__" + name +
builder);
unpack_body.push_back("}\n");
break;
}
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def &&
field.value.type.struct_def->fixed) {
std::string struct_builder =
type + ".pack(&builder, obj: &obj." + name + ")";
unpack_body.push_back("{{STRUCTNAME}}." + body + struct_builder +
builder);
} else {
unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
builder);
code_ += "let __" + name + " = " + type +
".pack(&builder, obj: &obj." + name + ")";
}
break;
}
case BASE_TYPE_STRING: {
unpack_body.push_back("{{STRUCTNAME}}." + body + "__" + name +
builder);
BuildingOptionalObjects(name, "String", "builder.create(string: s)");
break;
}
case BASE_TYPE_UTYPE: break;
default:
unpack_body.push_back("{{STRUCTNAME}}." + body + "obj." + name +
builder);
}
}
code_ += "let __root = {{STRUCTNAME}}.start{{STRUCTNAME}}(&builder)";
for (auto it = unpack_body.begin(); it < unpack_body.end(); it++)
code_ += *it;
code_ +=
"return {{STRUCTNAME}}.end{{STRUCTNAME}}(&builder, start: "
"__root)";
Outdent();
code_ += "}";
}
void GenerateVectorObjectAPITableExtension(const FieldDef &field,
const std::string &name,
const std::string &type) {
auto vectortype = field.value.type.VectorType();
switch (vectortype.base_type) {
case BASE_TYPE_UNION: {
code_ += "var __" + name + "__: [Offset<UOffset>] = []";
code_ += "for i in obj." + name + " {";
Indent();
code_ += "guard let off = i?.pack(builder: &builder) else { continue }";
code_ += "__" + name + "__.append(off)";
Outdent();
code_ += "}";
code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
name + "__)";
code_ += "let __" + name + "Type = builder.createVector(obj." + name +
".compactMap { $0?.type })";
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def &&
!field.value.type.struct_def->fixed) {
code_ += "var __" + name + "__: [Offset<UOffset>] = []";
code_ += "for var i in obj." + name + " {";
Indent();
code_ +=
"__" + name + "__.append(" + type + ".pack(&builder, obj: &i))";
Outdent();
code_ += "}";
code_ += "let __" + name + " = builder.createVector(ofOffsets: __" +
name + "__)";
} else {
code_ += "var __" + name + "__: [UnsafeMutableRawPointer] = []";
std::string code;
GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "_o",
true);
code = code.substr(0, code.size() - 2);
code_ += "for i in obj." + name + " {";
Indent();
code_ += "guard let _o = i else { continue }";
code_ += "__" + name + "__.append(create" +
field.value.type.struct_def->name + "(" + code + "))";
Outdent();
code_ += "}";
code_ += "let __" + name + " = builder.createVector(structs: __" +
name + "__, type: " + type + ".self)";
}
break;
}
case BASE_TYPE_STRING: {
code_ += "let __" + name + " = builder.createVector(ofStrings: obj." +
name + ".compactMap({ $0 }) )";
break;
}
default: {
code_ += "let __" + name + " = builder.createVector(obj." + name + ")";
break;
}
}
}
void BuildingOptionalObjects(const std::string &name,
const std::string &object_type,
const std::string &body_front) {
code_ += "let __" + name + ": Offset<" + object_type + ">";
code_ += "if let s = obj." + name + " {";
Indent();
code_ += "__" + name + " = " + body_front;
Outdent();
code_ += "} else {";
Indent();
code_ += "__" + name + " = Offset<" + object_type + ">()";
Outdent();
code_ += "}";
code_ += "";
}
void BuildObjectAPIConstructor(const std::vector<std::string> &body,
const std::string &header = "") {
code_.SetValue("HEADER", header);
code_ += "init({{HEADER}}) {";
Indent();
for (auto it = body.begin(); it < body.end(); ++it) code_ += *it;
Outdent();
code_ += "}\n";
}
void BuildObjectAPIConstructorBody(
const FieldDef &field, bool is_fixed,
std::vector<std::string> &buffer_constructor,
std::vector<std::string> &base_constructor) {
auto name = Name(field);
auto type = GenType(field.value.type);
code_.SetValue("VALUENAME", name);
code_.SetValue("VALUETYPE", type);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
code_.SetValue("VALUETYPE", type + "T");
buffer_constructor.push_back("var __" + name + " = _t." + name);
auto optional =
(field.value.type.struct_def && field.value.type.struct_def->fixed);
std::string question_mark = (optional && is_fixed ? "" : "?");
code_ += "var {{VALUENAME}}: {{VALUETYPE}}" + question_mark;
buffer_constructor.push_back("" + name + " = __" + name +
question_mark + ".unpack()");
base_constructor.push_back("" + name + " = " + type + "T()");
break;
}
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
BuildObjectAPIConstructorBodyVectors(field, name, buffer_constructor,
base_constructor, " ");
break;
}
case BASE_TYPE_STRING: {
code_ += "var {{VALUENAME}}: String?";
buffer_constructor.push_back(name + " = _t." + name);
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
buffer_constructor);
break;
}
default: {
buffer_constructor.push_back(name + " = _t." + name);
if (IsScalar(field.value.type.base_type) &&
!IsBool(field.value.type.base_type) && !IsEnum(field.value.type)) {
code_ += "var {{VALUENAME}}: {{VALUETYPE}}";
base_constructor.push_back(name + " = " + field.value.constant);
break;
}
if (IsEnum(field.value.type)) {
auto default_value = IsEnum(field.value.type)
? GenEnumDefaultValue(field)
: field.value.constant;
code_ += "var {{VALUENAME}}: {{VALUETYPE}}";
base_constructor.push_back(name + " = " + default_value);
break;
}
if (IsBool(field.value.type.base_type)) {
code_ += "var {{VALUENAME}}: Bool";
std::string default_value =
"0" == field.value.constant ? "false" : "true";
base_constructor.push_back(name + " = " + default_value);
}
}
}
}
void BuildObjectAPIConstructorBodyVectors(
const FieldDef &field, const std::string &name,
std::vector<std::string> &buffer_constructor,
std::vector<std::string> &base_constructor,
const std::string &indentation) {
auto vectortype = field.value.type.VectorType();
if (vectortype.base_type != BASE_TYPE_UTYPE) {
buffer_constructor.push_back(name + " = []");
buffer_constructor.push_back("for index in 0..<_t." + name + "Count {");
base_constructor.push_back(name + " = []");
}
switch (vectortype.base_type) {
case BASE_TYPE_STRUCT: {
code_.SetValue("VALUETYPE", GenType(vectortype) + "T");
code_ += "var {{VALUENAME}}: [{{VALUETYPE}}?]";
buffer_constructor.push_back(indentation + "var __v_ = _t." + name +
"(at: index)");
buffer_constructor.push_back(indentation + name +
".append(__v_?.unpack())");
break;
}
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH();
case BASE_TYPE_VECTOR: {
break;
}
case BASE_TYPE_UNION: {
BuildUnionEnumSwitchCase(*field.value.type.enum_def, name,
buffer_constructor, indentation, true);
break;
}
case BASE_TYPE_UTYPE: break;
default: {
code_.SetValue("VALUETYPE", (vectortype.base_type == BASE_TYPE_STRING
? "String?"
: GenType(vectortype)));
code_ += "var {{VALUENAME}}: [{{VALUETYPE}}]";
if (IsEnum(vectortype) && vectortype.base_type != BASE_TYPE_UNION) {
auto default_value = IsEnum(field.value.type)
? GenEnumDefaultValue(field)
: field.value.constant;
buffer_constructor.push_back(indentation + name + ".append(_t." +
name + "(at: index)!)");
break;
}
buffer_constructor.push_back(indentation + name + ".append(_t." + name +
"(at: index))");
break;
}
}
if (vectortype.base_type != BASE_TYPE_UTYPE)
buffer_constructor.push_back("}");
}
void BuildUnionEnumSwitchCaseWritter(const EnumDef &ev) {
auto field_name = EscapeKeyword(ev.name);
code_.SetValue("VALUETYPE", field_name);
code_ += "switch type {";
for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
auto field = **it;
auto ev_name = Name(field);
auto type = GenType(field.union_type);
std::transform(ev_name.begin(), ev_name.end(), ev_name.begin(),
LowerCase);
if (field.union_type.base_type == BASE_TYPE_NONE ||
field.union_type.base_type == BASE_TYPE_STRING) {
continue;
}
code_ += "case ." + ev_name + ":";
Indent();
code_ += "var __obj = value as? " + type + "T";
code_ += "return " + type + ".pack(&builder, obj: &__obj)";
Outdent();
}
code_ += "default: return Offset()";
code_ += "}";
}
void BuildUnionEnumSwitchCase(const EnumDef &ev, const std::string &name,
std::vector<std::string> &buffer_constructor,
const std::string &indentation = "",
const bool is_vector = false) {
auto field_name = EscapeKeyword(ev.name);
code_.SetValue("VALUETYPE", field_name);
code_ += "var {{VALUENAME}}: \\";
code_ += is_vector ? "[{{VALUETYPE}}Union?]" : "{{VALUETYPE}}Union?";
auto vector_reader = is_vector ? "(at: index" : "";
buffer_constructor.push_back(indentation + "switch _t." + name + "Type" +
vector_reader + (is_vector ? ")" : "") + " {");
for (auto it = ev.Vals().begin(); it < ev.Vals().end(); ++it) {
auto field = **it;
auto ev_name = Name(field);
std::transform(ev_name.begin(), ev_name.end(), ev_name.begin(),
LowerCase);
if (field.union_type.base_type == BASE_TYPE_NONE ||
field.union_type.base_type == BASE_TYPE_STRING) {
continue;
}
buffer_constructor.push_back(indentation + "case ." + ev_name + ":");
buffer_constructor.push_back(
indentation + " var _v = _t." + name + (is_vector ? "" : "(") +
vector_reader + (is_vector ? ", " : "") +
"type: " + GenType(field.union_type) + ".self)");
auto constructor =
field_name + "Union(_v?.unpack(), type: ." + ev_name + ")";
buffer_constructor.push_back(
indentation + " " + name +
(is_vector ? ".append(" + constructor + ")" : " = " + constructor));
}
buffer_constructor.push_back(indentation + "default: break");
buffer_constructor.push_back(indentation + "}");
}
void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
@@ -682,67 +1132,72 @@ class SwiftGenerator : public BaseGenerator {
std::transform(current_value.begin(), current_value.end(),
current_value.begin(), LowerCase);
code_.SetValue(type, current_value);
code_ += "\tpublic static var " + type + ": {{ENUM_NAME}} { return .{{" +
code_ += "public static var " + type + ": {{ENUM_NAME}} { return .{{" +
type + "}} }";
}
void GenLookup(const FieldDef &key_field) {
code_.SetValue("OFFSET", NumToString(key_field.value.offset));
auto offset_reader =
std::string offset_reader =
"Table.offset(Int32(fbb.capacity) - tableOffset, vOffset: {{OFFSET}}, "
"fbb: fbb)";
std::string spacing = "\t\t";
std::string double_spacing = spacing + "\t";
code_.SetValue("TYPE", GenType(key_field.value.type));
code_ +=
"\tfileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
"fileprivate static func lookupByKey(vector: Int32, key: {{TYPE}}, "
"fbb: "
"ByteBuffer) -> {{VALUENAME}}? {";
Indent();
if (key_field.value.type.base_type == BASE_TYPE_STRING)
code_ += spacing + "let key = key.utf8.map { $0 }";
code_ += spacing +
"var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
code_ += spacing + "var start: Int32 = 0";
code_ += spacing + "while span != 0 {";
code_ += double_spacing + "var middle = span / 2";
code_ += "let key = key.utf8.map { $0 }";
code_ += "var span = fbb.read(def: Int32.self, position: Int(vector - 4))";
code_ += "var start: Int32 = 0";
code_ += "while span != 0 {";
Indent();
code_ += "var middle = span / 2";
code_ +=
double_spacing +
"let tableOffset = Table.indirect(vector + 4 * (start + middle), fbb)";
if (key_field.value.type.base_type == BASE_TYPE_STRING) {
code_ += double_spacing + "let comp = Table.compare(" + offset_reader +
", key, fbb: fbb)";
code_ += "let comp = Table.compare(" + offset_reader + ", key, fbb: fbb)";
} else {
code_ += double_spacing +
"let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
code_ += "let comp = fbb.read(def: {{TYPE}}.self, position: Int(" +
offset_reader + "))";
}
code_ += double_spacing + "if comp > 0 {";
code_ += double_spacing + "\tspan = middle";
code_ += double_spacing + "} else if comp < 0 {";
code_ += double_spacing + "\tmiddle += 1";
code_ += double_spacing + "\tstart += middle";
code_ += double_spacing + "\tspan -= middle";
code_ += double_spacing + "} else {";
code_ += double_spacing + "\treturn {{VALUENAME}}(fbb, o: tableOffset)";
code_ += double_spacing + "}";
code_ += spacing + "}";
code_ += spacing + "return nil";
code_ += "\t}";
code_ += "if comp > 0 {";
Indent();
code_ += "span = middle";
Outdent();
code_ += "} else if comp < 0 {";
Indent();
code_ += "middle += 1";
code_ += "start += middle";
code_ += "span -= middle";
Outdent();
code_ += "} else {";
Indent();
code_ += "return {{VALUENAME}}(fbb, o: tableOffset)";
Outdent();
code_ += "}";
Outdent();
code_ += "}";
code_ += "return nil";
Outdent();
code_ += "}";
}
void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
std::string text;
::flatbuffers::GenComment(dc, &text, nullptr, prefix);
code_ += text + "\\";
void GenComment(const std::vector<std::string> &dc) {
if (dc.begin() == dc.end()) {
// Don't output empty comment blocks with 0 lines of comment content.
return;
}
for (auto it = dc.begin(); it != dc.end(); ++it) { code_ += "/// " + *it; }
}
std::string GenOffset() { return "let o = {{ACCESS}}.offset({{OFFSET}}); "; }
std::string GenReaderMainBody(const std::string &optional = "") {
return "\tpublic var {{VALUENAME}}: {{VALUETYPE}}" + optional + " { ";
return "public var {{VALUENAME}}: {{VALUETYPE}}" + optional + " { ";
}
std::string GenReader(const std::string &type,
@@ -756,13 +1211,13 @@ class SwiftGenerator : public BaseGenerator {
std::string GenMutate(const std::string &offset,
const std::string &get_offset, bool isRaw = false) {
return "\tpublic func mutate({{VALUENAME}}: {{VALUETYPE}}) -> Bool {" +
return "public func mutate({{VALUENAME}}: {{VALUETYPE}}) -> Bool {" +
get_offset + " return {{ACCESS}}.mutate({{VALUENAME}}" +
(isRaw ? ".rawValue" : "") + ", index: " + offset + ") }";
}
std::string GenMutateArray() {
return "\tpublic func mutate({{VALUENAME}}: {{VALUETYPE}}, at index: "
return "public func mutate({{VALUENAME}}: {{VALUETYPE}}, at index: "
"Int32) -> Bool { " +
GenOffset() +
"return {{ACCESS}}.directMutate({{VALUENAME}}, index: "
@@ -790,7 +1245,7 @@ class SwiftGenerator : public BaseGenerator {
}
std::string ValidateFunc() {
return "\tstatic func validateVersion() { FlatBuffersVersion_1_12_0() }";
return "static func validateVersion() { FlatBuffersVersion_1_12_0() }";
}
std::string GenType(const Type &type) const {
@@ -814,6 +1269,10 @@ class SwiftGenerator : public BaseGenerator {
return GenTypeBasic(type, true);
}
void Indent() { code_.IncrementIdentLevel(); }
void Outdent() { code_.DecrementIdentLevel(); }
std::string GenTypeBasic(const Type &type, bool can_override) const {
// clang-format off
static const char * const swift_type[] = {
@@ -863,7 +1322,7 @@ class SwiftGenerator : public BaseGenerator {
// Close cur_name_space in reverse order to reach the common prefix.
// In the previous example, D then C are closed.
for (size_t j = old_size; j > common_prefix_size; --j) {
if (namespace_depth != 0) {
if (namespace_depth >= 0) {
code_ += "}";
namespace_depth -= 1;
}
@@ -881,7 +1340,10 @@ class SwiftGenerator : public BaseGenerator {
namespace_depth += 1;
namespaces_.insert(name);
} else {
if (namespace_depth != 0) {
code_ += "}";
namespace_depth = 0;
}
is_extension = true;
}
}

View File

@@ -132,6 +132,16 @@ public struct ByteBuffer {
}
}
///Adds an array of type Bool to the buffer memory
/// - Parameter elements: An array of Bool
@usableFromInline mutating func push(elements: [Bool]) {
let size = elements.count * MemoryLayout<Bool>.size
ensureSpace(size: UInt32(size))
elements.lazy.reversed().forEach { (s) in
push(value: s ? 1 : 0, len: MemoryLayout.size(ofValue: s))
}
}
/// A custom type of structs that are padded according to the flatbuffer padding,
/// - Parameters:
/// - value: Pointer to the object in memory
@@ -174,8 +184,6 @@ public struct ByteBuffer {
/// - len: Size of string
@usableFromInline mutating internal func push(bytes: UnsafeBufferPointer<String.UTF8View.Element>, len: Int) -> Bool {
memcpy(_storage.memory.advanced(by: writerIndex - len), UnsafeRawPointer(bytes.baseAddress!), len)
// _memory.advanced(by: writerIndex - len).copyMemory(from:
// UnsafeRawPointer(bytes.baseAddress!), byteCount: len)
_writerSize += len
return true
}

View File

@@ -53,7 +53,7 @@ public struct FlatBufferBuilder {
/// Returns A sized Buffer from the readable bytes
public var sizedBuffer: ByteBuffer {
assert(finished, "Data shouldn't be called before finish()")
return ByteBuffer(memory: _bb.memory.advanced(by: _bb.reader), count: _bb.reader)
return ByteBuffer(memory: _bb.memory.advanced(by: _bb.reader), count: Int(_bb.size))
}
// MARK: - Init
@@ -276,6 +276,24 @@ public struct FlatBufferBuilder {
return push(element: Int32(len))
}
/// Creates a vector of type Bool in the buffer
/// - Parameter elements: elements to be written into the buffer
/// - returns: Offset of the vector
mutating public func createVector(_ elements: [Bool]) -> Offset<UOffset> {
return createVector(elements, size: elements.count)
}
/// Creates a vector of type Bool in the buffer
/// - Parameter elements: Elements to be written into the buffer
/// - Parameter size: Count of elements
/// - returns: Offset of the vector
mutating public func createVector(_ elements: [Bool], size: Int) -> Offset<UOffset> {
let size = size
startVector(size, elementSize: MemoryLayout<Bool>.size)
_bb.push(elements: elements)
return Offset(offset: endVector(len: size))
}
/// Creates a vector of type Scalar in the buffer
/// - Parameter elements: elements to be written into the buffer
/// - returns: Offset of the vector

View File

@@ -6,6 +6,14 @@ public protocol FlatBufferObject {
init(_ bb: ByteBuffer, o: Int32)
}
public protocol NativeTable {}
public protocol ObjectAPI {
associatedtype T
static func pack(_ builder: inout FlatBufferBuilder, obj: inout T) -> Offset<UOffset>
mutating func unpack() -> T
}
/// Readable is structures all the Flatbuffers structs
///
/// Readable is a procotol that each Flatbuffer struct should confirm to since

View File

@@ -6,8 +6,8 @@ public struct HelloReply: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func getRootAsHelloReply(bb: ByteBuffer) -> HelloReply { return HelloReply(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -30,8 +30,8 @@ public struct HelloRequest: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func getRootAsHelloRequest(bb: ByteBuffer) -> HelloRequest { return HelloRequest(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }
@@ -54,8 +54,8 @@ public struct ManyHellosRequest: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func getRootAsManyHellosRequest(bb: ByteBuffer) -> ManyHellosRequest { return ManyHellosRequest(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
private init(_ t: Table) { _accessor = t }

View File

@@ -13,6 +13,7 @@ let package = Package(
.package(path: "../../swift/")
],
targets: [
.target(name: "SwiftFlatBuffers"),
.testTarget(
name: "FlatBuffers.Test.SwiftTests",
dependencies: ["FlatBuffers"]),

View File

@@ -0,0 +1,2 @@
import Foundation
print("Flatbuffers")

View File

@@ -2,7 +2,7 @@ swift_dir=`pwd`
cd ..
test_dir=`pwd`
${test_dir}/../flatc --swift --gen-mutable -I ${test_dir}/include_test ${test_dir}/monster_test.fbs ${test_dir}/union_vector/union_vector.fbs
${test_dir}/../flatc --swift --gen-mutable --gen-object-api -I ${test_dir}/include_test ${test_dir}/monster_test.fbs ${test_dir}/union_vector/union_vector.fbs
cd ${test_dir}
mv *_generated.swift ${swift_dir}/Tests/FlatBuffers.Test.SwiftTests
cd ${swift_dir}

View File

@@ -33,7 +33,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
func testCreateMonsterResizedBuffer() {
let bytes = createMonster(withPrefix: false)
XCTAssertEqual(bytes.sizedByteArray, [48, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 36, 0, 72, 0, 40, 0, 0, 0, 38, 0, 32, 0, 0, 0, 28, 0, 0, 0, 27, 0, 20, 0, 16, 0, 12, 0, 4, 0, 0, 0, 0, 0, 0, 0, 11, 0, 36, 0, 0, 0, 164, 0, 0, 0, 0, 0, 0, 1, 60, 0, 0, 0, 68, 0, 0, 0, 76, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 120, 0, 0, 0, 0, 0, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 2, 0, 0, 0, 64, 0, 0, 0, 48, 0, 0, 0, 2, 0, 0, 0, 30, 0, 40, 0, 10, 0, 20, 0, 152, 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 49, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0, 3, 0, 0, 0, 20, 0, 0, 0, 36, 0, 0, 0, 4, 0, 0, 0, 240, 255, 255, 255, 32, 0, 0, 0, 248, 255, 255, 255, 36, 0, 0, 0, 12, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 12, 0, 0, 0, 28, 0, 0, 0, 5, 0, 0, 0, 87, 105, 108, 109, 97, 0, 0, 0, 6, 0, 0, 0, 66, 97, 114, 110, 101, 121, 0, 0, 5, 0, 0, 0, 70, 114, 111, 100, 111, 0, 0, 0])
readMonster(fb: ByteBuffer(data: bytes.data))
readMonster(fb: bytes.sizedBuffer)
}
func testCreateMonsterPrefixed() {
@@ -44,6 +44,18 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
readMonster(fb: newBuf)
}
func readMonster(fb: ByteBuffer) {
var monster = Monster1.getRootAsMonster(bb: fb)
readFlatbufferMonster(monster: &monster)
var unpacked: MyGame.Example.MonsterT? = monster.unpack()
readObjectApi(monster: unpacked!)
var builder = FlatBufferBuilder()
let root = Monster1.pack(&builder, obj: &unpacked)
builder.finish(offset: root)
var newMonster = Monster1.getRootAsMonster(bb: builder.sizedBuffer)
readFlatbufferMonster(monster: &newMonster)
}
func createMonster(withPrefix prefix: Bool) -> FlatBufferBuilder {
var fbb = FlatBufferBuilder(initialSize: 1)
let names = [fbb.create(string: "Frodo"), fbb.create(string: "Barney"), fbb.create(string: "Wilma")]
@@ -134,8 +146,7 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
XCTAssertTrue(vec?.mutate(test1: 3) ?? false)
}
func readMonster(fb: ByteBuffer) {
let monster = Monster1.getRootAsMonster(bb: fb)
func readFlatbufferMonster(monster: inout MyGame.Example.Monster) {
XCTAssertEqual(monster.hp, 80)
XCTAssertEqual(monster.mana, 150)
XCTAssertEqual(monster.name, "MyMonster")
@@ -187,4 +198,46 @@ class FlatBuffersMonsterWriterTests: XCTestCase {
XCTAssertEqual(monster.testarrayofbools.isEmpty, false)
}
}
func readObjectApi(monster: MyGame.Example.MonsterT) {
XCTAssertEqual(monster.hp, 80)
XCTAssertEqual(monster.mana, 150)
XCTAssertEqual(monster.name, "MyMonster")
let pos = monster.pos
XCTAssertEqual(pos?.x, 1)
XCTAssertEqual(pos?.y, 2)
XCTAssertEqual(pos?.z, 3)
XCTAssertEqual(pos?.test1, 3)
XCTAssertEqual(pos?.test2, .green)
let test = pos?.test3
XCTAssertEqual(test?.a, 5)
XCTAssertEqual(test?.b, 6)
let monster2 = monster.test?.value as? MyGame.Example.MonsterT
XCTAssertEqual(monster2?.name, "Fred")
XCTAssertEqual(monster.mana, 150)
monster.mana = 10
XCTAssertEqual(monster.mana, 10)
monster.mana = 150
XCTAssertEqual(monster.mana, 150)
XCTAssertEqual(monster.inventory.count, 5)
var sum: Byte = 0
for i in monster.inventory {
sum += i
}
XCTAssertEqual(sum, 10)
XCTAssertEqual(monster.test4.count, 2)
let test0 = monster.test4[0]
let test1 = monster.test4[1]
var sum0 = 0
var sum1 = 0
if let a = test0?.a, let b = test0?.b {
sum0 = Int(a) + Int(b)
}
if let a = test1?.a, let b = test1?.b {
sum1 = Int(a) + Int(b)
}
XCTAssertEqual(sum0 + sum1, 100)
XCTAssertEqual(monster.testbool, true)
}
}

View File

@@ -91,7 +91,7 @@ final class FlatBuffersUnionTests: XCTestCase {
let end = Movie.createMovie(&fb, vectorOfCharactersType: types, vectorOfCharacters: characterVector)
Movie.finish(&fb, end: end)
let movie = Movie.getRootAsMovie(bb: fb.buffer)
var movie = Movie.getRootAsMovie(bb: fb.buffer)
XCTAssertEqual(movie.charactersTypeCount, Int32(characterType.count))
XCTAssertEqual(movie.charactersCount, Int32(characters.count))
@@ -102,6 +102,19 @@ final class FlatBuffersUnionTests: XCTestCase {
XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, 7)
XCTAssertEqual(movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, swordDmg)
XCTAssertEqual(movie.characters(at: 2, type: BookReader.self)?.booksRead, 2)
var objc: MovieT? = movie.unpack()
XCTAssertEqual(movie.charactersTypeCount, Int32(objc?.characters.count ?? 0))
XCTAssertEqual(movie.characters(at: 0, type: BookReader.self)?.booksRead, (objc?.characters[0]?.value as? BookReaderT)?.booksRead)
fb.clear()
let newMovie = Movie.pack(&fb, obj: &objc)
fb.finish(offset: newMovie)
let packedMovie = Movie.getRootAsMovie(bb: fb.buffer)
XCTAssertEqual(packedMovie.characters(at: 0, type: BookReader.self)?.booksRead, movie.characters(at: 0, type: BookReader.self)?.booksRead)
XCTAssertEqual(packedMovie.characters(at: 1, type: Attacker.self)?.swordAttackDamage, movie.characters(at: 1, type: Attacker.self)?.swordAttackDamage)
XCTAssertEqual(packedMovie.characters(at: 2, type: BookReader.self)?.booksRead, movie.characters(at: 2, type: BookReader.self)?.booksRead)
}
}

View File

@@ -50,6 +50,28 @@ public enum Any_: UInt8, Enum {
public static var min: Any_ { return .none }
}
struct Any_Union {
var type: Any_
var value: NativeTable?
init(_ v: NativeTable?, type: Any_) {
self.type = type
self.value = v
}
func pack(builder: inout FlatBufferBuilder) -> Offset<UOffset> {
switch type {
case .monster:
var __obj = value as? MyGame.Example.MonsterT
return MyGame.Example.Monster.pack(&builder, obj: &__obj)
case .testsimpletablewithenum:
var __obj = value as? MyGame.Example.TestSimpleTableWithEnumT
return MyGame.Example.TestSimpleTableWithEnum.pack(&builder, obj: &__obj)
case .mygame_example2_monster:
var __obj = value as? MyGame.Example2.MonsterT
return MyGame.Example2.Monster.pack(&builder, obj: &__obj)
default: return Offset()
}
}
}
public enum AnyUniqueAliases: UInt8, Enum {
public typealias T = UInt8
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
@@ -64,6 +86,28 @@ public enum AnyUniqueAliases: UInt8, Enum {
public static var min: AnyUniqueAliases { return .none }
}
struct AnyUniqueAliasesUnion {
var type: AnyUniqueAliases
var value: NativeTable?
init(_ v: NativeTable?, type: AnyUniqueAliases) {
self.type = type
self.value = v
}
func pack(builder: inout FlatBufferBuilder) -> Offset<UOffset> {
switch type {
case .m:
var __obj = value as? MyGame.Example.MonsterT
return MyGame.Example.Monster.pack(&builder, obj: &__obj)
case .ts:
var __obj = value as? MyGame.Example.TestSimpleTableWithEnumT
return MyGame.Example.TestSimpleTableWithEnum.pack(&builder, obj: &__obj)
case .m2:
var __obj = value as? MyGame.Example2.MonsterT
return MyGame.Example2.Monster.pack(&builder, obj: &__obj)
default: return Offset()
}
}
}
public enum AnyAmbiguousAliases: UInt8, Enum {
public typealias T = UInt8
public static var byteSize: Int { return MemoryLayout<UInt8>.size }
@@ -78,12 +122,34 @@ public enum AnyAmbiguousAliases: UInt8, Enum {
public static var min: AnyAmbiguousAliases { return .none }
}
struct AnyAmbiguousAliasesUnion {
var type: AnyAmbiguousAliases
var value: NativeTable?
init(_ v: NativeTable?, type: AnyAmbiguousAliases) {
self.type = type
self.value = v
}
func pack(builder: inout FlatBufferBuilder) -> Offset<UOffset> {
switch type {
case .m1:
var __obj = value as? MyGame.Example.MonsterT
return MyGame.Example.Monster.pack(&builder, obj: &__obj)
case .m2:
var __obj = value as? MyGame.Example.MonsterT
return MyGame.Example.Monster.pack(&builder, obj: &__obj)
case .m3:
var __obj = value as? MyGame.Example.MonsterT
return MyGame.Example.Monster.pack(&builder, obj: &__obj)
default: return Offset()
}
}
}
public struct Test: Readable {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct
public static var size = 4
public static var alignment = 2
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
@@ -92,14 +158,40 @@ public struct Test: Readable {
public func mutate(a: Int16) -> Bool { return _accessor.mutate(a, index: 0) }
public var b: Int8 { return _accessor.readBuffer(of: Int8.self, at: 2) }
public func mutate(b: Int8) -> Bool { return _accessor.mutate(b, index: 2) }
public mutating func unpack() -> TestT {
return TestT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout TestT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
return builder.create(struct: createTest(a: obj.a, b: obj.b), type: Test.self)
}
}
public class TestT: NativeTable {
var a: Int16
var b: Int8
init(_ _t: inout Test) {
a = _t.a
b = _t.b
}
init() {
a = 0
b = 0
}
}
public struct Vec3: Readable {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct
public static var size = 32
public static var alignment = 8
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
@@ -114,14 +206,53 @@ public struct Vec3: Readable {
public func mutate(test1: Double) -> Bool { return _accessor.mutate(test1, index: 16) }
public var test2: MyGame.Example.Color { return MyGame.Example.Color(rawValue: _accessor.readBuffer(of: UInt8.self, at: 24)) ?? .red }
public var test3: MyGame.Example.Test { return MyGame.Example.Test(_accessor.bb, o: _accessor.postion + 26) }
public mutating func unpack() -> Vec3T {
return Vec3T(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout Vec3T?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
return builder.create(struct: createVec3(x: obj.x, y: obj.y, z: obj.z, test1: obj.test1, test2: obj.test2, test3a: obj.test3.a, test3b: obj.test3.b), type: Vec3.self)
}
}
public class Vec3T: NativeTable {
var x: Float32
var y: Float32
var z: Float32
var test1: Double
var test2: MyGame.Example.Color
var test3: MyGame.Example.TestT
init(_ _t: inout Vec3) {
x = _t.x
y = _t.y
z = _t.z
test1 = _t.test1
test2 = _t.test2
var __test3 = _t.test3
test3 = __test3.unpack()
}
init() {
x = 0.0
y = 0.0
z = 0.0
test1 = 0.0
test2 = .red
test3 = MyGame.Example.TestT()
}
}
public struct Ability: Readable {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct
public static var size = 8
public static var alignment = 4
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
@@ -130,8 +261,34 @@ public struct Ability: Readable {
public func mutate(id: UInt32) -> Bool { return _accessor.mutate(id, index: 0) }
public var distance: UInt32 { return _accessor.readBuffer(of: UInt32.self, at: 4) }
public func mutate(distance: UInt32) -> Bool { return _accessor.mutate(distance, index: 4) }
public mutating func unpack() -> AbilityT {
return AbilityT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout AbilityT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
return builder.create(struct: createAbility(id: obj.id, distance: obj.distance), type: Ability.self)
}
}
public class AbilityT: NativeTable {
var id: UInt32
var distance: UInt32
init(_ _t: inout Ability) {
id = _t.id
distance = _t.distance
}
init() {
id = 0
distance = 0
}
}
public static func createTest(a: Int16, b: Int8) -> UnsafeMutableRawPointer {
let memory = UnsafeMutableRawPointer.allocate(byteCount: Test.size, alignment: Test.alignment)
memory.initializeMemory(as: UInt8.self, repeating: 0, count: Test.size)
@@ -170,8 +327,8 @@ public struct InParentNamespace: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsInParentNamespace(bb: ByteBuffer) -> InParentNamespace { return InParentNamespace(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -180,20 +337,37 @@ public struct InParentNamespace: FlatBufferObject {
public static func startInParentNamespace(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 0) }
public static func endInParentNamespace(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
public static func createInParentNamespace(_ fbb: inout FlatBufferBuilder) -> Offset<UOffset> {
let __start = InParentNamespace.startInParentNamespace(&fbb)
return InParentNamespace.endInParentNamespace(&fbb, start: __start)
public mutating func unpack() -> InParentNamespaceT {
return InParentNamespaceT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout InParentNamespaceT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __root = InParentNamespace.startInParentNamespace(&builder)
return InParentNamespace.endInParentNamespace(&builder, start: __root)
}
}
public class InParentNamespaceT: NativeTable {
init(_ _t: inout InParentNamespace) {
}
init() {
}
}
public enum Example2 {
public struct Monster: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsMonster(bb: ByteBuffer) -> Monster { return Monster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -202,12 +376,29 @@ public struct Monster: FlatBufferObject {
public static func startMonster(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 0) }
public static func endMonster(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset<UOffset> { let end = Offset<UOffset>(offset: fbb.endTable(at: start)); return end }
public static func createMonster(_ fbb: inout FlatBufferBuilder) -> Offset<UOffset> {
let __start = Monster.startMonster(&fbb)
return Monster.endMonster(&fbb, start: __start)
public mutating func unpack() -> MonsterT {
return MonsterT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MonsterT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __root = Monster.startMonster(&builder)
return Monster.endMonster(&builder, start: __root)
}
}
public class MonsterT: NativeTable {
init(_ _t: inout Monster) {
}
init() {
}
}
}
// MARK: - Example2
@@ -220,8 +411,8 @@ public struct TestSimpleTableWithEnum: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsTestSimpleTableWithEnum(bb: ByteBuffer) -> TestSimpleTableWithEnum { return TestSimpleTableWithEnum(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -239,14 +430,39 @@ public struct TestSimpleTableWithEnum: FlatBufferObject {
TestSimpleTableWithEnum.add(color: color, &fbb)
return TestSimpleTableWithEnum.endTestSimpleTableWithEnum(&fbb, start: __start)
}
public mutating func unpack() -> TestSimpleTableWithEnumT {
return TestSimpleTableWithEnumT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout TestSimpleTableWithEnumT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __root = TestSimpleTableWithEnum.startTestSimpleTableWithEnum(&builder)
TestSimpleTableWithEnum.add(color: obj.color, &builder)
return TestSimpleTableWithEnum.endTestSimpleTableWithEnum(&builder, start: __root)
}
}
public class TestSimpleTableWithEnumT: NativeTable {
var color: MyGame.Example.Color
init(_ _t: inout TestSimpleTableWithEnum) {
color = _t.color
}
init() {
color = .green
}
}
public struct Stat: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsStat(bb: ByteBuffer) -> Stat { return Stat(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -274,14 +490,53 @@ public struct Stat: FlatBufferObject {
Stat.add(count: count, &fbb)
return Stat.endStat(&fbb, start: __start)
}
public mutating func unpack() -> StatT {
return StatT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout StatT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __id: Offset<String>
if let s = obj.id {
__id = builder.create(string: s)
} else {
__id = Offset<String>()
}
let __root = Stat.startStat(&builder)
Stat.add(id: __id, &builder)
Stat.add(val: obj.val, &builder)
Stat.add(count: obj.count, &builder)
return Stat.endStat(&builder, start: __root)
}
}
public class StatT: NativeTable {
var id: String?
var val: Int64
var count: UInt16
init(_ _t: inout Stat) {
id = _t.id
val = _t.val
count = _t.count
}
init() {
val = 0
count = 0
}
}
public struct Referrable: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsReferrable(bb: ByteBuffer) -> Referrable { return Referrable(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -323,15 +578,40 @@ public struct Referrable: FlatBufferObject {
}
return nil
}
public mutating func unpack() -> ReferrableT {
return ReferrableT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout ReferrableT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __root = Referrable.startReferrable(&builder)
Referrable.add(id: obj.id, &builder)
return Referrable.endReferrable(&builder, start: __root)
}
}
public class ReferrableT: NativeTable {
var id: UInt64
init(_ _t: inout Referrable) {
id = _t.id
}
init() {
id = 0
}
}
/// an example documentation comment: "monster object"
public struct Monster: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsMonster(bb: ByteBuffer) -> Monster { return Monster(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -622,14 +902,378 @@ public struct Monster: FlatBufferObject {
}
return nil
}
public mutating func unpack() -> MonsterT {
return MonsterT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MonsterT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __name: Offset<String>
if let s = obj.name {
__name = builder.create(string: s)
} else {
__name = Offset<String>()
}
let __inventory = builder.createVector(obj.inventory)
let __test = obj.test?.pack(builder: &builder) ?? Offset()
var __test4__: [UnsafeMutableRawPointer] = []
for i in obj.test4 {
guard let _o = i else { continue }
__test4__.append(createTest(a: _o.a, b: _o.b))
}
let __test4 = builder.createVector(structs: __test4__, type: MyGame.Example.Test.self)
let __testarrayofstring = builder.createVector(ofStrings: obj.testarrayofstring.compactMap({ $0 }) )
var __testarrayoftables__: [Offset<UOffset>] = []
for var i in obj.testarrayoftables {
__testarrayoftables__.append(MyGame.Example.Monster.pack(&builder, obj: &i))
}
let __testarrayoftables = builder.createVector(ofOffsets: __testarrayoftables__)
let __enemy = MyGame.Example.Monster.pack(&builder, obj: &obj.enemy)
let __testnestedflatbuffer = builder.createVector(obj.testnestedflatbuffer)
let __testempty = MyGame.Example.Stat.pack(&builder, obj: &obj.testempty)
let __testarrayofbools = builder.createVector(obj.testarrayofbools)
let __testarrayofstring2 = builder.createVector(ofStrings: obj.testarrayofstring2.compactMap({ $0 }) )
var __testarrayofsortedstruct__: [UnsafeMutableRawPointer] = []
for i in obj.testarrayofsortedstruct {
guard let _o = i else { continue }
__testarrayofsortedstruct__.append(createAbility(id: _o.id, distance: _o.distance))
}
let __testarrayofsortedstruct = builder.createVector(structs: __testarrayofsortedstruct__, type: MyGame.Example.Ability.self)
let __flex = builder.createVector(obj.flex)
var __test5__: [UnsafeMutableRawPointer] = []
for i in obj.test5 {
guard let _o = i else { continue }
__test5__.append(createTest(a: _o.a, b: _o.b))
}
let __test5 = builder.createVector(structs: __test5__, type: MyGame.Example.Test.self)
let __vectorOfLongs = builder.createVector(obj.vectorOfLongs)
let __vectorOfDoubles = builder.createVector(obj.vectorOfDoubles)
let __parentNamespaceTest = MyGame.InParentNamespace.pack(&builder, obj: &obj.parentNamespaceTest)
var __vectorOfReferrables__: [Offset<UOffset>] = []
for var i in obj.vectorOfReferrables {
__vectorOfReferrables__.append(MyGame.Example.Referrable.pack(&builder, obj: &i))
}
let __vectorOfReferrables = builder.createVector(ofOffsets: __vectorOfReferrables__)
let __vectorOfWeakReferences = builder.createVector(obj.vectorOfWeakReferences)
var __vectorOfStrongReferrables__: [Offset<UOffset>] = []
for var i in obj.vectorOfStrongReferrables {
__vectorOfStrongReferrables__.append(MyGame.Example.Referrable.pack(&builder, obj: &i))
}
let __vectorOfStrongReferrables = builder.createVector(ofOffsets: __vectorOfStrongReferrables__)
let __vectorOfCoOwningReferences = builder.createVector(obj.vectorOfCoOwningReferences)
let __vectorOfNonOwningReferences = builder.createVector(obj.vectorOfNonOwningReferences)
let __anyUnique = obj.anyUnique?.pack(builder: &builder) ?? Offset()
let __anyAmbiguous = obj.anyAmbiguous?.pack(builder: &builder) ?? Offset()
let __vectorOfEnums = builder.createVector(obj.vectorOfEnums)
let __root = Monster.startMonster(&builder)
Monster.add(pos: MyGame.Example.Vec3.pack(&builder, obj: &obj.pos), &builder)
Monster.add(mana: obj.mana, &builder)
Monster.add(hp: obj.hp, &builder)
Monster.add(name: __name, &builder)
Monster.addVectorOf(inventory: __inventory, &builder)
Monster.add(color: obj.color, &builder)
if let o = obj.test?.type {
Monster.add(testType: o, &builder)
Monster.add(test: __test, &builder)
}
Monster.addVectorOf(test4: __test4, &builder)
Monster.addVectorOf(testarrayofstring: __testarrayofstring, &builder)
Monster.addVectorOf(testarrayoftables: __testarrayoftables, &builder)
Monster.add(enemy: __enemy, &builder)
Monster.addVectorOf(testnestedflatbuffer: __testnestedflatbuffer, &builder)
Monster.add(testempty: __testempty, &builder)
Monster.add(testbool: obj.testbool, &builder)
Monster.add(testhashs32Fnv1: obj.testhashs32Fnv1, &builder)
Monster.add(testhashu32Fnv1: obj.testhashu32Fnv1, &builder)
Monster.add(testhashs64Fnv1: obj.testhashs64Fnv1, &builder)
Monster.add(testhashu64Fnv1: obj.testhashu64Fnv1, &builder)
Monster.add(testhashs32Fnv1a: obj.testhashs32Fnv1a, &builder)
Monster.add(testhashu32Fnv1a: obj.testhashu32Fnv1a, &builder)
Monster.add(testhashs64Fnv1a: obj.testhashs64Fnv1a, &builder)
Monster.add(testhashu64Fnv1a: obj.testhashu64Fnv1a, &builder)
Monster.addVectorOf(testarrayofbools: __testarrayofbools, &builder)
Monster.add(testf: obj.testf, &builder)
Monster.add(testf2: obj.testf2, &builder)
Monster.add(testf3: obj.testf3, &builder)
Monster.addVectorOf(testarrayofstring2: __testarrayofstring2, &builder)
Monster.addVectorOf(testarrayofsortedstruct: __testarrayofsortedstruct, &builder)
Monster.addVectorOf(flex: __flex, &builder)
Monster.addVectorOf(test5: __test5, &builder)
Monster.addVectorOf(vectorOfLongs: __vectorOfLongs, &builder)
Monster.addVectorOf(vectorOfDoubles: __vectorOfDoubles, &builder)
Monster.add(parentNamespaceTest: __parentNamespaceTest, &builder)
Monster.addVectorOf(vectorOfReferrables: __vectorOfReferrables, &builder)
Monster.add(singleWeakReference: obj.singleWeakReference, &builder)
Monster.addVectorOf(vectorOfWeakReferences: __vectorOfWeakReferences, &builder)
Monster.addVectorOf(vectorOfStrongReferrables: __vectorOfStrongReferrables, &builder)
Monster.add(coOwningReference: obj.coOwningReference, &builder)
Monster.addVectorOf(vectorOfCoOwningReferences: __vectorOfCoOwningReferences, &builder)
Monster.add(nonOwningReference: obj.nonOwningReference, &builder)
Monster.addVectorOf(vectorOfNonOwningReferences: __vectorOfNonOwningReferences, &builder)
if let o = obj.anyUnique?.type {
Monster.add(anyUniqueType: o, &builder)
Monster.add(anyUnique: __anyUnique, &builder)
}
if let o = obj.anyAmbiguous?.type {
Monster.add(anyAmbiguousType: o, &builder)
Monster.add(anyAmbiguous: __anyAmbiguous, &builder)
}
Monster.addVectorOf(vectorOfEnums: __vectorOfEnums, &builder)
Monster.add(signedEnum: obj.signedEnum, &builder)
return Monster.endMonster(&builder, start: __root)
}
}
public class MonsterT: NativeTable {
var pos: MyGame.Example.Vec3T?
var mana: Int16
var hp: Int16
var name: String?
var inventory: [UInt8]
var color: MyGame.Example.Color
var test: Any_Union?
var test4: [MyGame.Example.TestT?]
var testarrayofstring: [String?]
var testarrayoftables: [MyGame.Example.MonsterT?]
var enemy: MyGame.Example.MonsterT?
var testnestedflatbuffer: [UInt8]
var testempty: MyGame.Example.StatT?
var testbool: Bool
var testhashs32Fnv1: Int32
var testhashu32Fnv1: UInt32
var testhashs64Fnv1: Int64
var testhashu64Fnv1: UInt64
var testhashs32Fnv1a: Int32
var testhashu32Fnv1a: UInt32
var testhashs64Fnv1a: Int64
var testhashu64Fnv1a: UInt64
var testarrayofbools: [Bool]
var testf: Float32
var testf2: Float32
var testf3: Float32
var testarrayofstring2: [String?]
var testarrayofsortedstruct: [MyGame.Example.AbilityT?]
var flex: [UInt8]
var test5: [MyGame.Example.TestT?]
var vectorOfLongs: [Int64]
var vectorOfDoubles: [Double]
var parentNamespaceTest: MyGame.InParentNamespaceT?
var vectorOfReferrables: [MyGame.Example.ReferrableT?]
var singleWeakReference: UInt64
var vectorOfWeakReferences: [UInt64]
var vectorOfStrongReferrables: [MyGame.Example.ReferrableT?]
var coOwningReference: UInt64
var vectorOfCoOwningReferences: [UInt64]
var nonOwningReference: UInt64
var vectorOfNonOwningReferences: [UInt64]
var anyUnique: AnyUniqueAliasesUnion?
var anyAmbiguous: AnyAmbiguousAliasesUnion?
var vectorOfEnums: [MyGame.Example.Color]
var signedEnum: MyGame.Example.Race
init(_ _t: inout Monster) {
var __pos = _t.pos
pos = __pos?.unpack()
mana = _t.mana
hp = _t.hp
name = _t.name
inventory = []
for index in 0..<_t.inventoryCount {
inventory.append(_t.inventory(at: index))
}
color = _t.color
switch _t.testType {
case .monster:
var _v = _t.test(type: MyGame.Example.Monster.self)
test = Any_Union(_v?.unpack(), type: .monster)
case .testsimpletablewithenum:
var _v = _t.test(type: MyGame.Example.TestSimpleTableWithEnum.self)
test = Any_Union(_v?.unpack(), type: .testsimpletablewithenum)
case .mygame_example2_monster:
var _v = _t.test(type: MyGame.Example2.Monster.self)
test = Any_Union(_v?.unpack(), type: .mygame_example2_monster)
default: break
}
test4 = []
for index in 0..<_t.test4Count {
var __v_ = _t.test4(at: index)
test4.append(__v_?.unpack())
}
testarrayofstring = []
for index in 0..<_t.testarrayofstringCount {
testarrayofstring.append(_t.testarrayofstring(at: index))
}
testarrayoftables = []
for index in 0..<_t.testarrayoftablesCount {
var __v_ = _t.testarrayoftables(at: index)
testarrayoftables.append(__v_?.unpack())
}
var __enemy = _t.enemy
enemy = __enemy?.unpack()
testnestedflatbuffer = []
for index in 0..<_t.testnestedflatbufferCount {
testnestedflatbuffer.append(_t.testnestedflatbuffer(at: index))
}
var __testempty = _t.testempty
testempty = __testempty?.unpack()
testbool = _t.testbool
testhashs32Fnv1 = _t.testhashs32Fnv1
testhashu32Fnv1 = _t.testhashu32Fnv1
testhashs64Fnv1 = _t.testhashs64Fnv1
testhashu64Fnv1 = _t.testhashu64Fnv1
testhashs32Fnv1a = _t.testhashs32Fnv1a
testhashu32Fnv1a = _t.testhashu32Fnv1a
testhashs64Fnv1a = _t.testhashs64Fnv1a
testhashu64Fnv1a = _t.testhashu64Fnv1a
testarrayofbools = []
for index in 0..<_t.testarrayofboolsCount {
testarrayofbools.append(_t.testarrayofbools(at: index))
}
testf = _t.testf
testf2 = _t.testf2
testf3 = _t.testf3
testarrayofstring2 = []
for index in 0..<_t.testarrayofstring2Count {
testarrayofstring2.append(_t.testarrayofstring2(at: index))
}
testarrayofsortedstruct = []
for index in 0..<_t.testarrayofsortedstructCount {
var __v_ = _t.testarrayofsortedstruct(at: index)
testarrayofsortedstruct.append(__v_?.unpack())
}
flex = []
for index in 0..<_t.flexCount {
flex.append(_t.flex(at: index))
}
test5 = []
for index in 0..<_t.test5Count {
var __v_ = _t.test5(at: index)
test5.append(__v_?.unpack())
}
vectorOfLongs = []
for index in 0..<_t.vectorOfLongsCount {
vectorOfLongs.append(_t.vectorOfLongs(at: index))
}
vectorOfDoubles = []
for index in 0..<_t.vectorOfDoublesCount {
vectorOfDoubles.append(_t.vectorOfDoubles(at: index))
}
var __parentNamespaceTest = _t.parentNamespaceTest
parentNamespaceTest = __parentNamespaceTest?.unpack()
vectorOfReferrables = []
for index in 0..<_t.vectorOfReferrablesCount {
var __v_ = _t.vectorOfReferrables(at: index)
vectorOfReferrables.append(__v_?.unpack())
}
singleWeakReference = _t.singleWeakReference
vectorOfWeakReferences = []
for index in 0..<_t.vectorOfWeakReferencesCount {
vectorOfWeakReferences.append(_t.vectorOfWeakReferences(at: index))
}
vectorOfStrongReferrables = []
for index in 0..<_t.vectorOfStrongReferrablesCount {
var __v_ = _t.vectorOfStrongReferrables(at: index)
vectorOfStrongReferrables.append(__v_?.unpack())
}
coOwningReference = _t.coOwningReference
vectorOfCoOwningReferences = []
for index in 0..<_t.vectorOfCoOwningReferencesCount {
vectorOfCoOwningReferences.append(_t.vectorOfCoOwningReferences(at: index))
}
nonOwningReference = _t.nonOwningReference
vectorOfNonOwningReferences = []
for index in 0..<_t.vectorOfNonOwningReferencesCount {
vectorOfNonOwningReferences.append(_t.vectorOfNonOwningReferences(at: index))
}
switch _t.anyUniqueType {
case .m:
var _v = _t.anyUnique(type: MyGame.Example.Monster.self)
anyUnique = AnyUniqueAliasesUnion(_v?.unpack(), type: .m)
case .ts:
var _v = _t.anyUnique(type: MyGame.Example.TestSimpleTableWithEnum.self)
anyUnique = AnyUniqueAliasesUnion(_v?.unpack(), type: .ts)
case .m2:
var _v = _t.anyUnique(type: MyGame.Example2.Monster.self)
anyUnique = AnyUniqueAliasesUnion(_v?.unpack(), type: .m2)
default: break
}
switch _t.anyAmbiguousType {
case .m1:
var _v = _t.anyAmbiguous(type: MyGame.Example.Monster.self)
anyAmbiguous = AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m1)
case .m2:
var _v = _t.anyAmbiguous(type: MyGame.Example.Monster.self)
anyAmbiguous = AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m2)
case .m3:
var _v = _t.anyAmbiguous(type: MyGame.Example.Monster.self)
anyAmbiguous = AnyAmbiguousAliasesUnion(_v?.unpack(), type: .m3)
default: break
}
vectorOfEnums = []
for index in 0..<_t.vectorOfEnumsCount {
vectorOfEnums.append(_t.vectorOfEnums(at: index)!)
}
signedEnum = _t.signedEnum
}
init() {
pos = MyGame.Example.Vec3T()
mana = 150
hp = 100
inventory = []
color = .blue
test4 = []
testarrayofstring = []
testarrayoftables = []
enemy = MyGame.Example.MonsterT()
testnestedflatbuffer = []
testempty = MyGame.Example.StatT()
testbool = false
testhashs32Fnv1 = 0
testhashu32Fnv1 = 0
testhashs64Fnv1 = 0
testhashu64Fnv1 = 0
testhashs32Fnv1a = 0
testhashu32Fnv1a = 0
testhashs64Fnv1a = 0
testhashu64Fnv1a = 0
testarrayofbools = []
testf = 3.14159
testf2 = 3.0
testf3 = 0.0
testarrayofstring2 = []
testarrayofsortedstruct = []
flex = []
test5 = []
vectorOfLongs = []
vectorOfDoubles = []
parentNamespaceTest = MyGame.InParentNamespaceT()
vectorOfReferrables = []
singleWeakReference = 0
vectorOfWeakReferences = []
vectorOfStrongReferrables = []
coOwningReference = 0
vectorOfCoOwningReferences = []
nonOwningReference = 0
vectorOfNonOwningReferences = []
vectorOfEnums = []
signedEnum = .none
}
}
public struct TypeAliases: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MONS", addPrefix: prefix) }
public static func getRootAsTypeAliases(bb: ByteBuffer) -> TypeAliases { return TypeAliases(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -706,8 +1350,85 @@ public struct TypeAliases: FlatBufferObject {
TypeAliases.addVectorOf(vf64: vf64, &fbb)
return TypeAliases.endTypeAliases(&fbb, start: __start)
}
public mutating func unpack() -> TypeAliasesT {
return TypeAliasesT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout TypeAliasesT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __v8 = builder.createVector(obj.v8)
let __vf64 = builder.createVector(obj.vf64)
let __root = TypeAliases.startTypeAliases(&builder)
TypeAliases.add(i8: obj.i8, &builder)
TypeAliases.add(u8: obj.u8, &builder)
TypeAliases.add(i16: obj.i16, &builder)
TypeAliases.add(u16: obj.u16, &builder)
TypeAliases.add(i32: obj.i32, &builder)
TypeAliases.add(u32: obj.u32, &builder)
TypeAliases.add(i64: obj.i64, &builder)
TypeAliases.add(u64: obj.u64, &builder)
TypeAliases.add(f32: obj.f32, &builder)
TypeAliases.add(f64: obj.f64, &builder)
TypeAliases.addVectorOf(v8: __v8, &builder)
TypeAliases.addVectorOf(vf64: __vf64, &builder)
return TypeAliases.endTypeAliases(&builder, start: __root)
}
}
public class TypeAliasesT: NativeTable {
var i8: Int8
var u8: UInt8
var i16: Int16
var u16: UInt16
var i32: Int32
var u32: UInt32
var i64: Int64
var u64: UInt64
var f32: Float32
var f64: Double
var v8: [Int8]
var vf64: [Double]
init(_ _t: inout TypeAliases) {
i8 = _t.i8
u8 = _t.u8
i16 = _t.i16
u16 = _t.u16
i32 = _t.i32
u32 = _t.u32
i64 = _t.i64
u64 = _t.u64
f32 = _t.f32
f64 = _t.f64
v8 = []
for index in 0..<_t.v8Count {
v8.append(_t.v8(at: index))
}
vf64 = []
for index in 0..<_t.vf64Count {
vf64.append(_t.vf64(at: index))
}
}
init() {
i8 = 0
u8 = 0
i16 = 0
u16 = 0
i32 = 0
u32 = 0
i64 = 0
u64 = 0
f32 = 0.0
f64 = 0.0
v8 = []
vf64 = []
}
}
}
// MARK: - Example

View File

@@ -19,34 +19,105 @@ public enum Character: UInt8, Enum {
public static var min: Character { return .none }
}
struct CharacterUnion {
var type: Character
var value: NativeTable?
init(_ v: NativeTable?, type: Character) {
self.type = type
self.value = v
}
func pack(builder: inout FlatBufferBuilder) -> Offset<UOffset> {
switch type {
case .mulan:
var __obj = value as? AttackerT
return Attacker.pack(&builder, obj: &__obj)
case .rapunzel:
var __obj = value as? RapunzelT
return Rapunzel.pack(&builder, obj: &__obj)
case .belle:
var __obj = value as? BookReaderT
return BookReader.pack(&builder, obj: &__obj)
case .bookfan:
var __obj = value as? BookReaderT
return BookReader.pack(&builder, obj: &__obj)
default: return Offset()
}
}
}
public struct Rapunzel: Readable {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct
public static var size = 4
public static var alignment = 4
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
public var hairLength: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) }
public func mutate(hairLength: Int32) -> Bool { return _accessor.mutate(hairLength, index: 0) }
public mutating func unpack() -> RapunzelT {
return RapunzelT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout RapunzelT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
return builder.create(struct: createRapunzel(hairLength: obj.hairLength), type: Rapunzel.self)
}
}
public class RapunzelT: NativeTable {
var hairLength: Int32
init(_ _t: inout Rapunzel) {
hairLength = _t.hairLength
}
init() {
hairLength = 0
}
}
public struct BookReader: Readable {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Struct
public static var size = 4
public static var alignment = 4
public init(_ bb: ByteBuffer, o: Int32) { _accessor = Struct(bb: bb, position: o) }
public var booksRead: Int32 { return _accessor.readBuffer(of: Int32.self, at: 0) }
public func mutate(booksRead: Int32) -> Bool { return _accessor.mutate(booksRead, index: 0) }
public mutating func unpack() -> BookReaderT {
return BookReaderT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout BookReaderT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
return builder.create(struct: createBookReader(booksRead: obj.booksRead), type: BookReader.self)
}
}
public class BookReaderT: NativeTable {
var booksRead: Int32
init(_ _t: inout BookReader) {
booksRead = _t.booksRead
}
init() {
booksRead = 0
}
}
public func createRapunzel(hairLength: Int32) -> UnsafeMutableRawPointer {
let memory = UnsafeMutableRawPointer.allocate(byteCount: Rapunzel.size, alignment: Rapunzel.alignment)
memory.initializeMemory(as: UInt8.self, repeating: 0, count: Rapunzel.size)
@@ -65,8 +136,8 @@ public struct Attacker: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
public static func getRootAsAttacker(bb: ByteBuffer) -> Attacker { return Attacker(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -84,14 +155,39 @@ public struct Attacker: FlatBufferObject {
Attacker.add(swordAttackDamage: swordAttackDamage, &fbb)
return Attacker.endAttacker(&fbb, start: __start)
}
public mutating func unpack() -> AttackerT {
return AttackerT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout AttackerT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __root = Attacker.startAttacker(&builder)
Attacker.add(swordAttackDamage: obj.swordAttackDamage, &builder)
return Attacker.endAttacker(&builder, start: __root)
}
}
public class AttackerT: NativeTable {
var swordAttackDamage: Int32
init(_ _t: inout Attacker) {
swordAttackDamage = _t.swordAttackDamage
}
init() {
swordAttackDamage = 0
}
}
public struct Movie: FlatBufferObject {
static func validateVersion() { FlatBuffersVersion_1_12_0() }
public var __buffer: ByteBuffer! { return _accessor.bb }
private var _accessor: Table
public static func finish(_ fbb: inout FlatBufferBuilder, end: Offset<UOffset>, prefix: Bool = false) { fbb.finish(offset: end, fileId: "MOVI", addPrefix: prefix) }
public static func getRootAsMovie(bb: ByteBuffer) -> Movie { return Movie(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) }
@@ -122,5 +218,77 @@ public struct Movie: FlatBufferObject {
Movie.addVectorOf(characters: characters, &fbb)
return Movie.endMovie(&fbb, start: __start)
}
public mutating func unpack() -> MovieT {
return MovieT(&self)
}
public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MovieT?) -> Offset<UOffset> {
guard let obj = obj else { return Offset<UOffset>() }
let __mainCharacter = obj.mainCharacter?.pack(builder: &builder) ?? Offset()
var __characters__: [Offset<UOffset>] = []
for i in obj.characters {
guard let off = i?.pack(builder: &builder) else { continue }
__characters__.append(off)
}
let __characters = builder.createVector(ofOffsets: __characters__)
let __charactersType = builder.createVector(obj.characters.compactMap { $0?.type })
let __root = Movie.startMovie(&builder)
if let o = obj.mainCharacter?.type {
Movie.add(mainCharacterType: o, &builder)
Movie.add(mainCharacter: __mainCharacter, &builder)
}
Movie.addVectorOf(charactersType: __charactersType, &builder)
Movie.addVectorOf(characters: __characters, &builder)
return Movie.endMovie(&builder, start: __root)
}
}
public class MovieT: NativeTable {
var mainCharacter: CharacterUnion?
var characters: [CharacterUnion?]
init(_ _t: inout Movie) {
switch _t.mainCharacterType {
case .mulan:
var _v = _t.mainCharacter(type: Attacker.self)
mainCharacter = CharacterUnion(_v?.unpack(), type: .mulan)
case .rapunzel:
var _v = _t.mainCharacter(type: Rapunzel.self)
mainCharacter = CharacterUnion(_v?.unpack(), type: .rapunzel)
case .belle:
var _v = _t.mainCharacter(type: BookReader.self)
mainCharacter = CharacterUnion(_v?.unpack(), type: .belle)
case .bookfan:
var _v = _t.mainCharacter(type: BookReader.self)
mainCharacter = CharacterUnion(_v?.unpack(), type: .bookfan)
default: break
}
characters = []
for index in 0..<_t.charactersCount {
switch _t.charactersType(at: index) {
case .mulan:
var _v = _t.characters(at: index, type: Attacker.self)
characters.append(CharacterUnion(_v?.unpack(), type: .mulan))
case .rapunzel:
var _v = _t.characters(at: index, type: Rapunzel.self)
characters.append(CharacterUnion(_v?.unpack(), type: .rapunzel))
case .belle:
var _v = _t.characters(at: index, type: BookReader.self)
characters.append(CharacterUnion(_v?.unpack(), type: .belle))
case .bookfan:
var _v = _t.characters(at: index, type: BookReader.self)
characters.append(CharacterUnion(_v?.unpack(), type: .bookfan))
default: break
}
}
}
init() {
characters = []
}
}