Skip to content

Commit 2b698b9

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

File tree

7 files changed

+309
-0
lines changed

7 files changed

+309
-0
lines changed

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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
// Licensed to the Apache Software Foundation (ASF) under one
5+
// or more contributor license agreements. See the NOTICE file
6+
// distributed with this work for additional information
7+
// regarding copyright ownership. The ASF licenses this file
8+
// to you under the Apache License, Version 2.0 (the
9+
// "License"); you may not use this file except in compliance
10+
// with the License. You may obtain a copy of the License at
11+
//
12+
// http://www.apache.org/licenses/LICENSE-2.0
13+
//
14+
// Unless required by applicable law or agreed to in writing,
15+
// software distributed under the License is distributed on an
16+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
// KIND, either express or implied. See the License for the
18+
// specific language governing permissions and limitations
19+
// under the License.
20+
21+
import PackageDescription
22+
23+
let package = Package(
24+
name: "GetSimpleClient",
25+
platforms: [
26+
.macOS(.v14)
27+
],
28+
dependencies: [
29+
.package(name: "Arrow", path: "vendor/Arrow")
30+
],
31+
targets: [
32+
// Targets are the basic building blocks of a package, defining a module or a test suite.
33+
// Targets can depend on other targets in this package and products from dependencies.
34+
.executableTarget(
35+
name: "GetSimpleClient",
36+
dependencies: [
37+
.product(name: "Arrow", package: "Arrow")
38+
]
39+
),
40+
]
41+
)
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+
if let writeData = data {
27+
let arrowReader = ArrowReader()
28+
switch arrowReader.fromStream(writeData) {
29+
case .success(let result):
30+
let recordBatches = result.batches
31+
print("recordBatch: \(recordBatches.count)")
32+
let rb = recordBatches[0]
33+
print("recordBatch values: \(rb.length)")
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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// swift-tools-version: 6.0
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
// Licensed to the Apache Software Foundation (ASF) under one
5+
// or more contributor license agreements. See the NOTICE file
6+
// distributed with this work for additional information
7+
// regarding copyright ownership. The ASF licenses this file
8+
// to you under the Apache License, Version 2.0 (the
9+
// "License"); you may not use this file except in compliance
10+
// with the License. You may obtain a copy of the License at
11+
//
12+
// http://www.apache.org/licenses/LICENSE-2.0
13+
//
14+
// Unless required by applicable law or agreed to in writing,
15+
// software distributed under the License is distributed on an
16+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
// KIND, either express or implied. See the License for the
18+
// specific language governing permissions and limitations
19+
// under the License.
20+
21+
import PackageDescription
22+
23+
let package = Package(
24+
name: "GetSimpleClient",
25+
platforms: [
26+
.macOS(.v14)
27+
],
28+
dependencies: [
29+
.package(name: "Arrow", path: "vendor/Arrow"),
30+
.package(url: "https://github.com/hummingbird-project/hummingbird.git", from: "2.3.0"),
31+
],
32+
targets: [
33+
// Targets are the basic building blocks of a package, defining a module or a test suite.
34+
// Targets can depend on other targets in this package and products from dependencies.
35+
.executableTarget(
36+
name: "GetSimpleClient",
37+
dependencies: [
38+
.product(name: "Arrow", package: "Arrow"),
39+
.product(name: "Hummingbird", package: "hummingbird"),
40+
]
41+
),
42+
]
43+
)
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: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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(_ numRecords: UInt32) throws -> RecordBatch {
23+
let doubleBuilder: NumberArrayBuilder<Double> = try ArrowArrayBuilders.loadNumberArrayBuilder()
24+
let stringBuilder = try ArrowArrayBuilders.loadStringArrayBuilder()
25+
let date32Builder = try ArrowArrayBuilders.loadDate32ArrayBuilder()
26+
let date2 = Date(timeIntervalSinceReferenceDate: 86400 * 1)
27+
let date1 = Date(timeIntervalSinceReferenceDate: 86400 * 5000 + 352)
28+
for idx in 0..<numRecords {
29+
doubleBuilder.append(11.11 * Double(idx))
30+
stringBuilder.append("test\(idx)")
31+
if (idx & 1) == 1 {
32+
date32Builder.append(date1)
33+
} else {
34+
date32Builder.append(date2)
35+
}
36+
}
37+
38+
let doubleHolder = ArrowArrayHolderImpl(try doubleBuilder.finish())
39+
let stringHolder = ArrowArrayHolderImpl(try stringBuilder.finish())
40+
let date32Holder = ArrowArrayHolderImpl(try date32Builder.finish())
41+
let result = RecordBatch.Builder()
42+
.addColumn("col1", arrowArray: doubleHolder)
43+
.addColumn("col2", arrowArray: stringHolder)
44+
.addColumn("col3", arrowArray: date32Holder)
45+
.finish()
46+
switch result {
47+
case .success(let recordBatch):
48+
return recordBatch
49+
case .failure(let error):
50+
throw error
51+
}
52+
}
53+
54+
let router = Router()
55+
router.get("/") { request, _ -> ByteBuffer in
56+
print("received request from client")
57+
let recordBatchs = [try makeRecordBatch(4), try makeRecordBatch(3)]
58+
let arrowWriter = ArrowWriter()
59+
let writerInfo = ArrowWriter.Info(.recordbatch, schema: recordBatchs[0].schema, batches: recordBatchs)
60+
switch arrowWriter.toStream(writerInfo) {
61+
case .success(let writeData):
62+
print("sending recordBatchs: \(recordBatchs.count)")
63+
return ByteBuffer(data: writeData)
64+
case.failure(let error):
65+
throw error
66+
}
67+
}
68+
69+
// create application using router
70+
let app = Application(
71+
router: router,
72+
configuration: .init(address: .hostname("127.0.0.1", port: 8081))
73+
)
74+
75+
try await app.runService()

0 commit comments

Comments
 (0)