Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for array input #194

Merged
merged 13 commits into from
Dec 23, 2024
Prev Previous commit
Next Next commit
test other types
stevenbrix committed Dec 23, 2024
commit 09402f16a7b05721d127eb067713a18dd210913a
7 changes: 7 additions & 0 deletions swiftwinrt/Resources/Support/Array+FromAbi.swift
Original file line number Diff line number Diff line change
@@ -18,6 +18,13 @@ extension Array where Element: Numeric {
}
}

@_spi(WinRTInternal)
extension Array where Element: RawRepresentable, Element.RawValue: Numeric {
public static func from(abi: WinRTArrayAbi<Element>) throws -> [Element] {
Array(UnsafeBufferPointer(start: abi.start, count: Int(abi.count)))
}
}

@_spi(WinRTInternal)
extension Array {
public static func from<Bridge: AbiInterfaceBridge>(abiBridge: Bridge.Type, abi: WinRTArrayAbi<UnsafeMutablePointer<Bridge.CABI>?>) -> [Element] where Element == Bridge.SwiftProjection? {
12 changes: 11 additions & 1 deletion swiftwinrt/Resources/Support/Array+ToAbi.swift
Original file line number Diff line number Diff line change
@@ -13,7 +13,17 @@ extension Array where Element: ToAbi {
}

@_spi(WinRTInternal)
extension Array where Element: Numeric {
extension Array where Element: Numeric {
public func toABI(_ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<Element>?) throws -> Void) throws {
try withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: Element.self)
try withAbi(UInt32(count), .init(mutating: bytesPtr))
}
}
}

@_spi(WinRTInternal)
extension Array where Element: RawRepresentable, Element.RawValue: Numeric {
public func toABI(_ withAbi: (_ length: UInt32, _ bytes: UnsafeMutablePointer<Element>?) throws -> Void) throws {
try withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
let bytesPtr = bytes.baseAddress?.assumingMemoryBound(to: Element.self)
77 changes: 77 additions & 0 deletions tests/test_app/ArrayTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import WinSDK
import XCTest
import test_component
import Foundation

class StringableInt: IStringable {
let value: Int32
init(value: Int32) {
self.value = value
}
public func toString() -> String {
return "\(value)"
}
}

class ArrayTests : XCTestCase {
public func testInputIntArray() throws {
let input: [Int32] = [1, 2, 3, 4, 5]
let classy = Class()
let result = try classy.inInt32Array(input)
XCTAssertEqual("12345", result)
}

public func testInStringArray() throws {
let input: [String] = ["1", "2", "3", "4", "5"]
let classy = Class()
let result = try classy.inStringArray(input)
XCTAssertEqual("12345", result)
}

public func testInObjectArray() throws {
let input: [StringableInt] = [.init(value: 1), .init(value: 2), .init(value: 3), .init(value: 4), .init(value: 5)]
let classy = Class()
let result = try classy.inObjectArray(input)
XCTAssertEqual("12345", result)
}

public func testInStringableArray() throws {
let input: [StringableInt] = [.init(value: 1), .init(value: 2), .init(value: 3), .init(value: 4), .init(value: 5)]
let classy = Class()
let result = try classy.inStringableArray(input)
XCTAssertEqual("12345", result)
}

public func testInStructArray() throws {
let input: [BlittableStruct] = [BlittableStruct(first: 1, second: 2), BlittableStruct(first: 3, second: 4) ]
let classy = Class()
let result = try classy.inStructArray(input)
XCTAssertEqual("1234", result)
}

public func testInNonBlittableStructArray() throws {
let input: [NonBlittableStruct] = [NonBlittableStruct(first: "1", second: "2", third: 3, fourth: "3"), NonBlittableStruct(first: "4", second: "5", third: 3, fourth: "6")]
let classy = Class()
let result = try classy.inNonBlittableStructArray(input)
XCTAssertEqual("123456", result)
}

public func testInEnumArray() throws {
let input: [Signed] = [.first, .second, .third]
let classy = Class()
let result = try classy.inEnumArray(input)
XCTAssertEqual("0", result)
}
}

var arrayTests: [XCTestCaseEntry] = [
testCase([
("testInputIntArray", ArrayTests.testInputIntArray),
("testInStringArray", ArrayTests.testInStringArray),
("testInObjectArray", ArrayTests.testInObjectArray),
("testInStringableArray", ArrayTests.testInStringableArray),
("testInStructArray", ArrayTests.testInStructArray),
("testInNonBlittableStructArray", ArrayTests.testInNonBlittableStructArray),
("testInEnumArray", ArrayTests.testInEnumArray)
])
]
2 changes: 1 addition & 1 deletion tests/test_app/main.swift
Original file line number Diff line number Diff line change
@@ -460,7 +460,7 @@ var tests: [XCTestCaseEntry] = [
("testUnicode", SwiftWinRTTests.testUnicode),
("testErrorInfo", SwiftWinRTTests.testErrorInfo),
])
] + valueBoxingTests + eventTests + collectionTests + aggregationTests + asyncTests + memoryManagementTests + bufferTests + weakReferenceTests
] + valueBoxingTests + eventTests + collectionTests + aggregationTests + asyncTests + memoryManagementTests + bufferTests + weakReferenceTests + arrayTests

