Skip to content

Commit 4fded84

Browse files
Merge pull request #14 from willtemperley/main
Reinstate C import / export
2 parents 949f874 + 48b2a2f commit 4fded84

12 files changed

+903
-182
lines changed

Sources/Arrow/ArrowArray.swift

Lines changed: 71 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16+
import ArrowC
1617
import Foundation
1718

1819
/// A type-erased ArrowArray.
@@ -25,9 +26,10 @@ public protocol AnyArrowArray {
2526
var bufferDataSizes: [Int] { get }
2627
func asAny(_ index: UInt) -> Any?
2728
func asString(_ index: UInt) -> String
29+
func setCArrayPtr(_ cArrayPtr: UnsafePointer<ArrowC.ArrowArray>?)
2830
}
2931

30-
// MARK: - Core Protocol
32+
// MARK: Core Protocol
3133

3234
/// The interface for Arrow array types.
3335
public protocol ArrowArray<ItemType>: AnyArrowArray {
@@ -37,8 +39,42 @@ public protocol ArrowArray<ItemType>: AnyArrowArray {
3739
subscript(_ index: UInt) -> ItemType? { get }
3840
}
3941

40-
// MARK: - Default Implementations
41-
extension ArrowArray {
42+
public class ArrowArrayBase<T>: ArrowArray {
43+
44+
public var arrowData: ArrowData
45+
public var cArrayPtr: UnsafePointer<ArrowC.ArrowArray>? = nil
46+
47+
required public init(_ arrowData: ArrowData) throws(ArrowError) {
48+
self.arrowData = arrowData
49+
}
50+
51+
public subscript(_ index: UInt) -> T? {
52+
fatalError("Base class is abstract.")
53+
}
54+
55+
public func asString(_ index: UInt) -> String {
56+
guard let value = self[index] else {
57+
return ""
58+
}
59+
return "\(value)"
60+
}
61+
62+
public func asAny(_ index: UInt) -> Any? {
63+
self[index]
64+
}
65+
66+
public func setCArrayPtr(_ cArrayPtr: UnsafePointer<ArrowC.ArrowArray>?) {
67+
self.cArrayPtr = cArrayPtr
68+
}
69+
70+
deinit {
71+
if let cArrayPtr = cArrayPtr {
72+
ArrowCImporter.release(cArrayPtr)
73+
}
74+
}
75+
}
76+
77+
extension ArrowArrayBase {
4278
public var nullCount: UInt {
4379
arrowData.nullCount
4480
}
@@ -63,32 +99,19 @@ extension ArrowArray {
6399
arrowData.buffers.map { Int($0.capacity) }
64100
}
65101

66-
public func isNull(at index: UInt) throws -> Bool {
102+
public func isNull(at index: UInt) throws(ArrowError) -> Bool {
67103
if index >= self.length {
68-
throw ArrowError.outOfBounds(index: Int64(index))
104+
throw .outOfBounds(index: Int64(index))
69105
}
70106
return arrowData.isNull(index)
71107
}
72-
73-
public func asString(_ index: UInt) -> String {
74-
guard let value = self[index] else {
75-
return ""
76-
}
77-
return "\(value)"
78-
}
79-
80-
public func asAny(_ index: UInt) -> Any? {
81-
self[index]
82-
}
83108
}
84109

85110
// MARK: Fixed Arrays
86111

87-
public protocol FixedArrayProtocol: ArrowArray where ItemType: BitwiseCopyable {
88-
}
112+
public class FixedArray<T>: ArrowArrayBase<T> where T: BitwiseCopyable {
89113

90-
extension FixedArrayProtocol {
91-
public subscript(_ index: UInt) -> ItemType? {
114+
public override subscript(_ index: UInt) -> ItemType? {
92115
if arrowData.isNull(index) {
93116
return nil
94117
}
@@ -106,28 +129,9 @@ extension FixedArrayProtocol {
106129
}
107130
}
108131

109-
public struct FixedArray<T>: FixedArrayProtocol where T: BitwiseCopyable {
110-
public typealias ItemType = T
111-
public let arrowData: ArrowData
132+
public class StringArray: ArrowArrayBase<String> {
112133

113-
public init(arrowData: ArrowData) {
114-
self.arrowData = arrowData
115-
}
116-
117-
public init(_ arrowData: ArrowData) {
118-
self.arrowData = arrowData
119-
}
120-
}
121-
122-
public struct StringArray: ArrowArray {
123-
public typealias ItemType = String
124-
public let arrowData: ArrowData
125-
126-
public init(_ arrowData: ArrowData) {
127-
self.arrowData = arrowData
128-
}
129-
130-
public subscript(_ index: UInt) -> String? {
134+
public override subscript(_ index: UInt) -> String? {
131135
let offsetIndex = MemoryLayout<Int32>.stride * Int(index)
132136
if self.arrowData.isNull(index) {
133137
return nil
@@ -138,8 +142,8 @@ public struct StringArray: ArrowArray {
138142

139143
var startIndex: Int32 = 0
140144
if index > 0 {
141-
startIndex = offsets.rawPointer.advanced(by: offsetIndex).load(
142-
as: Int32.self)
145+
startIndex = offsets.rawPointer.advanced(by: offsetIndex)
146+
.load(as: Int32.self)
143147
}
144148

145149
let endIndex = offsets.rawPointer.advanced(
@@ -150,21 +154,16 @@ public struct StringArray: ArrowArray {
150154
let rawPointer = values.rawPointer.advanced(by: Int(startIndex))
151155
.bindMemory(to: UInt8.self, capacity: arrayLength)
152156
let buffer = UnsafeBufferPointer<UInt8>(
153-
start: rawPointer, count: arrayLength)
154-
let byteArray = Array(buffer)
155-
return String(data: Data(byteArray), encoding: .utf8)
157+
start: rawPointer,
158+
count: arrayLength
159+
)
160+
return String(bytes: buffer, encoding: .utf8)
156161
}
157162
}
158163

159-
public struct BoolArray: ArrowArray {
160-
public typealias ItemType = Bool
161-
public let arrowData: ArrowData
164+
public class BoolArray: ArrowArrayBase<Bool> {
162165

163-
public init(_ arrowData: ArrowData) {
164-
self.arrowData = arrowData
165-
}
166-
167-
public subscript(_ index: UInt) -> Bool? {
166+
public override subscript(_ index: UInt) -> Bool? {
168167
if self.arrowData.isNull(index) {
169168
return nil
170169
}
@@ -173,15 +172,9 @@ public struct BoolArray: ArrowArray {
173172
}
174173
}
175174

176-
public struct Date32Array: ArrowArray {
177-
public typealias ItemType = Date
178-
public let arrowData: ArrowData
175+
public class Date32Array: ArrowArrayBase<Date> {
179176

180-
public init(_ arrowData: ArrowData) {
181-
self.arrowData = arrowData
182-
}
183-
184-
public subscript(_ index: UInt) -> Date? {
177+
public override subscript(_ index: UInt) -> Date? {
185178
if self.arrowData.isNull(index) {
186179
return nil
187180
}
@@ -193,15 +186,9 @@ public struct Date32Array: ArrowArray {
193186
}
194187
}
195188

196-
public struct Date64Array: ArrowArray {
197-
public typealias ItemType = Date
198-
public let arrowData: ArrowData
189+
public class Date64Array: ArrowArrayBase<Date> {
199190

200-
public init(_ arrowData: ArrowData) {
201-
self.arrowData = arrowData
202-
}
203-
204-
public subscript(_ index: UInt) -> Date? {
191+
public override subscript(_ index: UInt) -> Date? {
205192
if self.arrowData.isNull(index) {
206193
return nil
207194
}
@@ -217,13 +204,7 @@ public typealias Time64Array = FixedArray<Time64>
217204

218205
public typealias Time32Array = FixedArray<Time32>
219206

220-
public struct TimestampArray: FixedArrayProtocol {
221-
public typealias ItemType = Timestamp
222-
public let arrowData: ArrowData
223-
224-
public init(_ arrowData: ArrowData) {
225-
self.arrowData = arrowData
226-
}
207+
public class TimestampArray: FixedArray<Timestamp> {
227208

228209
public struct FormattingOptions: Equatable {
229210
public var dateFormat: String = "yyyy-MM-dd HH:mm:ss.SSS"
@@ -256,7 +237,7 @@ public struct TimestampArray: FixedArrayProtocol {
256237
private var cachedFormatter: DateFormatter?
257238
private var cachedOptions: FormattingOptions?
258239

259-
public mutating func formattedDate(
240+
public func formattedDate(
260241
at index: UInt,
261242
options: FormattingOptions = FormattingOptions()
262243
) -> String? {
@@ -300,8 +281,7 @@ public struct TimestampArray: FixedArrayProtocol {
300281
return Date(timeIntervalSince1970: timeInterval)
301282
}
302283

303-
// TODO: Mutating function to hack around cached formatter
304-
public mutating func asString(_ index: UInt) -> String {
284+
public override func asString(_ index: UInt) -> String {
305285
if let formatted = formattedDate(at: index) {
306286
return formatted
307287
} else {
@@ -310,13 +290,7 @@ public struct TimestampArray: FixedArrayProtocol {
310290
}
311291
}
312292

313-
public struct BinaryArray: ArrowArray {
314-
public typealias ItemType = Data
315-
public let arrowData: ArrowData
316-
317-
public init(_ arrowData: ArrowData) {
318-
self.arrowData = arrowData
319-
}
293+
public class BinaryArray: ArrowArrayBase<Data> {
320294

321295
public struct Options {
322296
public var printAsHex = false
@@ -325,7 +299,7 @@ public struct BinaryArray: ArrowArray {
325299

326300
public var options = Options()
327301

328-
public subscript(_ index: UInt) -> Data? {
302+
public override subscript(_ index: UInt) -> Data? {
329303
let offsetIndex = MemoryLayout<Int32>.stride * Int(index)
330304
if self.arrowData.isNull(index) {
331305
return nil
@@ -350,7 +324,7 @@ public struct BinaryArray: ArrowArray {
350324
return Data(byteArray)
351325
}
352326

353-
public func asString(_ index: UInt) -> String {
327+
public override func asString(_ index: UInt) -> String {
354328
guard let data = self[index] else { return "" }
355329
if options.printAsHex {
356330
return data.hexEncodedString()
@@ -364,13 +338,14 @@ public struct BinaryArray: ArrowArray {
364338
}
365339
}
366340

367-
public struct NestedArray: ArrowArray, AnyArrowArray {
368-
public typealias ItemType = [Any?]
369-
public let arrowData: ArrowData
341+
public class NestedArray: ArrowArrayBase<[Any?]> {
342+
370343
private var children: [AnyArrowArray]?
371344

372-
public init(_ arrowData: ArrowData) throws(ArrowError) {
373-
self.arrowData = arrowData
345+
public required init(
346+
_ arrowData: ArrowData
347+
) throws(ArrowError) {
348+
try super.init(arrowData)
374349

375350
switch arrowData.type {
376351
case .list(let field):
@@ -398,7 +373,7 @@ public struct NestedArray: ArrowArray, AnyArrowArray {
398373
}
399374
}
400375

401-
public subscript(_ index: UInt) -> [Any?]? {
376+
public override subscript(_ index: UInt) -> [Any?]? {
402377
if self.arrowData.isNull(index) {
403378
return nil
404379
}
@@ -432,7 +407,7 @@ public struct NestedArray: ArrowArray, AnyArrowArray {
432407
}
433408
}
434409

435-
public func asString(_ index: UInt) -> String {
410+
public override func asString(_ index: UInt) -> String {
436411
switch arrowData.type {
437412
case .list(let _):
438413
if self.arrowData.isNull(index) {

Sources/Arrow/ArrowArrayBuilder.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,10 @@ extension ArrowArrayBuilderInternal {
8282

8383
// MARK: Base implementation.
8484

85-
// Note: It would be preferable to move all of this to a protocol, however
85+
// Note: It would be preferable to move this to a protocol, however
8686
// ListArrayBuilder overrides finish. This is delicate because protocol
87-
// extension method dispatching means the
87+
// extension method dispatching uses static dispatch, so overrides are not
88+
// called when type erasure is used in nested types.
8889
public class ArrowArrayBuilderBase<
8990
BufferBuilder: ArrowBufferBuilder,
9091
ArrayType: ArrowArray<BufferBuilder.ItemType>

Sources/Arrow/ArrowArrayLoader.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,41 +21,41 @@ struct ArrowArrayLoader {
2121
) throws(ArrowError) -> any AnyArrowArray {
2222
switch arrowType {
2323
case .int8:
24-
return FixedArray<Int8>(arrowData)
24+
return try FixedArray<Int8>(arrowData)
2525
case .int16:
26-
return FixedArray<Int16>(arrowData)
26+
return try FixedArray<Int16>(arrowData)
2727
case .int32:
28-
return FixedArray<Int32>(arrowData)
28+
return try FixedArray<Int32>(arrowData)
2929
case .int64:
30-
return FixedArray<Int64>(arrowData)
30+
return try FixedArray<Int64>(arrowData)
3131
case .uint8:
32-
return FixedArray<UInt8>(arrowData)
32+
return try FixedArray<UInt8>(arrowData)
3333
case .uint16:
34-
return FixedArray<UInt16>(arrowData)
34+
return try FixedArray<UInt16>(arrowData)
3535
case .uint32:
36-
return FixedArray<UInt32>(arrowData)
36+
return try FixedArray<UInt32>(arrowData)
3737
case .uint64:
38-
return FixedArray<UInt64>(arrowData)
38+
return try FixedArray<UInt64>(arrowData)
3939
case .float64:
40-
return FixedArray<Double>(arrowData)
40+
return try FixedArray<Double>(arrowData)
4141
case .float32:
42-
return FixedArray<Float>(arrowData)
42+
return try FixedArray<Float>(arrowData)
4343
case .date32:
44-
return Date32Array(arrowData)
44+
return try Date32Array(arrowData)
4545
case .date64:
46-
return Date64Array(arrowData)
46+
return try Date64Array(arrowData)
4747
case .time32:
48-
return Time32Array(arrowData)
48+
return try Time32Array(arrowData)
4949
case .time64:
50-
return Time64Array(arrowData)
50+
return try Time64Array(arrowData)
5151
case .timestamp:
52-
return TimestampArray(arrowData)
52+
return try TimestampArray(arrowData)
5353
case .utf8:
54-
return StringArray(arrowData)
54+
return try StringArray(arrowData)
5555
case .boolean:
56-
return BoolArray(arrowData)
56+
return try BoolArray(arrowData)
5757
case .binary:
58-
return BinaryArray(arrowData)
58+
return try BinaryArray(arrowData)
5959
case .strct(let _):
6060
return try NestedArray(arrowData)
6161
case .list(let _):

0 commit comments

Comments
 (0)