Skip to content

Commit ab513e2

Browse files
committed
Add UnsafeMutableTupleTests
1 parent af59f18 commit ab513e2

File tree

5 files changed

+139
-20
lines changed

5 files changed

+139
-20
lines changed

Sources/OpenGraph/Runtime/Metadata.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extension Metadata: Swift.Hashable, Swift.CustomStringConvertible {
2727
@inlinable
2828
@inline(__always)
2929
public init(_ type: Any.Type) {
30-
self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<OGSwiftMetadata>.self))
30+
self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<_Metadata>.self))
3131
}
3232

3333
@inlinable

Sources/OpenGraph/Runtime/TupleType.swift

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,24 @@
77

88
public import OpenGraph_SPI
99

10+
// MARK: TupleType
11+
1012
extension TupleType {
1113
public init(_ types: [Any.Type]) {
1214
self.init(count: types.count, elements: types.map(Metadata.init))
1315
}
1416

1517
public init(_ type: Any.Type) {
16-
self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<OGSwiftMetadata>.self))
18+
self.init(rawValue: unsafeBitCast(type, to: UnsafePointer<_Metadata>.self))
1719
}
1820

21+
public var isEmpty: Bool { count == 0 }
22+
public var indices: Range<Int> { 0 ..< count }
23+
1924
public var type: Any.Type {
2025
unsafeBitCast(rawValue, to: Any.Type.self)
2126
}
2227

