From 72d5912424211561adc6f8e7bc502180631d9f8e Mon Sep 17 00:00:00 2001 From: Kino Roy Date: Tue, 6 Sep 2022 17:34:02 -0700 Subject: [PATCH] THRIFT-5621: Add Swift tutorial Client: swift --- configure.ac | 1 + tutorial/Makefile.am | 4 + tutorial/swift/Makefile.am | 33 +++++++++ tutorial/swift/Package.swift | 53 ++++++++++++++ tutorial/swift/README.md | 11 +++ .../swift/Sources/TutorialClient/main.swift | 45 ++++++++++++ .../swift/Sources/TutorialRunner/main.swift | 36 +++++++++ .../TutorialServer/CalculatorService.swift | 73 +++++++++++++++++++ .../swift/Sources/TutorialServer/main.swift | 28 +++++++ tutorial/swift/swift-dep | 1 + 10 files changed, 285 insertions(+) create mode 100644 tutorial/swift/Makefile.am create mode 100644 tutorial/swift/Package.swift create mode 100644 tutorial/swift/README.md create mode 100644 tutorial/swift/Sources/TutorialClient/main.swift create mode 100644 tutorial/swift/Sources/TutorialRunner/main.swift create mode 100644 tutorial/swift/Sources/TutorialServer/CalculatorService.swift create mode 100644 tutorial/swift/Sources/TutorialServer/main.swift create mode 120000 tutorial/swift/swift-dep diff --git a/configure.ac b/configure.ac index 88271e676..a926e3e12 100644 --- a/configure.ac +++ b/configure.ac @@ -839,6 +839,7 @@ AC_CONFIG_FILES([ tutorial/py.tornado/Makefile tutorial/rb/Makefile tutorial/rs/Makefile + tutorial/swift/Makefile ]) if test "$have_cpp" = "yes" ; then MAYBE_CPP="cpp" ; else MAYBE_CPP="" ; fi diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index aa5712b5f..24969d13b 100644 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -86,6 +86,10 @@ if WITH_PHP SUBDIRS += php endif +if WITH_SWIFT +SUBDIRS += swift +endif + # # generate html for tutorial.thrift # diff --git a/tutorial/swift/Makefile.am b/tutorial/swift/Makefile.am new file mode 100644 index 000000000..f48456054 --- /dev/null +++ b/tutorial/swift/Makefile.am @@ -0,0 +1,33 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# Common thrift code generation rules +# +gen_swift: + $(THRIFT) --gen swift -r -o Sources/Common $(top_srcdir)/tutorial/tutorial.thrift + +tutorial: gen_swift + swift run TutorialRunner + +tutorialserver: gen_swift + swift run TutorialServer + +tutorialclient: gen_swift + swift run TutorialClient diff --git a/tutorial/swift/Package.swift b/tutorial/swift/Package.swift new file mode 100644 index 000000000..ae3f53099 --- /dev/null +++ b/tutorial/swift/Package.swift @@ -0,0 +1,53 @@ +// swift-tools-version:5.1 +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import PackageDescription + +let thriftDependency: Target.Dependency = .product(name: "Thrift", package: "swift-dep") +let package = Package( + name: "swift-tutorial", + platforms: [ + .macOS(.v10_13) + ], + products: [ + // Products define the executables and libraries a package produces, and make them visible to other packages. + .executable(name: "TutorialServer", targets: ["TutorialServer"]), + .executable(name: "TutorialClient", targets: ["TutorialClient"]), + .executable(name: "TutorialRunner", targets: ["TutorialRunner"]) + ], + dependencies: [ + // Dependencies declare other packages that this package depends on. + .package(path: "./swift-dep"), + ], + targets: [ + // Targets are the basic building blocks of a package. A target can define a module or a test suite. + // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "Common", + dependencies: [thriftDependency]), + .target( + name: "TutorialServer", + dependencies: [thriftDependency, "Common"]), + .target( + name: "TutorialClient", + dependencies: [thriftDependency, "Common"]), + .target(name: "TutorialRunner") + ] +) diff --git a/tutorial/swift/README.md b/tutorial/swift/README.md new file mode 100644 index 000000000..18a1e7b6d --- /dev/null +++ b/tutorial/swift/README.md @@ -0,0 +1,11 @@ +# Thrift Swift Tutorial +================================================== + +## Run the tutorial code (client + server): +`make tutorial` + +## Run the server only +`make tutorialserver` + +## Run the client only +`make tutorialclient` diff --git a/tutorial/swift/Sources/TutorialClient/main.swift b/tutorial/swift/Sources/TutorialClient/main.swift new file mode 100644 index 000000000..ea8720f34 --- /dev/null +++ b/tutorial/swift/Sources/TutorialClient/main.swift @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Foundation +import Thrift +import Common + +let transport = try TSocketTransport(hostname: "localhost", port: 9090) +let inOutProto = TBinaryProtocol(on: transport) +let client = CalculatorClient(inoutProtocol: inOutProto) + +try client.ping() +print("1+1= \(try client.add(num1: 1, num2: 1))") + +let work = Work(num1: 1, num2: 0, op: .divide) +do { + _ = try client.calculate(logid: 1, w: work) + assertionFailure("Hm... shouldn't be able to divide by zero") +} catch let error as InvalidOperation { + print("Invalid operation: \(error.why)") +} + +work.op = .subtract +work.num1 = 15 +work.num2 = 10 + +print("15-10= \(try client.calculate(logid: 1, w: work))") + +print("Done!") diff --git a/tutorial/swift/Sources/TutorialRunner/main.swift b/tutorial/swift/Sources/TutorialRunner/main.swift new file mode 100644 index 000000000..7d2439127 --- /dev/null +++ b/tutorial/swift/Sources/TutorialRunner/main.swift @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Foundation + +let swiftUrl = URL(fileURLWithPath: "/usr/bin/swift") +let server = Process() +server.executableURL = swiftUrl +server.arguments = ["run", "TutorialServer"] +try server.run() + +Thread.sleep(forTimeInterval: 2) + +let client = Process() +client.executableURL = swiftUrl +client.arguments = ["run", "TutorialClient"] +try client.run() +client.waitUntilExit() + +server.terminate() diff --git a/tutorial/swift/Sources/TutorialServer/CalculatorService.swift b/tutorial/swift/Sources/TutorialServer/CalculatorService.swift new file mode 100644 index 000000000..2021cfc81 --- /dev/null +++ b/tutorial/swift/Sources/TutorialServer/CalculatorService.swift @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Foundation +import Common + +struct CalculatorError: Error { + +} +class CalculatorService: Calculator { + var resultMap = [Int32:SharedStruct]() + + func ping() throws { + print("ping()") + } + + func add(num1: Int32, num2: Int32) throws -> Int32 { + print("add(\(num1), \(num2))") + return num1 + num2 + } + + func calculate(logid: Int32, w: Work) throws -> Int32 { + print("calculate(\(logid), \(w))") + let result: Int32 = try { + switch w.op { + case .add: + return w.num1 + w.num2 + case .subtract: + return w.num1 - w.num2 + case .multiply: + return w.num1 * w.num2 + case .divide: + guard w.num2 != 0 else { + throw InvalidOperation(whatOp: w.op.rawValue, why: "Cannot divide by 0") + } + return w.num1 / w.num2 + } + }() + + let resultEntry = SharedStruct(key: logid, value: "\(result)") + resultMap[logid] = resultEntry + + return result + } + + func zip() throws { + print("zip()") + } + + func getStruct(key: Int32) throws -> SharedStruct { + print("getStruct(\(key))") + guard let entry = resultMap[key] else { + throw CalculatorError() + } + return entry + } +} diff --git a/tutorial/swift/Sources/TutorialServer/main.swift b/tutorial/swift/Sources/TutorialServer/main.swift new file mode 100644 index 000000000..517a8b1f0 --- /dev/null +++ b/tutorial/swift/Sources/TutorialServer/main.swift @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Foundation +import Common +import Thrift + +let service = CalculatorService() +let processor = CalculatorProcessor(service: service) +let server = try TSocketServer(port: 9090, inProtocol: TBinaryProtocol.self, outProtocol: TBinaryProtocol.self, processor: processor) + +RunLoop.main.run() diff --git a/tutorial/swift/swift-dep b/tutorial/swift/swift-dep new file mode 120000 index 000000000..c757a77c2 --- /dev/null +++ b/tutorial/swift/swift-dep @@ -0,0 +1 @@ +../../lib/swift \ No newline at end of file