Skip to content

Commit 35e2ea1

Browse files
authored
add support for array output and by reference (#198)
* move array methods over to specific class * working mostly, a few test failures * fix array testsd * fix indentation for in and out * fix it and ship it * insert assignment at front * some last fixes * update can write * delete debug.log...gross * remove extra whitespace * catch and free memory so it doesn't leak
1 parent 9a4be08 commit 35e2ea1

36 files changed

+3483
-665
lines changed

Diff for: swiftwinrt/Resources/Support/Array+FromAbi.swift

-7
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,6 @@ extension Array {
3535
}
3636
}
3737

38-
@_spi(WinRTInternal)
39-
extension Array {
40-
public static func from<Bridge: AbiInterfaceBridge>(abiBridge: Bridge.Type, start: UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?, count: UInt32) -> [Element] where Element == Bridge.SwiftProjection? {
41-
UnsafeBufferPointer(start: start, count: Int(count)).map { InterfaceWrapperBase<Bridge>.unwrapFrom(abi: ComPtr($0)) }
42-
}
43-
}
44-
4538
@_spi(WinRTInternal)
4639
extension Array {
4740
public static func from<Bridge: AbiBridge>(abiBridge: Bridge.Type, abi: WinRTArrayAbi<UnsafeMutablePointer<Bridge.CABI>?>) -> [Element] where Element == Bridge.SwiftProjection?, Bridge.SwiftProjection: WinRTClass {

Diff for: swiftwinrt/Resources/Support/Array+ToAbi.swift

+77-11
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,121 @@ import Foundation
33

44
@_spi(WinRTInternal)
55
extension Array where Element: ToAbi {
6-
public func toABI(_ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<Element.ABI>?) throws -> Void) throws {
6+
public func toABI(_ withAbi: (WinRTArrayAbi<Element.ABI>) throws -> Void) throws {
77
let abiArray: [Element.ABI] = try map { try $0.toABI() }
88
try abiArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
99
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: Element.ABI.self)
10-
try withAbi(UInt32(count), .init(mutating: bytesPtr))
10+
try withAbi((count: UInt32(count), start: .init(mutating: bytesPtr)))
11+
}
12+
}
13+
14+
public func fill(abi: UnsafeMutablePointer<UnsafeMutablePointer<Element.ABI>?>?) throws {
15+
guard let abi else { return }
16+
abi.pointee = CoTaskMemAlloc(UInt64(MemoryLayout<Element.ABI>.size * count)).assumingMemoryBound(to: Element.ABI.self)
17+
do {
18+
try fill(abi: abi.pointee)
19+
} catch {
20+
CoTaskMemFree(abi.pointee)
21+
throw error
22+
}
23+
}
24+
25+
public func fill(abi: UnsafeMutablePointer<Element.ABI>?) throws {
26+
guard let abi else { return }
27+
for (index, element) in enumerated() {
28+
abi[index] = try element.toABI()
1129
}
1230
}
1331
}
1432

1533
@_spi(WinRTInternal)
1634
extension Array where Element: Numeric {
17-
public func toABI(_ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<Element>?) throws -> Void) throws {
35+
public func toABI(_ withAbi: (WinRTArrayAbi<Element>) throws -> Void) throws {
1836
try withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
1937
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: Element.self)
20-
try withAbi(UInt32(count), .init(mutating: bytesPtr))
38+
try withAbi((count: UInt32(count), start: .init(mutating: bytesPtr)))
2139
}
2240
}
41+
42+
public func fill(abi: UnsafeMutablePointer<Element>?) {
43+
guard let abi else { return }
44+
_ = UnsafeMutableBufferPointer(start: abi, count: count).update(from: self)
45+
}
46+
47+
public func fill(abi: UnsafeMutablePointer<UnsafeMutablePointer<Element>?>?) {
48+
guard let abi else { return }
49+
abi.pointee = CoTaskMemAlloc(UInt64(MemoryLayout<Element>.size * count)).assumingMemoryBound(to: Element.self)
50+
fill(abi: abi.pointee)
51+
}
2352
}
2453

2554
@_spi(WinRTInternal)
2655
extension Array where Element: RawRepresentable, Element.RawValue: Numeric {
27-
public func toABI(_ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<Element>?) throws -> Void) throws {
56+
public func toABI(_ withAbi: (WinRTArrayAbi<Element>) throws -> Void) throws {
2857
try withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
2958
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: Element.self)
30-
try withAbi(UInt32(count), .init(mutating: bytesPtr))
59+
try withAbi((count: UInt32(count), start: .init(mutating: bytesPtr)))
3160
}
3261
}
62+
63+
public func fill(abi: UnsafeMutablePointer<Element>?) {
64+
guard let abi else { return }
65+
_ = UnsafeMutableBufferPointer(start: abi, count: count).update(from: self)
66+
}
67+
68+
public func fill(abi: UnsafeMutablePointer<UnsafeMutablePointer<Element>?>?) {
69+
guard let abi else { return }
70+
abi.pointee = CoTaskMemAlloc(UInt64(MemoryLayout<Element>.size * count)).assumingMemoryBound(to: Element.self)
71+
fill(abi: abi.pointee)
72+
}
3373
}
3474

