From ae603b9770ee336ad8e7c6e696a8912d63d76c2a Mon Sep 17 00:00:00 2001 From: mustiikhalil Date: Fri, 19 Feb 2021 12:47:28 +0300 Subject: [PATCH] [Swift] adds support for default vectors and strings (#6461) Small fix Adhere to the new protocol names --- src/idl_gen_swift.cpp | 70 +++++++----- src/idl_parser.cpp | 2 +- tests/FlatBuffers.Test.Swift/SwiftTest.sh | 1 + .../FlatBuffersMonsterWriterTests.swift | 18 +++ .../FlatbuffersMoreDefaults.swift | 53 +++++++++ .../XCTestManifests.swift | 12 ++ .../monster_test_generated.swift | 6 +- .../more_defaults_generated.swift | 122 +++++++++++++++++++++ tests/generate_code.sh | 7 +- 9 files changed, 254 insertions(+), 37 deletions(-) create mode 100644 tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatbuffersMoreDefaults.swift create mode 100644 tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp index 7996b50..512711c 100644 --- a/src/idl_gen_swift.cpp +++ b/src/idl_gen_swift.cpp @@ -537,7 +537,8 @@ class SwiftGenerator : public BaseGenerator { auto &create_func_header = *create_header; auto name = Name(field); auto type = GenType(field.value.type); - auto opt_scalar = field.IsOptional() && IsScalar(field.value.type.base_type); + auto opt_scalar = + field.IsOptional() && IsScalar(field.value.type.base_type); auto nullable_type = opt_scalar ? type + "?" : type; code_.SetValue("VALUENAME", name); code_.SetValue("VALUETYPE", nullable_type); @@ -560,7 +561,7 @@ class SwiftGenerator : public BaseGenerator { "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}\\"; code_ += field.IsOptional() ? (optional_enum + "\\") - : (is_enum + ", def: {{CONSTANT}}\\"); + : (is_enum + ", def: {{CONSTANT}}\\"); code_ += ", at: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; @@ -568,8 +569,9 @@ class SwiftGenerator : public BaseGenerator { IsEnum(field.value.type) ? (field.IsOptional() ? "nil" : GenEnumDefaultValue(field)) : field.value.constant; - create_func_header.push_back("" + name + ": " + nullable_type + " = " + - (field.IsOptional() ? "nil" : default_value)); + create_func_header.push_back( + "" + name + ": " + nullable_type + " = " + + (field.IsOptional() ? "nil" : default_value)); return; } @@ -583,8 +585,9 @@ class SwiftGenerator : public BaseGenerator { "fbb.add(element: {{VALUENAME}},\\"; code_ += field.IsOptional() ? "\\" : " def: {{CONSTANT}},"; code_ += " at: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; - create_func_header.push_back(name + ": " + nullable_type + " = " + - (field.IsOptional() ? "nil" : default_value)); + create_func_header.push_back( + name + ": " + nullable_type + " = " + + (field.IsOptional() ? "nil" : default_value)); return; } @@ -648,9 +651,8 @@ class SwiftGenerator : public BaseGenerator { code_.SetValue("VALUETYPE", type); code_.SetValue("OFFSET", name); code_.SetValue("CONSTANT", field.value.constant); - bool opt_scalar = field.IsOptional() && IsScalar(field.value.type.base_type); - std::string def_Val = opt_scalar ? "nil" : "{{CONSTANT}}"; - std::string optional = opt_scalar ? "?" : ""; + std::string def_Val = field.IsDefault() ? "{{CONSTANT}}" : "nil"; + std::string optional = field.IsOptional() ? "?" : ""; auto const_string = "return o == 0 ? " + def_Val + " : "; GenComment(field.doc_comment); if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) && @@ -675,7 +677,8 @@ class SwiftGenerator : public BaseGenerator { } if (IsEnum(field.value.type)) { - auto default_value = field.IsOptional() ? "nil" : GenEnumDefaultValue(field); + auto default_value = + field.IsOptional() ? "nil" : GenEnumDefaultValue(field); code_.SetValue("BASEVALUE", GenTypeBasic(field.value.type, false)); code_ += GenReaderMainBody(optional) + "\\"; code_ += GenOffset() + "return o == 0 ? " + default_value + " : " + @@ -709,9 +712,10 @@ class SwiftGenerator : public BaseGenerator { GenConstructor(GenIndirect("o + {{ACCESS}}.postion")); break; - case BASE_TYPE_STRING: + case BASE_TYPE_STRING: { + auto default_string = "\"" + field.value.constant + "\""; code_.SetValue("VALUETYPE", GenType(field.value.type)); - code_.SetValue("CONSTANT", "nil"); + code_.SetValue("CONSTANT", field.IsDefault() ? default_string : "nil"); code_ += GenReaderMainBody(is_required) + GenOffset() + required_reader + "{{ACCESS}}.string(at: o) }"; code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}SegmentArray: [UInt8]" + @@ -719,11 +723,9 @@ class SwiftGenerator : public BaseGenerator { " { return " "{{ACCESS}}.getVector(at: {{TABLEOFFSET}}.{{OFFSET}}.v) }"; break; - + } case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru - case BASE_TYPE_VECTOR: - GenTableReaderVectorFields(field, const_string); - break; + case BASE_TYPE_VECTOR: GenTableReaderVectorFields(field); break; case BASE_TYPE_UNION: code_.SetValue("CONSTANT", "nil"); code_ += @@ -736,15 +738,14 @@ class SwiftGenerator : public BaseGenerator { } } - void GenTableReaderVectorFields(const FieldDef &field, - const std::string &const_string) { + void GenTableReaderVectorFields(const FieldDef &field) { + std::string const_string = "return o == 0 ? {{CONSTANT}} : "; auto vectortype = field.value.type.VectorType(); code_.SetValue("SIZE", NumToString(InlineSize(vectortype))); code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}Count: Int32 { " + GenOffset() + - const_string + "{{ACCESS}}.vector(count: o) }"; - code_.SetValue("CONSTANT", IsScalar(vectortype.base_type) == true - ? field.value.constant - : "nil"); + "return o == 0 ? 0 : {{ACCESS}}.vector(count: o) }"; + code_.SetValue("CONSTANT", + IsScalar(vectortype.base_type) == true ? "0" : "nil"); auto nullable = IsScalar(vectortype.base_type) == true ? "" : "?"; nullable = IsEnum(vectortype) == true ? "?" : nullable; @@ -759,11 +760,10 @@ class SwiftGenerator : public BaseGenerator { if (IsBool(vectortype.base_type)) { code_.SetValue("CONSTANT", field.value.offset == 0 ? "false" : "true"); - code_.SetValue("VALUETYPE", "Byte"); + code_.SetValue("VALUETYPE", "Bool"); } - if (!IsEnum(vectortype)) - code_ += - const_string + (IsBool(vectortype.base_type) ? "0 != " : "") + "\\"; + + if (!IsEnum(vectortype)) code_ += const_string + "\\"; if (IsScalar(vectortype.base_type) && !IsEnum(vectortype) && !IsBool(field.value.type.base_type)) { @@ -1166,9 +1166,9 @@ class SwiftGenerator : public BaseGenerator { buffer_constructor.push_back("" + name + " = _t." + name); } else { buffer_constructor.push_back("var __" + name + " = _t." + name); - buffer_constructor.push_back("" + name + " = __" + name + - (field.IsRequired() ? "!" : question_mark) + - ".unpack()"); + buffer_constructor.push_back( + "" + name + " = __" + name + + (field.IsRequired() ? "!" : question_mark) + ".unpack()"); } break; } @@ -1181,7 +1181,17 @@ class SwiftGenerator : public BaseGenerator { case BASE_TYPE_STRING: { code_ += "{{ACCESS_TYPE}} var {{VALUENAME}}: String" + is_required; buffer_constructor.push_back(name + " = _t." + name); - if (field.IsRequired()) base_constructor.push_back(name + " = \"\""); + + if (field.IsRequired()) { + std::string default_value = + field.IsDefault() ? field.value.constant : ""; + base_constructor.push_back(name + " = \"" + default_value + "\""); + break; + } + if (field.IsDefault() && !field.IsRequired()) { + std::string value = field.IsDefault() ? field.value.constant : "nil"; + base_constructor.push_back(name + " = \"" + value + "\""); + } break; } case BASE_TYPE_UTYPE: break; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index c633191..0f48c84 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2434,7 +2434,7 @@ bool Parser::SupportsOptionalScalars() const { bool Parser::SupportsDefaultVectorsAndStrings() const { static FLATBUFFERS_CONSTEXPR unsigned long supported_langs = - IDLOptions::kRust; + IDLOptions::kRust | IDLOptions::kSwift; return !(opts.lang_to_generate & ~supported_langs); } diff --git a/tests/FlatBuffers.Test.Swift/SwiftTest.sh b/tests/FlatBuffers.Test.Swift/SwiftTest.sh index 5e2916c..7b907be 100755 --- a/tests/FlatBuffers.Test.Swift/SwiftTest.sh +++ b/tests/FlatBuffers.Test.Swift/SwiftTest.sh @@ -10,6 +10,7 @@ cd ${test_dir} cd ${swift_dir}/Tests/FlatBuffers.Test.SwiftTests fbc --swift --gen-mutable --grpc --gen-object-api -I ${test_dir}/include_test ${test_dir}/monster_test.fbs ${test_dir}/union_vector/union_vector.fbs fbc --swift ${test_dir}/optional_scalars.fbs +fbc --swift --gen-object-api ${test_dir}/more_defaults.fbs cd ${swift_dir} swift build --build-tests swift test diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift index 16c74ac..702b0d9 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersMonsterWriterTests.swift @@ -99,6 +99,24 @@ class FlatBuffersMonsterWriterTests: XCTestCase { readObjectApi(monster: unpacked) } + func testArrayOfBools() { + let boolArray = [false, true, false, true, false, true, false] + var fbb = FlatBufferBuilder(initialSize: 1) + let name = fbb.create(string: "Frodo") + let bools = fbb.createVector(boolArray) + let root = Monster.createMonster(&fbb, offsetOfName: name, vectorOfTestarrayofbools: bools) + fbb.finish(offset: root) + let monster = Monster.getRootAsMonster(bb: fbb.sizedBuffer) + + let values = monster.testarrayofbools + + XCTAssertEqual(boolArray, values) + + for i in 0.. [XCTestCaseEntry] { [ testCase(FlatBuffersDoubleTests.__allTests__FlatBuffersDoubleTests), testCase(FlatBuffersMonsterWriterTests.__allTests__FlatBuffersMonsterWriterTests), + testCase(FlatBuffersMoreDefaults.__allTests__FlatBuffersMoreDefaults), testCase(FlatBuffersStructsTests.__allTests__FlatBuffersStructsTests), testCase(FlatBuffersTests.__allTests__FlatBuffersTests), testCase(FlatBuffersUnionTests.__allTests__FlatBuffersUnionTests), diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift index ecd56a2..b4ec29a 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test_generated.swift @@ -800,9 +800,9 @@ public struct MyGame_Example_Monster: FlatBufferObject, ObjectAPIPacker { public var testhashu64Fnv1a: UInt64 { let o = _accessor.offset(VTOFFSET.testhashu64Fnv1a.v); return o == 0 ? 0 : _accessor.readBuffer(of: UInt64.self, at: o) } @discardableResult public func mutate(testhashu64Fnv1a: UInt64) -> Bool {let o = _accessor.offset(VTOFFSET.testhashu64Fnv1a.v); return _accessor.mutate(testhashu64Fnv1a, index: o) } public var testarrayofboolsCount: Int32 { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? 0 : _accessor.vector(count: o) } - public func testarrayofbools(at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? true : 0 != _accessor.directRead(of: Byte.self, offset: _accessor.vector(at: o) + index * 1) } - public var testarrayofbools: [Byte] { return _accessor.getVector(at: VTOFFSET.testarrayofbools.v) ?? [] } - public func mutate(testarrayofbools: Byte, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return _accessor.directMutate(testarrayofbools, index: _accessor.vector(at: o) + index * 1) } + public func testarrayofbools(at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return o == 0 ? true : _accessor.directRead(of: Bool.self, offset: _accessor.vector(at: o) + index * 1) } + public var testarrayofbools: [Bool] { return _accessor.getVector(at: VTOFFSET.testarrayofbools.v) ?? [] } + public func mutate(testarrayofbools: Bool, at index: Int32) -> Bool { let o = _accessor.offset(VTOFFSET.testarrayofbools.v); return _accessor.directMutate(testarrayofbools, index: _accessor.vector(at: o) + index * 1) } public var testf: Float32 { let o = _accessor.offset(VTOFFSET.testf.v); return o == 0 ? 3.14159 : _accessor.readBuffer(of: Float32.self, at: o) } @discardableResult public func mutate(testf: Float32) -> Bool {let o = _accessor.offset(VTOFFSET.testf.v); return _accessor.mutate(testf, index: o) } public var testf2: Float32 { let o = _accessor.offset(VTOFFSET.testf2.v); return o == 0 ? 3.0 : _accessor.readBuffer(of: Float32.self, at: o) } diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift new file mode 100644 index 0000000..ecab387 --- /dev/null +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/more_defaults_generated.swift @@ -0,0 +1,122 @@ +// automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all +// swiftformat:disable all + +import FlatBuffers + +public struct MoreDefaults: FlatBufferObject, ObjectAPIPacker { + + static func validateVersion() { FlatBuffersVersion_1_12_0() } + public var __buffer: ByteBuffer! { return _accessor.bb } + private var _accessor: Table + + public static func getRootAsMoreDefaults(bb: ByteBuffer) -> MoreDefaults { return MoreDefaults(Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader))) } + + private init(_ t: Table) { _accessor = t } + public init(_ bb: ByteBuffer, o: Int32) { _accessor = Table(bb: bb, position: o) } + + private enum VTOFFSET: VOffset { + case ints = 4 + case floats = 6 + case emptyString = 8 + case someString = 10 + var v: Int32 { Int32(self.rawValue) } + var p: VOffset { self.rawValue } + } + + public var intsCount: Int32 { let o = _accessor.offset(VTOFFSET.ints.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func ints(at index: Int32) -> Int32 { let o = _accessor.offset(VTOFFSET.ints.v); return o == 0 ? 0 : _accessor.directRead(of: Int32.self, offset: _accessor.vector(at: o) + index * 4) } + public var ints: [Int32] { return _accessor.getVector(at: VTOFFSET.ints.v) ?? [] } + public var floatsCount: Int32 { let o = _accessor.offset(VTOFFSET.floats.v); return o == 0 ? 0 : _accessor.vector(count: o) } + public func floats(at index: Int32) -> Float32 { let o = _accessor.offset(VTOFFSET.floats.v); return o == 0 ? 0 : _accessor.directRead(of: Float32.self, offset: _accessor.vector(at: o) + index * 4) } + public var floats: [Float32] { return _accessor.getVector(at: VTOFFSET.floats.v) ?? [] } + public var emptyString: String? { let o = _accessor.offset(VTOFFSET.emptyString.v); return o == 0 ? "" : _accessor.string(at: o) } + public var emptyStringSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.emptyString.v) } + public var someString: String? { let o = _accessor.offset(VTOFFSET.someString.v); return o == 0 ? "some" : _accessor.string(at: o) } + public var someStringSegmentArray: [UInt8]? { return _accessor.getVector(at: VTOFFSET.someString.v) } + public static func startMoreDefaults(_ fbb: inout FlatBufferBuilder) -> UOffset { fbb.startTable(with: 4) } + public static func addVectorOf(ints: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: ints, at: VTOFFSET.ints.p) } + public static func addVectorOf(floats: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: floats, at: VTOFFSET.floats.p) } + public static func add(emptyString: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: emptyString, at: VTOFFSET.emptyString.p) } + public static func add(someString: Offset, _ fbb: inout FlatBufferBuilder) { fbb.add(offset: someString, at: VTOFFSET.someString.p) } + public static func endMoreDefaults(_ fbb: inout FlatBufferBuilder, start: UOffset) -> Offset { let end = Offset(offset: fbb.endTable(at: start)); return end } + public static func createMoreDefaults( + _ fbb: inout FlatBufferBuilder, + vectorOfInts ints: Offset = Offset(), + vectorOfFloats floats: Offset = Offset(), + offsetOfEmptyString emptyString: Offset = Offset(), + offsetOfSomeString someString: Offset = Offset() + ) -> Offset { + let __start = MoreDefaults.startMoreDefaults(&fbb) + MoreDefaults.addVectorOf(ints: ints, &fbb) + MoreDefaults.addVectorOf(floats: floats, &fbb) + MoreDefaults.add(emptyString: emptyString, &fbb) + MoreDefaults.add(someString: someString, &fbb) + return MoreDefaults.endMoreDefaults(&fbb, start: __start) + } + + + public mutating func unpack() -> MoreDefaultsT { + return MoreDefaultsT(&self) + } + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MoreDefaultsT?) -> Offset { + guard var obj = obj else { return Offset() } + return pack(&builder, obj: &obj) + } + + public static func pack(_ builder: inout FlatBufferBuilder, obj: inout MoreDefaultsT) -> Offset { + let __ints = builder.createVector(obj.ints) + let __floats = builder.createVector(obj.floats) + let __emptyString: Offset + if let s = obj.emptyString { + __emptyString = builder.create(string: s) + } else { + __emptyString = Offset() + } + + let __someString: Offset + if let s = obj.someString { + __someString = builder.create(string: s) + } else { + __someString = Offset() + } + + let __root = MoreDefaults.startMoreDefaults(&builder) + MoreDefaults.addVectorOf(ints: __ints, &builder) + MoreDefaults.addVectorOf(floats: __floats, &builder) + MoreDefaults.add(emptyString: __emptyString, &builder) + MoreDefaults.add(someString: __someString, &builder) + return MoreDefaults.endMoreDefaults(&builder, start: __root) + } +} + +public class MoreDefaultsT: NativeObject { + + public var ints: [Int32] + public var floats: [Float32] + public var emptyString: String? + public var someString: String? + + public init(_ _t: inout MoreDefaults) { + ints = [] + for index in 0..<_t.intsCount { + ints.append(_t.ints(at: index)) + } + floats = [] + for index in 0..<_t.floatsCount { + floats.append(_t.floats(at: index)) + } + emptyString = _t.emptyString + someString = _t.someString + } + + public init() { + ints = [] + floats = [] + emptyString = "" + someString = "some" + } + + public func serialize() -> ByteBuffer { return serialize(type: MoreDefaults.self) } + +} diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 0f374f6..a308611 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -69,9 +69,10 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_JS_TS_FLAGS -o namespace working_dir=`pwd` cd FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests -$working_dir/../flatc --swift --grpc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I ../../../include_test ../../../monster_test.fbs -$working_dir/../flatc --swift $TEST_BASE_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS ../../../union_vector/union_vector.fbs -$working_dir/../flatc --swift ../../../optional_scalars.fbs +$working_dir/../flatc --swift --grpc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I ${working_dir}/include_test ${working_dir}/monster_test.fbs +$working_dir/../flatc --swift $TEST_BASE_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS ${working_dir}/union_vector/union_vector.fbs +$working_dir/../flatc --swift ${working_dir}/optional_scalars.fbs +$working_dir/../flatc --swift --gen-object-api ${working_dir}/more_defaults.fbs cd $working_dir cd FlatBuffers.GRPC.Swift/Sources/Model -- 2.7.4