From ff1b73128d7dbe79e5f91c3fe191b1201be948d2 Mon Sep 17 00:00:00 2001 From: mustiikhalil Date: Mon, 20 Jul 2020 20:38:50 +0300 Subject: [PATCH] [Swift] Optional Scalars Preparation (#6028) * Perpares swift to take optional scalars + adds optional string helper method + disables linters in generated code * Small fix for generated code * Update grpc support to alpha 17 for swift --- grpc/src/compiler/swift_generator.cc | 8 ++--- src/idl_gen_swift.cpp | 34 ++++++++++++------- swift/FlatBuffers.podspec | 2 +- .../FlatBuffers/FlatBufferBuilder.swift | 17 ++++++++++ tests/FlatBuffers.GRPC.Swift/Package.swift | 2 +- .../Sources/Model/greeter.grpc.swift | 4 +-- .../Sources/Model/greeter_generated.swift | 1 + tests/FlatBuffers.Test.Swift/Package.swift | 2 +- .../FlatBuffersTests.swift | 21 ++++++++++++ .../monster_test.grpc.swift | 8 ++--- .../monster_test_generated.swift | 1 + .../union_vector_generated.swift | 1 + 12 files changed, 75 insertions(+), 26 deletions(-) diff --git a/grpc/src/compiler/swift_generator.cc b/grpc/src/compiler/swift_generator.cc index 7aa29ac10..a6016afb2 100644 --- a/grpc/src/compiler/swift_generator.cc +++ b/grpc/src/compiler/swift_generator.cc @@ -164,7 +164,7 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { grpc::string start = "\t\tcase \"$MethodName$\":\n\t\t"; if (method->NoStreaming()) { return start + - "return UnaryCallHandler(callHandlerContext: callHandlerContext) { " + "return CallHandlerFactory.makeUnary(callHandlerContext: callHandlerContext) { " "context in" "\n\t\t\t" "return { request in" @@ -175,7 +175,7 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { } if (method->ClientStreaming()) { return start + - "return ClientStreamingCallHandler(callHandlerContext: " + "return CallHandlerFactory.makeClientStreaming(callHandlerContext: " "callHandlerContext) { context in" "\n\t\t\t" "self.$MethodName$(context: context)" @@ -183,7 +183,7 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { } if (method->ServerStreaming()) { return start + - "return ServerStreamingCallHandler(callHandlerContext: " + "return CallHandlerFactory.makeServerStreaming(callHandlerContext: " "callHandlerContext) { context in" "\n\t\t\t" "return { request in" @@ -194,7 +194,7 @@ grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) { } if (method->BidiStreaming()) { return start + - "return BidirectionalStreamingCallHandler(callHandlerContext: " + "return CallHandlerFactory.makeBidirectionalStreaming(callHandlerContext: " "callHandlerContext) { context in" "\n\t\t\t" "self.$MethodName$(context: context)" diff --git a/src/idl_gen_swift.cpp b/src/idl_gen_swift.cpp index d5ff4447e..3e6c55877 100644 --- a/src/idl_gen_swift.cpp +++ b/src/idl_gen_swift.cpp @@ -142,7 +142,8 @@ class SwiftGenerator : public BaseGenerator { code_.Clear(); code_.SetValue("ACCESS", "_accessor"); code_.SetValue("TABLEOFFSET", "VTOFFSET"); - code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n"; + code_ += "// " + std::string(FlatBuffersGeneratedWarning()); + code_ += "// swiftlint:disable all\n"; code_ += "import FlatBuffers\n"; // Generate code for all the enum declarations. @@ -509,8 +510,8 @@ class SwiftGenerator : public BaseGenerator { auto default_value = IsEnum(field.value.type) ? GenEnumDefaultValue(field) : field.value.constant; auto is_enum = IsEnum(field.value.type) ? ".rawValue" : ""; - code_ += "{{VALUETYPE}}" + builder_string + "fbb.add(element: {{VALUENAME}}" + - is_enum + + code_ += "{{VALUETYPE}}" + builder_string + + "fbb.add(element: {{VALUENAME}}" + is_enum + ", def: {{CONSTANT}}, at: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; create_func_header.push_back("" + name + ": " + type + " = " + default_value); @@ -530,13 +531,17 @@ class SwiftGenerator : public BaseGenerator { } if (IsStruct(field.value.type)) { - auto struct_type = "UnsafeMutableRawPointer?"; - auto camel_case_name = "structOf" + MakeCamel(name, true); - create_func_header.push_back(camel_case_name + " " + name + ": " + struct_type + " = nil"); - auto create_struct = "guard let {{VALUENAME}} = {{VALUENAME}} else { return }; fbb.create(struct: {{VALUENAME}}, type: {{VALUETYPE}}.self); "; - auto reader_type = "fbb.add(structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; - code_ += struct_type + builder_string + create_struct + reader_type; - return; + auto struct_type = "UnsafeMutableRawPointer?"; + auto camel_case_name = "structOf" + MakeCamel(name, true); + create_func_header.push_back(camel_case_name + " " + name + ": " + + struct_type + " = nil"); + auto create_struct = + "guard let {{VALUENAME}} = {{VALUENAME}} else { return }; " + "fbb.create(struct: {{VALUENAME}}, type: {{VALUETYPE}}.self); "; + auto reader_type = + "fbb.add(structOffset: {{TABLEOFFSET}}.{{OFFSET}}.p) }"; + code_ += struct_type + builder_string + create_struct + reader_type; + return; } auto offset_type = field.value.type.base_type == BASE_TYPE_STRING @@ -879,11 +884,14 @@ class SwiftGenerator : public BaseGenerator { case BASE_TYPE_STRUCT: { if (field.value.type.struct_def && field.value.type.struct_def->fixed) { - // This is a Struct (IsStruct), not a table. We create UnsafeMutableRawPointer in this case. + // This is a Struct (IsStruct), not a table. We create + // UnsafeMutableRawPointer in this case. std::string code; - GenerateStructArgs(*field.value.type.struct_def, &code, "", "", "$0", true); + GenerateStructArgs(*field.value.type.struct_def, &code, "", "", + "$0", true); code = code.substr(0, code.size() - 2); - code_ += "let __" + name + " = obj." + name + ".map { create" + field.value.type.struct_def->name + "(" + code + ") }"; + code_ += "let __" + name + " = obj." + name + ".map { create" + + field.value.type.struct_def->name + "(" + code + ") }"; } else { code_ += "let __" + name + " = " + type + ".pack(&builder, obj: &obj." + name + ")"; diff --git a/swift/FlatBuffers.podspec b/swift/FlatBuffers.podspec index 35cdb819e..ac799464b 100644 --- a/swift/FlatBuffers.podspec +++ b/swift/FlatBuffers.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'FlatBuffers' - s.version = '0.6.0' + s.version = '0.7.0' s.summary = 'FlatBuffers: Memory Efficient Serialization Library' s.description = "FlatBuffers is a cross platform serialization library architected for diff --git a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift index e0a163863..96ed588fe 100644 --- a/swift/Sources/FlatBuffers/FlatBufferBuilder.swift +++ b/swift/Sources/FlatBuffers/FlatBufferBuilder.swift @@ -395,6 +395,14 @@ public struct FlatBufferBuilder { return Offset(offset: _bb.size) } + /// Insets a string into the buffer using UTF8 + /// - Parameter str: String to be serialized + /// - returns: The strings offset in the buffer + mutating public func create(string str: String?) -> Offset { + guard let str = str else { return Offset() } + return create(string: str) + } + /// Inserts a shared string to the buffer /// /// The function checks the stringOffsetmap if it's seen a similar string before @@ -441,6 +449,15 @@ public struct FlatBufferBuilder { track(offset: push(element: element), at: position) } + /// Adds a value into the buffer of type optional Scalar + /// - Parameters: + /// - element: Optional element of type scalar + /// - position: The predefined position of the element + mutating public func add(element: T?, at position: VOffset) { + guard let element = element else { return } + track(offset: push(element: element), at: position) + } + /// Pushes the values into the buffer /// - Parameter element: Element to insert /// - returns: Postion of the Element diff --git a/tests/FlatBuffers.GRPC.Swift/Package.swift b/tests/FlatBuffers.GRPC.Swift/Package.swift index 53250011b..1a77d7280 100644 --- a/tests/FlatBuffers.GRPC.Swift/Package.swift +++ b/tests/FlatBuffers.GRPC.Swift/Package.swift @@ -12,7 +12,7 @@ let package = Package( dependencies: [ // Main SwiftNIO package .package(path: "../../swift"), - .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.9") + .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.17") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter.grpc.swift b/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter.grpc.swift index d337ddfbb..43b81574a 100644 --- a/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter.grpc.swift +++ b/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter.grpc.swift @@ -53,13 +53,13 @@ public extension GreeterProvider { func handleMethod(_ methodName: String, callHandlerContext: CallHandlerContext) -> GRPCCallHandler? { switch methodName { case "SayHello": - return UnaryCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeUnary(callHandlerContext: callHandlerContext) { context in return { request in self.SayHello(request, context: context) } } case "SayManyHellos": - return ServerStreamingCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeServerStreaming(callHandlerContext: callHandlerContext) { context in return { request in self.SayManyHellos(request: request, context: context) } diff --git a/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter_generated.swift b/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter_generated.swift index c0793bb12..f71128267 100644 --- a/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter_generated.swift +++ b/tests/FlatBuffers.GRPC.Swift/Sources/Model/greeter_generated.swift @@ -1,4 +1,5 @@ // automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all import FlatBuffers diff --git a/tests/FlatBuffers.Test.Swift/Package.swift b/tests/FlatBuffers.Test.Swift/Package.swift index dc5ab9da6..bf02bdf2f 100644 --- a/tests/FlatBuffers.Test.Swift/Package.swift +++ b/tests/FlatBuffers.Test.Swift/Package.swift @@ -11,7 +11,7 @@ let package = Package( ], dependencies: [ .package(path: "../../swift/"), - .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.12") + .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.17") ], targets: [ .target(name: "SwiftFlatBuffers"), diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift index d6e722bc7..470e62e92 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/FlatBuffersTests.swift @@ -59,6 +59,27 @@ final class FlatBuffersTests: XCTestCase { XCTAssertEqual(c.nameVector, [78, 111, 114, 119, 97, 121]) XCTAssertEqual(c.name, country) } + + func testWriteOptionalValues() { + var b = FlatBufferBuilder() + let offset = b.create(string: nil) + createOptionalTable(b: &b, v: nil, off: offset) + let unitArray = b.sizedByteArray + // TODO: - Test function should be adjusted when the generation of optional scalars code is complete + let bb = ByteBuffer(bytes: unitArray) + let table = Table(bb: bb, position: Int32(bb.read(def: UOffset.self, position: bb.reader)) + Int32(bb.reader)) + XCTAssertEqual(unitArray, [8, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0]) + XCTAssertEqual(table.offset(4) == 0, true) + XCTAssertEqual(table.offset(6) == 0, true) + } + + func createOptionalTable(b: inout FlatBufferBuilder, v: Int?, off: Offset) { + let start = b.startTable(with: 2) + b.add(offset: off, at: 6) + b.add(element: v, at: 4) + let root = Offset(offset: b.endTable(at: start)) + b.finish(offset: root) + } } class Country { diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test.grpc.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test.grpc.swift index 2dcf0ced7..f635b750a 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test.grpc.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/monster_test.grpc.swift @@ -65,23 +65,23 @@ public extension MonsterStorageProvider { func handleMethod(_ methodName: String, callHandlerContext: CallHandlerContext) -> GRPCCallHandler? { switch methodName { case "Store": - return UnaryCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeUnary(callHandlerContext: callHandlerContext) { context in return { request in self.Store(request, context: context) } } case "Retrieve": - return ServerStreamingCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeServerStreaming(callHandlerContext: callHandlerContext) { context in return { request in self.Retrieve(request: request, context: context) } } case "GetMaxHitPoint": - return ClientStreamingCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeClientStreaming(callHandlerContext: callHandlerContext) { context in self.GetMaxHitPoint(context: context) } case "GetMinMaxHitPoints": - return BidirectionalStreamingCallHandler(callHandlerContext: callHandlerContext) { context in + return CallHandlerFactory.makeBidirectionalStreaming(callHandlerContext: callHandlerContext) { context in self.GetMinMaxHitPoints(context: context) } default: return nil; 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 f30689f2d..81a7e366a 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 @@ -1,4 +1,5 @@ // automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all import FlatBuffers diff --git a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift index 3710d7afc..4806e55a5 100644 --- a/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift +++ b/tests/FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests/union_vector_generated.swift @@ -1,4 +1,5 @@ // automatically generated by the FlatBuffers compiler, do not modify +// swiftlint:disable all import FlatBuffers