3575
@_spi(WinRTInternal)
3676
extension Array {
37-
public func toABI<Bridge: AbiInterfaceBridge>(abiBridge: Bridge.Type, _ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?) throws -> Void) throws where Element == Bridge.SwiftProjection? {
77+
public func toABI<Bridge: AbiInterfaceBridge>(abiBridge: Bridge.Type, _ withAbi: (WinRTArrayAbi<UnsafeMutablePointer<Bridge.CABI>?>) throws -> Void) throws where Element == Bridge.SwiftProjection? {
3878
let abiWrapperArray: [InterfaceWrapperBase<Bridge>?] = map { .init($0) }
3979
let abiArray = try abiWrapperArray.map { try $0?.toABI{ $0 } }
4080
try abiArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
4181
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: UnsafeMutablePointer<Bridge.CABI>?.self)
42-
try withAbi(UInt32(count), .init(mutating: bytesPtr))
82+
try withAbi((count: UInt32(count), start: .init(mutating: bytesPtr)))
83+
}
84+
}
85+
86+
public func fill<Bridge: AbiInterfaceBridge>(abi: UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?, abiBridge: Bridge.Type) where Element == Bridge.SwiftProjection? {
87+
guard let abi else { return }
88+
for (index, element) in enumerated() {
89+
let wrapper = InterfaceWrapperBase<Bridge>(element)
90+
wrapper?.copyTo(&abi[index])
4391
}
4492
}
93+
94+
public func fill<Bridge: AbiInterfaceBridge>(abi: UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?>?, abiBridge: Bridge.Type) where Element == Bridge.SwiftProjection? {
95+
guard let abi else { return }
96+
abi.pointee = CoTaskMemAlloc(UInt64(MemoryLayout<UnsafeMutablePointer<Bridge.CABI>>.size * count)).assumingMemoryBound(to: UnsafeMutablePointer<Bridge.CABI>?.self)
97+
fill(abi: abi.pointee, abiBridge: abiBridge)
98+
}
4599
}
46100

47101
@_spi(WinRTInternal)
48102
extension Array {
49-
public func toABI<Bridge: AbiBridge>(abiBridge: Bridge.Type, _ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?) throws -> Void) throws where Element == Bridge.SwiftProjection?, Bridge.SwiftProjection: WinRTClass {
103+
public func toABI<Bridge: AbiBridge>(abiBridge: Bridge.Type, _ withAbi: (WinRTArrayAbi<UnsafeMutablePointer<Bridge.CABI>?>) throws -> Void) throws where Element == Bridge.SwiftProjection?, Bridge.SwiftProjection: WinRTClass {
50104
let abiArray: [UnsafeMutablePointer<Bridge.CABI>?] = map { RawPointer($0) }
51105
try abiArray.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
52106
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: UnsafeMutablePointer<Bridge.CABI>?.self)
53-
try withAbi(UInt32(count), .init(mutating: bytesPtr))
107+
try withAbi((count: UInt32(count), start: .init(mutating: bytesPtr)))
108+
}
109+
}
110+
111+
public func fill<Bridge: AbiBridge>(abi: UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?, abiBridge: Bridge.Type) where Element == Bridge.SwiftProjection?, Bridge.SwiftProjection: WinRTClass {
112+
guard let abi else { return }
113+
for (index, element) in enumerated() {
114+
abi[index] = RawPointer(element)
54115
}
55116
}
56-
}
57117

118+
public func fill<Bridge: AbiBridge>(abi: UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<Bridge.CABI>?>?>?, abiBridge: Bridge.Type) where Element == Bridge.SwiftProjection?, Bridge.SwiftProjection: WinRTClass {
119+
guard let abi else { return }
120+
abi.pointee = CoTaskMemAlloc(UInt64(MemoryLayout<UnsafeMutablePointer<Bridge.CABI>>.size * count)).assumingMemoryBound(to: UnsafeMutablePointer<Bridge.CABI>?.self)
121+
fill(abi: abi.pointee, abiBridge: abiBridge)
122+
}
123+
}

Diff for: swiftwinrt/Resources/Support/Array+toVector.swift

+24
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ internal class ArrayVector<T> : IVector {
3131
func replaceAll(_ items: [T]) {
3232
storage = items
3333
}
34+
35+
func getMany(_ startIndex: UInt32, _ items: inout [T]) -> UInt32 {
36+
let count = Swift.min(UInt32(storage.count) - startIndex, UInt32(items.count))
37+
for i in 0..<count {
38+
items[Int(i)] = storage[Int(startIndex + i)]
39+
}
40+
return count
41+
}
3442
}
3543

3644
extension ArrayVector where T: Equatable {
@@ -56,6 +64,14 @@ internal class ArrayVectorView<T> : IVectorView {
5664
func indexOf(_ item: T, _ index: inout UInt32) -> Bool { return false }
5765

5866
func first() -> AnyIIterator<T>? { ArrayIterator(storage) }
67+
68+
func getMany(_ startIndex: UInt32, _ items: inout [T]) -> UInt32 {
69+
let count = Swift.min(UInt32(storage.count) - startIndex, UInt32(items.count))
70+
for i in 0..<count {
71+
items[Int(i)] = storage[Int(startIndex + i)]
72+
}
73+
return count
74+
}
5975
}
6076

6177
extension ArrayVectorView where T: Equatable {
@@ -82,4 +98,12 @@ class ArrayIterator<T>: IIterator {
8298
var hasCurrent: Bool { index < storage.count }
8399

84100
func queryInterface(_ iid: IID) -> IUnknownRef? { nil }
101+
102+
func getMany(_ items: inout [T]) -> UInt32 {
103+
let count = Swift.min(storage.count - index, items.count)
104+
for i in 0..<count {
105+
items[i] = storage[index + i]
106+
}
107+
return UInt32(count)
108+
}
85109
}

Diff for: swiftwinrt/abi_writer.h

+1
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ namespace swiftwinrt
307307
#undef FindText
308308
#undef GetClassName
309309
#undef GetObject
310+
#undef GetGlyphIndices
310311
311312
#define ENABLE_WINRT_EXPERIMENTAL_TYPES
312313

0 commit comments

Comments
 (0)