RoInitialize(RO_INIT_MULTITHREADED)
XCTMain(tests)
24 changes: 24 additions & 0 deletions tests/test_component/Sources/CWinRT/include/test_component.h
Original file line number Diff line number Diff line change
@@ -3115,6 +3115,30 @@ struct __x_ABI_Ctest__component_CStructWithIReference
UINT32 valueLength,
INT32* value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InStringArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
HSTRING* value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InObjectArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
IInspectable** value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InStringableArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
__x_ABI_CWindows_CFoundation_CIStringable** value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InStructArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
struct __x_ABI_Ctest__component_CBlittableStruct* value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InNonBlittableStructArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
struct __x_ABI_Ctest__component_CNonBlittableStruct* value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* InEnumArray)(__x_ABI_Ctest__component_CIClass* This,
UINT32 valueLength,
enum __x_ABI_Ctest__component_CSigned* value,
HSTRING* result);
HRESULT (STDMETHODCALLTYPE* NoexceptVoid)(__x_ABI_Ctest__component_CIClass* This);
HRESULT (STDMETHODCALLTYPE* NoexceptInt32)(__x_ABI_Ctest__component_CIClass* This,
INT32* result);
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ private var IID___x_ABI_Ctest__component_CIBufferTesterStatics: test_component.I
}

private var IID___x_ABI_Ctest__component_CIClass: test_component.IID {
.init(Data1: 0x5ADEA2BF, Data2: 0x88FC, Data3: 0x5F8B, Data4: ( 0xB5,0xD3,0x59,0xB1,0x64,0x5D,0x0F,0xDD ))// 5ADEA2BF-88FC-5F8B-B5D3-59B1645D0FDD
.init(Data1: 0x0FD4DE6B, Data2: 0x257A, Data3: 0x5CA3, Data4: ( 0xB5,0x72,0xB6,0x6A,0x81,0xB0,0x8E,0x59 ))// 0FD4DE6B-257A-5CA3-B572-B66A81B08E59
}