23-
public var isEmpty: Bool {
24-
count == 0
25-
}
26-
27-
public var indices: Range<Int> {
28-
0 ..< count
29-
}
30-
3128
public func type(at index: Int) -> Any.Type {
3229
elementType(at: index).type
3330
}
@@ -47,3 +44,86 @@ extension TupleType {
4744

4845
@_silgen_name("OGTupleWithBuffer")
4946
public func withUnsafeTuple(of type: TupleType, count: Int, _ body: (UnsafeMutableTuple) -> ())
47+
48+
// MARK: - UnsafeTuple
49+
50+
extension UnsafeTuple {
51+
public var count: Int { type.count }
52+
public var isEmpty: Bool { type.isEmpty }
53+
public var indices: Range<Int> { type.indices }
54+
55+
public func address<T>(as _: T.Type = T.self) -> UnsafePointer<T> {
56+
value.assumingMemoryBound(to: T.self)
57+
}
58+
59+
public func address<T>(of index: Int, as _: T.Type = T.self) -> UnsafePointer<T> {
60+
value.advanced(by: type.elementOffset(at: index, type: Metadata(T.self)))
61+
.assumingMemoryBound(to: T.self)
62+
}
63+
64+
public subscript<T>() -> T {
65+
unsafeAddress { address(as: T.self) }
66+
}
67+
68+
public subscript<T>(_ index: Int) -> T {
69+
unsafeAddress { address(of: index, as: T.self) }
70+
}
71+
}
72+
73+
// MARK: - UnsafeMutableTuple
74+
75+
@_silgen_name("swift_slowAlloc")
76+
private func slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPointer
77+
78+
@_silgen_name("swift_slowDealloc")
79+
private func slowDealloc(_ ptr: UnsafeMutableRawPointer, _ size: Int, _ alignMask: Int)
80+
81+
extension UnsafeMutableTuple {
82+
public init(with tupleType: TupleType) {
83+
self.init(type: tupleType, value: slowAlloc(tupleType.size, -1))
84+
}
85+
86+
public func initialize<T>(at index: Int, to element: T) {
87+
withUnsafePointer(to: element) { elementPointer in
88+
type.setElement(in: value, at: index, from: elementPointer, options: .initCopy)
89+
}
90+
}
91+
92+
public func deinitialize() {
93+
type.destory(value)
94+
}
95+
96+
public func deinitialize(at index: Int) {
97+
type.destory(value, at: index)
98+
}
99+
100+
public func deallocate(initialized: Bool) {
101+
if initialized {
102+
deinitialize()
103+
}
104+
slowDealloc(value, -1, -1)
105+
}
106+
107+
public var count: Int { type.count }
108+
public var isEmpty: Bool { type.isEmpty }
109+
public var indices: Range<Int> { type.indices }
110+
111+
public func address<T>(as _: T.Type = T.self) -> UnsafeMutablePointer<T> {
112+
value.assumingMemoryBound(to: T.self)
113+
}
114+
115+
public func address<T>(of index: Int, as _: T.Type = T.self) -> UnsafeMutablePointer<T> {
116+
value.advanced(by: type.elementOffset(at: index, type: Metadata(T.self)))
117+
.assumingMemoryBound(to: T.self)
118+
}
119+
120+
public subscript<T>() -> T {
121+
unsafeAddress { UnsafePointer(address(as: T.self)) }
122+
unsafeMutableAddress { address(as: T.self) }
123+
}
124+
125+
public subscript<T>(_ index: Int) -> T {
126+
unsafeAddress { UnsafePointer(address(of: index, as: T.self)) }
127+
unsafeMutableAddress { address(of: index, as: T.self) }
128+
}
129+
}

Sources/OpenGraph_SPI/Runtime/OGTupleType.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@ typedef OG_CLOSED_ENUM(uint32_t, OGTupleCopyOptions) {
2222
OGTupleCopyOptionsInitTake = 3
2323
} OG_SWIFT_NAME(TupleType.CopyOptions);
2424

25-
struct OGUnsafeTuple {
25+
typedef struct OG_SWIFT_NAME(UnsafeTuple) OGUnsafeTuple {
2626
OGTupleType type;
2727
const void *value;
28-
} OG_SWIFT_NAME(UnsafeTuple);
28+
} OGUnsafeTuple;
2929

30-
typedef struct OGUnsafeTuple OGUnsafeTuple;
31-
32-
struct OGUnsafeMutableTuple {
30+
typedef struct OG_SWIFT_NAME(UnsafeMutableTuple) OGUnsafeMutableTuple {
3331
OGTupleType type;
3432
void *value;
35-
} OG_SWIFT_NAME(UnsafeMutableTuple);
36-
37-
typedef struct OGUnsafeMutableTuple OGUnsafeMutableTuple;
33+
} OGUnsafeMutableTuple;
3834

3935
OG_EXTERN_C_BEGIN
4036

Sources/OpenGraph_SPI/Runtime/OGTypeID.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
OG_ASSUME_NONNULL_BEGIN
1515

16-
typedef struct OGSwiftMetadata {
17-
} OGSwiftMetadata OG_SWIFT_NAME(_Metadata);
16+
typedef struct OG_SWIFT_NAME(_Metadata) OGSwiftMetadata {
17+
} OGSwiftMetadata ;
1818

1919
typedef const OGSwiftMetadata *OGTypeID OG_SWIFT_STRUCT OG_SWIFT_NAME(Metadata);
2020

Tests/OpenGraphCompatibilityTests/Runtime/TupleTypeTests.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,46 @@ struct TupleTypeTests {
9898
}
9999
}
100100
}
101+
102+
@Suite(.enabled(if: swiftToolchainSupported))
103+
struct UnsafeTupleTests {
104+
}
105+
106+
@Suite(.enabled(if: swiftToolchainSupported))
107+
struct UnsafeMutableTupleTests {
108+
class T1 {
109+
var a = 0
110+
var b: Double = 0
111+
}
112+
113+
struct T2 {
114+
var a: Int = 0
115+
var b: Double = 0
116+
}
117+
118+
enum T3 {
119+
case a, b
120+
}
121+
122+
@Test
123+
func initialize() {
124+
let mutableTuple = UnsafeMutableTuple(with: TupleType([T1.self, T2.self]))
125+
126+
#expect(mutableTuple.count == 2)
127+
#expect(mutableTuple.isEmpty == false)
128+
129+
let t1 = T1()
130+
t1.a = 1
131+
let t2 = T2(a: 2)
132+
mutableTuple.initialize(at: 0, to: t1)
133+
mutableTuple.initialize(at: 1, to: t2)
134+
135+
let retrievedT1: T1 = mutableTuple[0]
136+
let retrievedT2: T2 = mutableTuple[1]
137+
138+
#expect(retrievedT1.a == 1)
139+
#expect(retrievedT2.a == 2)
140+
141+
mutableTuple.deinitialize()
142+
}
143+
}

0 commit comments

Comments
 (0)