Skip to content

Commit c422e9a

Browse files
committed
GH-40488: [Swift] Add simple get swift example
1 parent e006c3c commit c422e9a

7 files changed

Lines changed: 277 additions & 0 deletions

File tree

http/get_simple/swift/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/
8+
.netrc
9+
Package.resolved
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "GetSimpleClient",
8+
platforms: [
9+
.macOS(.v14)
10+
],
11+
dependencies: [
12+
.package(name: "Arrow", path: "vendor/Arrow")
13+
],
14+
targets: [
15+
// Targets are the basic building blocks of a package, defining a module or a test suite.
16+
// Targets can depend on other targets in this package and products from dependencies.
17+
.executableTarget(
18+
name: "GetSimpleClient",
19+
dependencies: [
20+
.product(name: "Arrow", package: "Arrow")
21+
]
22+
),
23+
]
24+
)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!---
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
# HTTP GET Arrow Data: Simple Swift Client Example
21+
22+
This directory contains a minimal example of an HTTP client implemented in Swift. The client:
23+
1. Sends an HTTP GET request to a server.
24+
2. Receives an HTTP 200 response from the server, with the response body containing an Arrow IPC stream record batch.
25+
3. Prints some of the record batches attributes and data to the terminal
26+
27+
To run this example, first start one of the server examples in the parent directory, then:
28+
1. download and copy Apache Arrow Swift's Arrow folder into the vendor/Arrow folder:
29+
30+
```sh
31+
git clone --filter=blob:none --no-checkout --depth 1 --sparse https://github.com/apache/arrow.git
32+
pushd arrow
33+
git sparse-checkout add swift/Arrow
34+
git checkout
35+
popd
36+
mkdir -p vendor/Arrow
37+
mv arrow/swift/Arrow vendor
38+
rm -rf arrow
39+
```
40+
41+
2. run:
42+
43+
```sh
44+
swift run
45+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import Foundation
19+
import Arrow
20+
21+
let sem = DispatchSemaphore(value: 0)
22+
let url = URL(string: "http://127.0.0.1:8081")!
23+
print("sending request to server")
24+
let task = URLSession.shared.dataTask(with: url) { data, response, error in
25+
defer {sem.signal()}
26+
print("HTTP Request Failed \(error)")
27+
if let writeData = data {
28+
let arrowReader = ArrowReader()
29+
switch arrowReader.fromStream(writeData) {
30+
case .success(let result):
31+
let recordBatches = result.batches
32+
print("recordBatch columns: \(recordBatches.count)")
33+
let rb = recordBatches[0]
34+
print("recordBatch columns: \(rb.columnCount)")
35+
for (idx, column) in rb.columns.enumerated() {
36+
print("col \(idx)")
37+
let array = column.array
38+
for idx in 0..<array.length {
39+
print("data col \(idx): \(String(describing:array.asAny(idx)))")
40+
}
41+
}
42+
case.failure(let error):
43+
print("error: \(error)")
44+
}
45+
} else if let error = error {
46+
print("HTTP Request Failed \(error)")
47+
}
48+
}
49+
50+
task.resume()
51+
_ = sem.wait(timeout: .distantFuture)
52+
print("done running http server")
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "GetSimpleClient",
8+
platforms: [
9+
.macOS(.v14)
10+
],
11+
dependencies: [
12+
.package(name: "Arrow", path: "vendor/Arrow"),
13+
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.3.0"),
14+
],
15+
targets: [
16+
// Targets are the basic building blocks of a package, defining a module or a test suite.
17+
// Targets can depend on other targets in this package and products from dependencies.
18+
.executableTarget(
19+
name: "GetSimpleClient",
20+
dependencies: [
21+
.product(name: "Arrow", package: "Arrow"),
22+
.product(name: "Hummingbird", package: "hummingbird"),
23+
]
24+
),
25+
]
26+
)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<!---
2+
Licensed to the Apache Software Foundation (ASF) under one
3+
or more contributor license agreements. See the NOTICE file
4+
distributed with this work for additional information
5+
regarding copyright ownership. The ASF licenses this file
6+
to you under the Apache License, Version 2.0 (the
7+
"License"); you may not use this file except in compliance
8+
with the License. You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing,
13+
software distributed under the License is distributed on an
14+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
KIND, either express or implied. See the License for the
16+
specific language governing permissions and limitations
17+
under the License.
18+
-->
19+
20+
# HTTP GET Arrow Data: Simple Swift Server Example
21+
22+
This directory contains a minimal example of an HTTP server implemented in Swift. The server:
23+
24+
1. Creates a record batches and populates it with synthesized data.
25+
2. Listens for HTTP requests from clients.
26+
3. Upon receiving a request, sends an HTTP 200 response with the body containing an Arrow IPC stream of record batches.
27+
To run this example:
28+
29+
```sh
30+
git clone --filter=blob:none --no-checkout --depth 1 --sparse https://github.com/apache/arrow.git
31+
pushd arrow
32+
git sparse-checkout add swift/Arrow
33+
git checkout
34+
popd
35+
mkdir -p vendor/Arrow
36+
mv arrow/swift/Arrow vendor
37+
rm -rf arrow
38+
```
39+
40+
2. run:
41+
42+
```sh
43+
swift run
44+
```
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import Foundation
19+
import Arrow
20+
import Hummingbird
21+
22+
func makeRecordBatch() throws -> RecordBatch {
23+
let doubleBuilder: NumberArrayBuilder<Double> = try ArrowArrayBuilders.loadNumberArrayBuilder()
24+
doubleBuilder.append(11.11)
25+
doubleBuilder.append(22.22)
26+
doubleBuilder.append(33.33)
27+
doubleBuilder.append(44.44)
28+
let stringBuilder = try ArrowArrayBuilders.loadStringArrayBuilder()
29+
stringBuilder.append("test10")
30+
stringBuilder.append("test22")
31+
stringBuilder.append("test33")
32+
stringBuilder.append("test44")
33+
let date32Builder = try ArrowArrayBuilders.loadDate32ArrayBuilder()
34+
let date2 = Date(timeIntervalSinceReferenceDate: 86400 * 1)
35+
let date1 = Date(timeIntervalSinceReferenceDate: 86400 * 5000 + 352)
36+
date32Builder.append(date1)
37+
date32Builder.append(date2)
38+
date32Builder.append(date1)
39+
date32Builder.append(date2)
40+
let doubleHolder = ArrowArrayHolderImpl(try doubleBuilder.finish())
41+
let stringHolder = ArrowArrayHolderImpl(try stringBuilder.finish())
42+
let date32Holder = ArrowArrayHolderImpl(try date32Builder.finish())
43+
let result = RecordBatch.Builder()
44+
.addColumn("col1", arrowArray: doubleHolder)
45+
.addColumn("col2", arrowArray: stringHolder)
46+
.addColumn("col3", arrowArray: date32Holder)
47+
.finish()
48+
switch result {
49+
case .success(let recordBatch):
50+
return recordBatch
51+
case .failure(let error):
52+
throw error
53+
}
54+
}
55+
56+
let router = Router()
57+
router.get("/") { request, _ -> ByteBuffer in
58+
print("received request from client")
59+
let recordBatch = try makeRecordBatch()
60+
let arrowWriter = ArrowWriter()
61+
let writerInfo = ArrowWriter.Info(.recordbatch, schema: recordBatch.schema, batches: [recordBatch])
62+
switch arrowWriter.toStream(writerInfo) {
63+
case .success(let writeData):
64+
print("sending recordBatch with row count: \(recordBatch.length)")
65+
return ByteBuffer(data: writeData)
66+
case.failure(let error):
67+
throw error
68+
}
69+
}
70+
71+
// create application using router
72+
let app = Application(
73+
router: router,
74+
configuration: .init(address: .hostname("127.0.0.1", port: 8081))
75+
)
76+
77+
try await app.runService()

0 commit comments

Comments
 (0)