private var IID___x_ABI_Ctest__component_CIClassFactory: test_component.IID {
@@ -736,6 +736,66 @@ public enum __ABI_test_component {
return .init(from: result)
}

public func InStringArray(_ value: [String]) throws -> String {
var result: HSTRING?
try value.toABI { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InStringArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func InObjectArray(_ value: [Any?]) throws -> String {
var result: HSTRING?
try value.toABI(abiBridge: __IMPL_.AnyBridge.self) { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InObjectArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func InStringableArray(_ value: [test_component.AnyIStringable?]) throws -> String {
var result: HSTRING?
try value.toABI(abiBridge: __IMPL_Windows_Foundation.IStringableBridge.self) { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InStringableArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func InStructArray(_ value: [test_component.BlittableStruct]) throws -> String {
var result: HSTRING?
try value.toABI { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InStructArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func InNonBlittableStructArray(_ value: [test_component.NonBlittableStruct]) throws -> String {
var result: HSTRING?
try value.toABI { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InNonBlittableStructArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func InEnumArray(_ value: [test_component.Signed]) throws -> String {
var result: HSTRING?
try value.toABI { (count, _value) in
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.InEnumArray(pThis, count, _value, &result))
}
}
return .init(from: result)
}

public func NoexceptVoid() throws {
_ = try perform(as: __x_ABI_Ctest__component_CIClass.self) { pThis in
try CHECKED(pThis.pointee.lpVtbl.pointee.NoexceptVoid(pThis))
Original file line number Diff line number Diff line change
@@ -9936,10 +9936,7 @@ internal var __x_ABI_C__FIVector_1_IInspectableVTable: __x_ABI_C__FIVector_1_IIn

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1_IInspectableWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi: UnsafeMutablePointer<UnsafeMutablePointer<C_IInspectable>?>? = $2
let items: [Any?] = .init() //.from(abiBridge: __IMPL_.AnyBridge.self, abi: (count: count, start: abi))

let items: [Any?] = .from(abiBridge: __IMPL_.AnyBridge.self, abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -10266,9 +10263,7 @@ internal var __x_ABI_C__FIVector_1_GUIDVTable: __x_ABI_C__FIVector_1_GUIDVtbl =

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1_GUIDWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi = $2
let items: [Foundation.UUID] = try! .from(abi: (count: $1, start: $2))
let items: [Foundation.UUID] = .from(abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -10586,9 +10581,7 @@ internal var __x_ABI_C__FIVector_1_HSTRINGVTable: __x_ABI_C__FIVector_1_HSTRINGV

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1_HSTRINGWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi = $2
let items: [String] = .init() //.from(abi: (count: $1, start: $2))
let items: [String] = .from(abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -10911,9 +10904,7 @@ internal var __x_ABI_C__FIVector_1___x_ABI_CWindows__CStorage__CSearch__CSortEnt

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1___x_ABI_CWindows__CStorage__CSearch__CSortEntryWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi = $2
let items: [test_component.SortEntry] = .init() //.from(abi: (count: $1, start: $2))
let items: [test_component.SortEntry] = .from(abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -11235,9 +11226,7 @@ internal var __x_ABI_C__FIVector_1___x_ABI_Ctest__zcomponent__CBaseVTable: __x_A

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1___x_ABI_Ctest__zcomponent__CBaseWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi: UnsafeMutablePointer<UnsafeMutablePointer<__IMPL_test_component.BaseBridge.CABI>?>? = $2
let items: [__IMPL_test_component.BaseBridge.SwiftProjection?] = try! .from(abiBridge: __IMPL_test_component.BaseBridge.self, abi: (count: count, start: abi))
let items: [test_component.Base?] = .from(abiBridge: __IMPL_test_component.BaseBridge.self, abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -11557,9 +11546,7 @@ internal var __x_ABI_C__FIVector_1___x_ABI_Ctest__zcomponent__CIBasicVTable: __x

ReplaceAll: {
guard let __unwrapped__instance = __x_ABI_C__FIVector_1___x_ABI_Ctest__zcomponent__CIBasicWrapper.tryUnwrapFrom(raw: $0) else { return E_INVALIDARG }
let count: UInt32 = $1
let abi = $2
let items: [test_component.AnyIBasic?] = .init() //.from(abiBridge: __IMPL_test_component.IBasicBridge.self, abi: (count: $1, start: $2))
let items: [test_component.AnyIBasic?] = .from(abiBridge: __IMPL_test_component.IBasicBridge.self, abi: (count: $1, start: $2))
__unwrapped__instance.replaceAll(items)
return S_OK
}
@@ -16798,7 +16785,7 @@ internal class __x_ABI_C__FITypedEventHandler_2___x_ABI_CWindows__CStorage__CSea
}
}
private var IID___x_ABI_C__FITypedEventHandler_2___x_ABI_Ctest__zcomponent__CClass___x_ABI_Ctest__zcomponent__CDeferrableEventArgs: test_component.IID {
.init(Data1: 0x11bc190a, Data2: 0x59d8, Data3: 0x515a, Data4: ( 0xb1,0x46,0x8e,0x42,0x2f,0x57,0x68,0x5c ))// 11bc190a-59d8-515a-b146-8e422f57685c
.init(Data1: 0xe7c34e55, Data2: 0x1da3, Data3: 0x51d7, Data4: ( 0x83,0xc3,0x9c,0x56,0xe0,0x62,0x6f,0xe5 ))// e7c34e55-1da3-51d7-83c3-9c56e0626fe5
}

internal extension WinRTDelegateBridge where CABI == __x_ABI_C__FITypedEventHandler_2___x_ABI_Ctest__zcomponent__CClass___x_ABI_Ctest__zcomponent__CDeferrableEventArgs {
Original file line number Diff line number Diff line change
@@ -669,6 +669,30 @@ public final class Class : WinRTClass, IBasic {
try _default.InInt32Array(value)
}

public func inStringArray(_ value: [String]) throws -> String {
try _default.InStringArray(value)
}

public func inObjectArray(_ value: [Any?]) throws -> String {
try _default.InObjectArray(value)
}

public func inStringableArray(_ value: [test_component.AnyIStringable?]) throws -> String {
try _default.InStringableArray(value)
}

public func inStructArray(_ value: [BlittableStruct]) throws -> String {
try _default.InStructArray(value)
}

public func inNonBlittableStructArray(_ value: [NonBlittableStruct]) throws -> String {
try _default.InNonBlittableStructArray(value)
}

public func inEnumArray(_ value: [Signed]) throws -> String {
try _default.InEnumArray(value)
}

public func noexceptVoid() {
try! _default.NoexceptVoid()
}
12 changes: 6 additions & 6 deletions tests/test_component/cpp/test_component.idl
Original file line number Diff line number Diff line change
@@ -264,12 +264,12 @@ namespace test_component
Fruit EnumProperty;

String InInt32Array(Int32[] value);
//String InStringArray(String[] value);
//String InObjectArray(Object[] value);
//String InStringableArray(Windows.Foundation.IStringable[] value);
//String InStructArray(BlittableStruct[] value);
//String InNonBlittableStructArray(NonBlittableStruct[] value);
//String InEnumArray(Signed[] value);
String InStringArray(String[] value);
String InObjectArray(Object[] value);
String InStringableArray(Windows.Foundation.IStringable[] value);
String InStructArray(BlittableStruct[] value);
String InNonBlittableStructArray(NonBlittableStruct[] value);
String InEnumArray(Signed[] value);

// void OutInt32Array(out Int32[] value);
// void OutStringArray(out String[] value);