Skip to content

Commit 2e7ac93

Browse files
committed
add withUnsafeTuple implementation
1 parent ab513e2 commit 2e7ac93

File tree

5 files changed

+55
-20
lines changed

5 files changed

+55
-20
lines changed

Sources/OpenGraph/Runtime/TupleType.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ extension UnsafeTuple {
5353
public var indices: Range<Int> { type.indices }
5454

5555
public func address<T>(as _: T.Type = T.self) -> UnsafePointer<T> {
56-
value.assumingMemoryBound(to: T.self)
56+
guard type.type == T.self else {
57+
preconditionFailure()
58+
}
59+
return value.assumingMemoryBound(to: T.self)
5760
}
5861

5962
public func address<T>(of index: Int, as _: T.Type = T.self) -> UnsafePointer<T> {
@@ -109,7 +112,10 @@ extension UnsafeMutableTuple {
109112
public var indices: Range<Int> { type.indices }
110113

111114
public func address<T>(as _: T.Type = T.self) -> UnsafeMutablePointer<T> {
112-
value.assumingMemoryBound(to: T.self)
115+
guard type.type == T.self else {
116+
preconditionFailure()
117+
}
118+
return value.assumingMemoryBound(to: T.self)
113119
}
114120

115121
public func address<T>(of index: Int, as _: T.Type = T.self) -> UnsafeMutablePointer<T> {
@@ -119,11 +125,11 @@ extension UnsafeMutableTuple {
119125

120126
public subscript<T>() -> T {
121127
unsafeAddress { UnsafePointer(address(as: T.self)) }
122-
unsafeMutableAddress { address(as: T.self) }
128+
nonmutating unsafeMutableAddress { address(as: T.self) }
123129
}
124130

125131
public subscript<T>(_ index: Int) -> T {
126132
unsafeAddress { UnsafePointer(address(of: index, as: T.self)) }
127-
unsafeMutableAddress { address(of: index, as: T.self) }
133+
nonmutating unsafeMutableAddress { address(of: index, as: T.self) }
128134
}
129135
}

Sources/OpenGraph_SPI/Runtime/OGTupleType.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,27 @@ void OGTupleDestoryElement(OGTupleType tuple_type, void *value, size_t index) {
231231
element_type->vw_destroy(reinterpret_cast<swift::OpaqueValue *>((intptr_t)value + index));
232232
#endif
233233
}
234+
235+
void OGTupleWithBuffer(OGTupleType tuple_type, size_t count, const void (* function)(const OGUnsafeMutableTuple mutableTuple, const void * context OG_SWIFT_CONTEXT) OG_SWIFT_CC(swift), const void *context) {
236+
#ifdef OPENGRAPH_SWIFT_TOOLCHAIN_SUPPORTED
237+
auto metadata = reinterpret_cast<OG::swift::metadata const*>(tuple_type);
238+
auto buffer_size = metadata->vw_stride() * count;
239+
OGUnsafeMutableTuple tuple;
240+
tuple.type = tuple_type;
241+
if (buffer_size <= 0x1000) {
242+
char buffer[buffer_size];
243+
bzero(buffer, buffer_size);
244+
// NOTE: If you use buffer out of the scope, the stack may be malformed.
245+
// So we need to call function in this scope.
246+
function(tuple, context);
247+
} else {
248+
void *buffer = malloc_type_malloc(buffer_size, 0x100004077774924);
249+
if (buffer == nullptr) {
250+
OG::precondition_failure("memory allocation failure");
251+
}
252+
tuple.value = buffer;
253+
function(tuple, context);
254+
free(buffer);
255+
}
256+
#endif
257+
}

Sources/OpenGraph_SPI/Runtime/OGTupleType.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ void OGTupleDestoryElement(OGTupleType tuple_type, void *buffer, size_t index) O
8080

8181
OG_EXPORT
8282
OG_REFINED_FOR_SWIFT
83-
void OGTupleWithBuffer(OGTupleType tuple_type, size_t count, const void (*_Nullable function)(const void * _Nullable context OG_SWIFT_CONTEXT) OG_SWIFT_CC(swift), const void * _Nullable context);
83+
void OGTupleWithBuffer(OGTupleType tuple_type, size_t count, const void (* function)(const OGUnsafeMutableTuple mutableTuple, const void * context OG_SWIFT_CONTEXT) OG_SWIFT_CC(swift), const void *context);
8484

8585
OG_EXTERN_C_END
8686

Sources/OpenGraph_SPI/Runtime/OGTypeID.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
OG_ASSUME_NONNULL_BEGIN
1515

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

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

Tests/OpenGraphCompatibilityTests/Runtime/TupleTypeTests.swift

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -99,24 +99,32 @@ struct TupleTypeTests {
9999
}
100100
}
101101

102-
@Suite(.enabled(if: swiftToolchainSupported))
103-
struct UnsafeTupleTests {
104-
}
105-
106102
@Suite(.enabled(if: swiftToolchainSupported))
107103
struct UnsafeMutableTupleTests {
108104
class T1 {
109105
var a = 0
110-
var b: Double = 0
111106
}
112107

113108
struct T2 {
114-
var a: Int = 0
115-
var b: Double = 0
109+
var a = 0
116110
}
117111

118-
enum T3 {
119-
case a, b
112+
@Test
113+
func buffer() {
114+
withUnsafeTuple(of: TupleType([T1.self, T2.self]), count: 1) { mutableTuple in
115+
let ref = T1()
116+
ref.a = 1
117+
mutableTuple.initialize(at: 0, to: ref)
118+
mutableTuple.initialize(at: 1, to: T2(a: 2))
119+
120+
let tuple = UnsafeTuple(type: mutableTuple.type, value: mutableTuple.value)
121+
let t1 = tuple[0] as T1
122+
let t2 = tuple[1] as T2
123+
124+
#expect(t1 === ref)
125+
#expect(t1.a == 1)
126+
#expect(t2.a == 2)
127+
}
120128
}
121129

122130
@Test
@@ -131,12 +139,9 @@ struct UnsafeMutableTupleTests {
131139
let t2 = T2(a: 2)
132140
mutableTuple.initialize(at: 0, to: t1)
133141
mutableTuple.initialize(at: 1, to: t2)
134-
135-
let retrievedT1: T1 = mutableTuple[0]
136-
let retrievedT2: T2 = mutableTuple[1]
137142

138-
#expect(retrievedT1.a == 1)
139-
#expect(retrievedT2.a == 2)
143+
#expect((mutableTuple[0] as T1).a == 1)
144+
#expect((mutableTuple[1] as T2).a == 2)
140145

141146
mutableTuple.deinitialize()
142147
}

0 commit comments

Comments
 (0)