From 99d52279d7d02b5854863418eeb3c079bfb73f95 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Fri, 3 Apr 2026 17:36:10 +0900
Subject: [PATCH 01/11] Generate foundation types in SwiftKitCore
---
.../test/java/com/example/swift/DataTest.java | 1 +
Sources/FakeFoundation/Data.swift | 26 ++++
Sources/FakeFoundation/DataProtocol.swift | 21 +++
Sources/FakeFoundation/Date.swift | 27 ++++
...t2JavaGenerator+JavaBindingsPrinting.swift | 2 +-
...ISwift2JavaGenerator+JavaTranslation.swift | 53 +++++--
.../JavaTypes/JavaType+JDK.swift | 11 ++
.../Swift2JavaTranslator.swift | 2 +-
.../generated/Data+SwiftJava.swift | 55 ++++++++
.../generated/DataProtocol+SwiftJava.swift | 19 +++
.../generated/Date+SwiftJava.swift | 53 +++++++
.../generated/SwiftJavaModule+SwiftJava.swift | 12 ++
.../swift/swiftkit/core/generated/Data.java | 133 ++++++++++++++++++
.../swiftkit/core/generated/DataProtocol.java | 14 ++
.../swift/swiftkit/core/generated/Date.java | 131 +++++++++++++++++
.../swiftkit/core/generated/SwiftJava.java | 20 +++
scripts/swiftkit-jni-generate-bindings.sh | 50 +++++++
17 files changed, 616 insertions(+), 14 deletions(-)
create mode 100644 Sources/FakeFoundation/Data.swift
create mode 100644 Sources/FakeFoundation/DataProtocol.swift
create mode 100644 Sources/FakeFoundation/Date.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
create mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
create mode 100755 scripts/swiftkit-jni-generate-bindings.sh
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
index a6024ca12..d947e7133 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.generated.Data;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/Sources/FakeFoundation/Data.swift b/Sources/FakeFoundation/Data.swift
new file mode 100644
index 000000000..5fd160dd0
--- /dev/null
+++ b/Sources/FakeFoundation/Data.swift
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Data: DataProtocol {
+ public init(bytes: UnsafeRawPointer, count: Int)
+ public init(_ bytes: [UInt8])
+ public var count: Int { get }
+ public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
+}
diff --git a/Sources/FakeFoundation/DataProtocol.swift b/Sources/FakeFoundation/DataProtocol.swift
new file mode 100644
index 000000000..d5a02d423
--- /dev/null
+++ b/Sources/FakeFoundation/DataProtocol.swift
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public protocol DataProtocol {}
diff --git a/Sources/FakeFoundation/Date.swift b/Sources/FakeFoundation/Date.swift
new file mode 100644
index 000000000..ee18b8afc
--- /dev/null
+++ b/Sources/FakeFoundation/Date.swift
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+public struct Date {
+ /// The interval between the date object and 00:00:00 UTC on 1 January 1970.
+ public var timeIntervalSince1970: Double { get }
+
+ /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
+ public init(timeIntervalSince1970: Double)
+}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 8f6d97a67..4581091b8 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -616,7 +616,7 @@ extension JNISwift2JavaGenerator {
}
generics.append((name, extends))
}
- .map { "\($0) extends \($1.compactMap(\.className).joined(separator: " & "))" }
+ .map { "\($0) extends \($1.compactMap(\.description).joined(separator: " & "))" }
.joined(separator: ", ")
if !generics.isEmpty {
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 69455ba69..8df7930f6 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -505,10 +505,24 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreGeneratedDate),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .foundationData, .essentialsData:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreGeneratedData),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer:
return TranslatedParameter(
@@ -945,12 +959,22 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreGeneratedDate
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationData, .essentialsData:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreGeneratedData
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationUUID, .essentialsUUID:
return TranslatedResult(
@@ -1094,13 +1118,13 @@ extension JNISwift2JavaGenerator {
return .swiftSet(elementJavaType)
case .foundationDate, .essentialsDate:
- return .class(package: nil, name: "Date")
+ return .swiftkitCoreGeneratedDate
case .foundationData, .essentialsData:
- return .class(package: nil, name: "Data")
+ return .swiftkitCoreGeneratedData
case .foundationDataProtocol, .essentialsDataProtocol:
- return .class(package: nil, name: "DataProtocol")
+ return .swiftkitCoreGeneratedDataProtocol
case .foundationUUID, .essentialsUUID:
return .javaUtilUUID
@@ -1162,7 +1186,6 @@ extension JNISwift2JavaGenerator {
genericParameters: [SwiftGenericParameterDeclaration],
genericRequirements: [SwiftGenericRequirement],
) throws -> TranslatedResult {
- let arity = elements.count
var outParameters: [OutParameter] = []
var elementOutParamNames: [String] = []
var elementConversions: [JavaNativeConversionStep] = []
@@ -1854,16 +1877,22 @@ extension JNISwift2JavaGenerator {
case .wrapMemoryAddressUnsafe(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
- guard case .class(_, let className, let typeParameters) = javaType else {
+ guard case .class(let package, let className, let typeParameters) = javaType else {
fatalError("\(javaType) is not class.")
}
+ let packagePart: String =
+ if let package {
+ "\(package)."
+ } else {
+ ""
+ }
let genericClause =
if !typeParameters.isEmpty {
"<\(typeParameters.map(\.description).joined(separator: ", "))>"
} else {
""
}
- return "\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
+ return "\(packagePart)\(className).\(genericClause)wrapMemoryAddressUnsafe(\(inner), swiftArena)"
case .constructJavaClass(let inner, let javaType):
let inner = inner.render(&printer, placeholder)
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 34cb7f458..56a6d65bf 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -59,4 +59,15 @@ extension JavaType {
.class(package: "java.util", name: "UUID")
}
+ static var swiftkitCoreGeneratedDate: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "Date")
+ }
+
+ static var swiftkitCoreGeneratedData: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "Data")
+ }
+
+ static var swiftkitCoreGeneratedDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.core.generated", name: "DataProtocol")
+ }
}
diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
index a5d96a1af..d9952724c 100644
--- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
+++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
@@ -111,7 +111,7 @@ extension Swift2JavaTranslator {
// Apply any specializations registered after their target types were visited
visitor.applyPendingSpecializations()
- self.visitFoundationDeclsIfNeeded(with: visitor)
+// self.visitFoundationDeclsIfNeeded(with: visitor)
}
private func visitFoundationDeclsIfNeeded(with visitor: Swift2JavaVisitor) {
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
new file mode 100644
index 000000000..dbe1a8f05
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
@@ -0,0 +1,55 @@
+
+// ==== --------------------------------------------------
+// Thunks for Data
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Data {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024init___3B")
+public func Java_org_swift_swiftkit_core_generated_Data__00024init___3B(environment: UnsafeMutablePointer!, thisClass: jclass, bytes: jbyteArray?) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Data.init([UInt8](fromJNI: bytes, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024getCount__J")
+public func Java_org_swift_swiftkit_core_generated_Data__00024getCount__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return Int64(selfPointer$.pointee.count).getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..3f7754f5e
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
@@ -0,0 +1,19 @@
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_DataProtocol {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
new file mode 100644
index 000000000..838d8729e
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
@@ -0,0 +1,53 @@
+
+// ==== --------------------------------------------------
+// Thunks for Date
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Date {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024init__D")
+public func Java_org_swift_swiftkit_core_generated_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Date.init(timeIntervalSince1970: Double(fromJNI: timeIntervalSince1970, in: environment)))
+ let resultBits$ = Int64(Int(bitPattern: result$))
+ return resultBits$.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J")
+public func Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.timeIntervalSince1970.getJNILocalRefValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
+
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
new file mode 100644
index 000000000..e24e89ffe
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
@@ -0,0 +1,12 @@
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+import SwiftJavaRuntimeSupport
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
new file mode 100644
index 000000000..c6b0f3636
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
@@ -0,0 +1,133 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class Data implements JNISwiftInstance, DataProtocol {
+ static final String LIB_NAME = "SwiftJava";
+
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ return true;
+ }
+ /**
+ * The designated constructor of any imported Swift types.
+ *
+ * @param selfPointer a pointer to the memory containing the value
+ * @param swiftArena the arena this object belongs to. When the arena goes out of scope, this value is destroyed.
+ */
+ private Data(long selfPointer, SwiftArena swiftArena) {
+ SwiftObjects.requireNonZero(selfPointer, "selfPointer");
+ this.selfPointer = selfPointer;
+
+ // Only register once we have fully initialized the object since this will need the object pointer.
+ swiftArena.register(this);
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
+
+ /**
+ * Assume that the passed {@code long} represents a memory address of a {@link Data}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Data types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Data wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new Data(selfPointer, swiftArena);
+ }
+
+ public static Data wrapMemoryAddressUnsafe(long selfPointer) {
+ return new Data(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
+ }
+ /** Pointer to the "self". */
+ private final long selfPointer;
+
+ /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
+ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
+
+ public long $memoryAddress() {
+ return this.selfPointer;
+ }
+
+ @Override
+ public AtomicBoolean $statusDestroyedFlag() {
+ return $state$destroyed;
+ }
+
+
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(_ bytes: [UInt8])
+ * }
+ */
+ public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
+ return Data.wrapMemoryAddressUnsafe(Data.$init(Objects.requireNonNull(bytes, "bytes must not be null")), swiftArena);
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $init(byte[] bytes);
+
+
+
+ // ==== --------------------------------------------------
+ // getter:Data.count
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var count: Int
+ * }
+ */
+ public long getCount() {
+ return Data.$getCount(this.$memoryAddress());
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $getCount(long selfPointer);
+
+ private static native long $typeMetadataAddressDowncall();
+ @Override
+ public long $typeMetadataAddress() {
+ return Data.$typeMetadataAddressDowncall();
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
+
+ public String toString() {
+ return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ public String toDebugString() {
+ return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ @Override
+ public Runnable $createDestroyFunction() {
+ long self$ = this.$memoryAddress();
+ long selfType$ = this.$typeMetadataAddress();
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Data.$createDestroyFunction",
+ "this", this,
+ "self", self$);
+ }
+ return new Runnable() {
+ @Override
+ public void run() {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Data.$destroy", "self", self$);
+ }
+ SwiftObjects.destroy(self$, selfType$);
+ }
+ };
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
new file mode 100644
index 000000000..8e9c0b90f
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
@@ -0,0 +1,14 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public interface DataProtocol extends JNISwiftInstance {
+} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:154
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
new file mode 100644
index 000000000..1e32774b5
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
@@ -0,0 +1,131 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class Date implements JNISwiftInstance {
+ static final String LIB_NAME = "SwiftJava";
+
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ return true;
+ }
+ /**
+ * The designated constructor of any imported Swift types.
+ *
+ * @param selfPointer a pointer to the memory containing the value
+ * @param swiftArena the arena this object belongs to. When the arena goes out of scope, this value is destroyed.
+ */
+ private Date(long selfPointer, SwiftArena swiftArena) {
+ SwiftObjects.requireNonZero(selfPointer, "selfPointer");
+ this.selfPointer = selfPointer;
+
+ // Only register once we have fully initialized the object since this will need the object pointer.
+ swiftArena.register(this);
+ } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
+
+ /**
+ * Assume that the passed {@code long} represents a memory address of a {@link Date}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Date types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Date wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
+ return new Date(selfPointer, swiftArena);
+ }
+
+ public static Date wrapMemoryAddressUnsafe(long selfPointer) {
+ return new Date(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
+ }
+ /** Pointer to the "self". */
+ private final long selfPointer;
+
+ /** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
+ private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
+
+ public long $memoryAddress() {
+ return this.selfPointer;
+ }
+
+ @Override
+ public AtomicBoolean $statusDestroyedFlag() {
+ return $state$destroyed;
+ }
+
+
+ // ==== --------------------------------------------------
+ // Date.init
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(timeIntervalSince1970: Double)
+ * }
+ */
+ public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
+ return Date.wrapMemoryAddressUnsafe(Date.$init(timeIntervalSince1970), swiftArena);
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native long $init(double timeIntervalSince1970);
+
+
+ // ==== --------------------------------------------------
+ // getter:Date.timeIntervalSince1970
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var timeIntervalSince1970: Double
+ * }
+ */
+ public double getTimeIntervalSince1970() {
+ return Date.$getTimeIntervalSince1970(this.$memoryAddress());
+ } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ private static native double $getTimeIntervalSince1970(long selfPointer);
+
+ private static native long $typeMetadataAddressDowncall();
+ @Override
+ public long $typeMetadataAddress() {
+ return Date.$typeMetadataAddressDowncall();
+ } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
+
+ public String toString() {
+ return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ public String toDebugString() {
+ return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
+ }
+
+ @Override
+ public Runnable $createDestroyFunction() {
+ long self$ = this.$memoryAddress();
+ long selfType$ = this.$typeMetadataAddress();
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Date.$createDestroyFunction",
+ "this", this,
+ "self", self$);
+ }
+ return new Runnable() {
+ @Override
+ public void run() {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall("Date.$destroy", "self", self$);
+ }
+ SwiftObjects.destroy(self$, selfType$);
+ }
+ };
+ } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
new file mode 100644
index 000000000..0a19e273c
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
@@ -0,0 +1,20 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+package org.swift.swiftkit.core.generated;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.core.collections.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public final class SwiftJava {
+ static final String LIB_NAME = "SwiftJava";
+
+ static {
+ System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ System.loadLibrary(LIB_NAME);
+ }
+} // printModuleClass(_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:410
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
new file mode 100755
index 000000000..a83e97309
--- /dev/null
+++ b/scripts/swiftkit-jni-generate-bindings.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+##===----------------------------------------------------------------------===##
+##
+## This source file is part of the Swift.org open source project
+##
+## Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+## Licensed under Apache License v2.0
+##
+## See LICENSE.txt for license information
+## See CONTRIBUTORS.txt for the list of Swift.org project authors
+##
+## SPDX-License-Identifier: Apache-2.0
+##
+##===----------------------------------------------------------------------===##
+
+# Regenerate FFM bindings for types in SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/
+#
+# Run from the swift-java repository root:
+# ./scripts/swiftkit-ffm-generate-bindings.sh
+
+set -euo pipefail
+
+REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
+
+JAVA_OUTPUT="${REPO_ROOT}/SwiftKitCore/src/main/java"
+JAVA_PACKAGE="org.swift.swiftkit.core.generated"
+
+# Declare types to generate: SWIFT_MODULE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+TYPES=(
+ "SwiftJava Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/generated"
+)
+
+for entry in "${TYPES[@]}"; do
+ read -r MODULE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+
+ echo "==> Generating ${INPUT_SWIFT}..."
+
+ xcrun swift run swift-java jextract \
+ --mode jni \
+ --swift-module "$MODULE" \
+ --input-swift "${REPO_ROOT}/${INPUT_SWIFT}" \
+ --output-swift "${REPO_ROOT}/${OUTPUT_SWIFT}" \
+ --output-java "$JAVA_OUTPUT" \
+ --java-package "$JAVA_PACKAGE"
+
+ echo " Swift thunks: ${OUTPUT_SWIFT}/"
+ echo " Java output: SwiftKitCore/src/main/java/$(echo "$JAVA_PACKAGE" | tr '.' '/')/"
+done
+
+echo "==> Done."
From cbd55ffc1a5bbd31b84b5103908d2c3516925448 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Fri, 3 Apr 2026 17:53:02 +0900
Subject: [PATCH 02/11] Add Date and Date wrapper by hand
---
.../test/java/com/example/swift/DataTest.java | 2 +-
Sources/FakeFoundation/Data.swift | 26 ----
Sources/FakeFoundation/Date.swift | 27 ----
...t2JavaGenerator+JavaBindingsPrinting.swift | 131 ------------------
...ISwift2JavaGenerator+JavaTranslation.swift | 14 +-
.../JavaTypes/JavaType+JDK.swift | 12 +-
.../Swift2JavaTranslator.swift | 33 -----
.../SwiftJavaMacros/ImplementsJavaMacro.swift | 2 +-
.../Foundation/Data+JNI.swift | 67 +++++++++
.../Foundation/Date+JNI.swift | 47 +++++++
.../generated/Data+SwiftJava.swift | 55 --------
.../generated/DataProtocol+SwiftJava.swift | 19 ---
.../generated/Date+SwiftJava.swift | 53 -------
.../generated/SwiftJavaModule+SwiftJava.swift | 12 --
.../core/{generated => foundation}/Data.java | 115 ++++++++++-----
.../core/foundation/DataProtocol.java | 11 +-
.../core/{generated => foundation}/Date.java | 109 +++++++++++----
.../swiftkit/core/generated/DataProtocol.java | 14 --
.../swiftkit/core/generated/SwiftJava.java | 20 ---
19 files changed, 298 insertions(+), 471 deletions(-)
delete mode 100644 Sources/FakeFoundation/Data.swift
delete mode 100644 Sources/FakeFoundation/Date.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
create mode 100644 Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
delete mode 100644 Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
rename SwiftKitCore/src/main/java/org/swift/swiftkit/core/{generated => foundation}/Data.java (63%)
rename Sources/FakeFoundation/DataProtocol.swift => SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java (76%)
rename SwiftKitCore/src/main/java/org/swift/swiftkit/core/{generated => foundation}/Date.java (62%)
delete mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
delete mode 100644 SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
index d947e7133..32bd4a98b 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DataTest.java
@@ -16,7 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
-import org.swift.swiftkit.core.generated.Data;
+import org.swift.swiftkit.core.foundation.Data;
import static org.junit.jupiter.api.Assertions.*;
diff --git a/Sources/FakeFoundation/Data.swift b/Sources/FakeFoundation/Data.swift
deleted file mode 100644
index 5fd160dd0..000000000
--- a/Sources/FakeFoundation/Data.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-public struct Data: DataProtocol {
- public init(bytes: UnsafeRawPointer, count: Int)
- public init(_ bytes: [UInt8])
- public var count: Int { get }
- public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
-}
diff --git a/Sources/FakeFoundation/Date.swift b/Sources/FakeFoundation/Date.swift
deleted file mode 100644
index ee18b8afc..000000000
--- a/Sources/FakeFoundation/Date.swift
+++ /dev/null
@@ -1,27 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-public struct Date {
- /// The interval between the date object and 00:00:00 UTC on 1 January 1970.
- public var timeIntervalSince1970: Double { get }
-
- /// Returns a `Date` initialized relative to 00:00:00 UTC on 1 January 1970 by a given number of seconds.
- public init(timeIntervalSince1970: Double)
-}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index 4581091b8..eaf34540b 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -314,8 +314,6 @@ extension JNISwift2JavaGenerator {
printer.println()
}
- printSpecificTypeHelpers(&printer, decl)
-
printTypeMetadataAddressFunction(&printer, decl)
printer.println()
@@ -336,22 +334,6 @@ extension JNISwift2JavaGenerator {
}
}
- /// Prints helpers for specific types like `Foundation.Date`
- private func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationDate, .essentialsDate:
- printFoundationDateHelpers(&printer, decl)
-
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
-
- default:
- break
- }
- }
-
private func printHeader(_ printer: inout CodePrinter) {
printer.print(
"""
@@ -832,117 +814,4 @@ extension JNISwift2JavaGenerator {
}
}
}
-
- private func printFoundationDateHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- printer.print(
- """
- /**
- * Converts this wrapped date to a Java {@link java.time.Instant}.
- *
- * This method constructs the {@code Instant} using the underlying {@code double} value
- * representing seconds since the Unix Epoch (January 1, 1970).
- *
- *
- * @return A {@code java.time.Instant} derived from the floating-point timestamp.
- */
- public java.time.Instant toInstant() {
- long seconds = (long) this.getTimeIntervalSince1970();
- long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
- return java.time.Instant.ofEpochSecond(seconds, nanos);
- }
- """
- )
- printer.println()
- printer.print(
- """
- /**
- * Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
- *
- * Warning: Precision Loss
- *
- * The input precision will be degraded.
- *
- *
- * Java's {@code Instant} stores time with nanosecond precision (9 decimal places).
- * However, this class stores time as a 64-bit floating-point value.
- *
- *
- * This leaves enough capacity for microsecond precision (approx. 6 decimal places).
- *
- *
- * Consequently, the last ~3 digits of the {@code Instant}'s nanosecond field will be
- * truncated or subjected to rounding errors during conversion.
- *
- *
- * @param instant The source timestamp to convert.
- * @return A date derived from the input instant with microsecond precision.
- */
- public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
- Objects.requireNonNull(instant, "Instant cannot be null");
- double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
- return Date.init(timeIntervalSince1970, swiftArena);
- }
- """
- )
- }
-
- private func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- printer.print(
- """
- /**
- * Creates a new Swift @{link Data} instance from a byte array.
- *
- * @param bytes The byte array to copy into the Data
- * @param swiftArena The arena for memory management
- * @return A new Data instance containing a copy of the bytes
- */
- public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
- Objects.requireNonNull(bytes, "bytes cannot be null");
- return Data.init(bytes, swiftArena);
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this Data to a new byte array.
- *
- * This is a relatively efficient implementation, which avoids native array copies,
- * however it will still perform a copy of the data onto the JVM heap, so use this
- * only when necessary.
- *
- *
When utmost performance is necessary, you may want to investigate the FFM mode
- * of jextract which is able to map memory more efficiently.
- *
- * @return A byte array containing a copy of this Data's bytes
- */
- public byte[] toByteArray() {
- return $toByteArray(this.$memoryAddress());
- }
- """
- )
-
- printer.print(
- """
- private static native byte[] $toByteArray(long selfPointer);
-
- /**
- * Copies the contents of this Data to a new byte array.
- *
- * @deprecated Prefer using the `toByteArray` method as it is more performant.
- * This implementation uses a naive conversion path from native bytes into jbytes
- * and then copying them onto the jvm heap.
- *
- * @return A byte array containing a copy of this Data's bytes
- */
- @Deprecated(forRemoval = true)
- public byte[] toByteArrayIndirectCopy() {
- return $toByteArrayIndirectCopy(this.$memoryAddress());
- }
-
- private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
- """
- )
- }
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 8df7930f6..733cbac43 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -508,7 +508,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .concrete(.swiftkitCoreGeneratedDate),
+ type: .concrete(.swiftkitCoreFoundationDate),
annotations: parameterAnnotations,
),
conversion: .valueMemoryAddress(.placeholder),
@@ -518,7 +518,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .concrete(.swiftkitCoreGeneratedData),
+ type: .concrete(.swiftkitCoreFoundationData),
annotations: parameterAnnotations,
),
conversion: .valueMemoryAddress(.placeholder),
@@ -959,7 +959,7 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- let javaType = JavaType.swiftkitCoreGeneratedDate
+ let javaType = JavaType.swiftkitCoreFoundationDate
return TranslatedResult(
javaType: javaType,
annotations: resultAnnotations,
@@ -968,7 +968,7 @@ extension JNISwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- let javaType = JavaType.swiftkitCoreGeneratedData
+ let javaType = JavaType.swiftkitCoreFoundationData
return TranslatedResult(
javaType: javaType,
annotations: resultAnnotations,
@@ -1118,13 +1118,13 @@ extension JNISwift2JavaGenerator {
return .swiftSet(elementJavaType)
case .foundationDate, .essentialsDate:
- return .swiftkitCoreGeneratedDate
+ return .swiftkitCoreFoundationDate
case .foundationData, .essentialsData:
- return .swiftkitCoreGeneratedData
+ return .swiftkitCoreFoundationData
case .foundationDataProtocol, .essentialsDataProtocol:
- return .swiftkitCoreGeneratedDataProtocol
+ return .swiftkitCoreFoundationDataProtocol
case .foundationUUID, .essentialsUUID:
return .javaUtilUUID
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 56a6d65bf..32e01b26f 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -59,15 +59,15 @@ extension JavaType {
.class(package: "java.util", name: "UUID")
}
- static var swiftkitCoreGeneratedDate: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "Date")
+ static var swiftkitCoreFoundationDate: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Date")
}
- static var swiftkitCoreGeneratedData: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "Data")
+ static var swiftkitCoreFoundationData: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Data")
}
- static var swiftkitCoreGeneratedDataProtocol: JavaType {
- .class(package: "org.swift.swiftkit.core.generated", name: "DataProtocol")
+ static var swiftkitCoreFoundationDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "DataProtocol")
}
}
diff --git a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
index d9952724c..51d100350 100644
--- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
+++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
@@ -110,39 +110,6 @@ extension Swift2JavaTranslator {
// Apply any specializations registered after their target types were visited
visitor.applyPendingSpecializations()
-
-// self.visitFoundationDeclsIfNeeded(with: visitor)
- }
-
- private func visitFoundationDeclsIfNeeded(with visitor: Swift2JavaVisitor) {
- // If any API uses 'Foundation.Data' or 'FoundationEssentials.Data',
- // import 'Data' as if it's declared in this module.
- if let dataDecl = self.symbolTable[.foundationData] ?? self.symbolTable[.essentialsData] {
- let dataProtocolDecl = (self.symbolTable[.foundationDataProtocol] ?? self.symbolTable[.essentialsDataProtocol])!
- if self.isUsing(where: { $0 == dataDecl || $0 == dataProtocolDecl }) {
- visitor.visit(
- nominalDecl: dataDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATA.swift",
- )
- visitor.visit(
- nominalDecl: dataProtocolDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATAPROTOCOL.swift",
- )
- }
- }
-
- // Foundation.Date
- if let dateDecl = self.symbolTable[.foundationDate] ?? self.symbolTable[.essentialsDate] {
- if self.isUsing(where: { $0 == dateDecl }) {
- visitor.visit(
- nominalDecl: dateDecl.syntax!.asNominal!,
- in: nil,
- sourceFilePath: "Foundation/FAKE_FOUNDATION_DATE.swift",
- )
- }
- }
}
package func prepareForTranslation() {
diff --git a/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift b/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
index 2770a490c..bfcde7b30 100644
--- a/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
+++ b/Sources/SwiftJavaMacros/ImplementsJavaMacro.swift
@@ -213,7 +213,7 @@ extension JavaImplementationMacro: PeerMacro {
@used
#endif
@_cdecl(\(literal: cName))
- public func \(context.makeUniqueName(swiftName))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) {
+ public func \(context.makeUniqueName("\(swiftTypeName)_\(swiftName)"))(\(raw: cParameters.map{ $0.description }.joined(separator: ", ")))\(raw: cReturnType) {
\(body)
}
"""
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
new file mode 100644
index 000000000..aa391639f
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@JavaImplementation("org.swift.swiftkit.core.foundation.Data")
+extension Data {
+ @JavaMethod("$init")
+ static func _init(environment: UnsafeMutablePointer!, bytes: [UInt8]) -> Int64 {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Data(bytes))
+ return Int64(Int(bitPattern: result$))
+ }
+
+ @JavaMethod("$getCount")
+ static func _getCount(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Int64 {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return Int64(selfPointer$.pointee.count)
+ }
+
+ @JavaMethod("$toByteArray")
+ static func _toByteArray(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.withUnsafeBytes { buffer in
+ return buffer.getJNIValue(in: environment)
+ }
+ }
+
+ @JavaMethod("$toByteArrayIndirectCopy")
+ static func _toByteArrayIndirectCopy(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return [UInt8](selfPointer$.pointee)
+ }
+
+ @JavaMethod("$typeMetadataAddressDowncall")
+ static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
+ let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer))
+ }
+}
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
new file mode 100644
index 000000000..3c27cd7af
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+JNI.swift
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+@JavaImplementation("org.swift.swiftkit.core.foundation.Date")
+extension Date {
+ @JavaMethod("$init")
+ static func _init(environment: UnsafeMutablePointer!, timeIntervalSince1970: Double) -> Int64 {
+ let result$ = UnsafeMutablePointer.allocate(capacity: 1)
+ result$.initialize(to: Date(timeIntervalSince1970: timeIntervalSince1970))
+ return Int64(Int(bitPattern: result$))
+ }
+
+ @JavaMethod("$getTimeIntervalSince1970")
+ static func _getTimeIntervalSince1970(environment: UnsafeMutablePointer!, selfPointer: Int64) -> Double {
+ let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
+ guard let selfPointer$ else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.timeIntervalSince1970
+ }
+
+ @JavaMethod("$typeMetadataAddressDowncall")
+ static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
+ let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
+ return Int64(Int(bitPattern: metadataPointer))
+ }
+}
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
deleted file mode 100644
index dbe1a8f05..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/Data+SwiftJava.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for Data
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_Data {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024init___3B")
-public func Java_org_swift_swiftkit_core_generated_Data__00024init___3B(environment: UnsafeMutablePointer!, thisClass: jclass, bytes: jbyteArray?) -> jlong {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Data.init([UInt8](fromJNI: bytes, in: environment)))
- let resultBits$ = Int64(Int(bitPattern: result$))
- return resultBits$.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024getCount__J")
-public func Java_org_swift_swiftkit_core_generated_Data__00024getCount__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jlong {
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
- let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return Int64(selfPointer$.pointee.count).getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__")
-public func Java_org_swift_swiftkit_core_generated_Data__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
deleted file mode 100644
index 3f7754f5e..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/DataProtocol+SwiftJava.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for DataProtocol
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_DataProtocol {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
deleted file mode 100644
index 838d8729e..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/Date+SwiftJava.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-
-// ==== --------------------------------------------------
-// Thunks for Date
-
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
-enum _JNI_Date {
-} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:166
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024init__D")
-public func Java_org_swift_swiftkit_core_generated_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
- let result$ = UnsafeMutablePointer.allocate(capacity: 1)
- result$.initialize(to: Date.init(timeIntervalSince1970: Double(fromJNI: timeIntervalSince1970, in: environment)))
- let resultBits$ = Int64(Int(bitPattern: result$))
- return resultBits$.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J")
-public func Java_org_swift_swiftkit_core_generated_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
- assert(selfPointer != 0, "selfPointer memory address was null")
- let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: environment))
- let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$)
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.timeIntervalSince1970.getJNILocalRefValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
-#if compiler(>=6.3)
-@used
-#endif
-@_cdecl("Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__")
-public func Java_org_swift_swiftkit_core_generated_Date__00024typeMetadataAddressDowncall__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- let metadataPointer = unsafeBitCast(Date.self, to: UnsafeRawPointer.self)
- return Int64(Int(bitPattern: metadataPointer)).getJNIValue(in: environment)
-} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:808
-
diff --git a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
deleted file mode 100644
index e24e89ffe..000000000
--- a/Sources/SwiftJavaRuntimeSupport/generated/SwiftJavaModule+SwiftJava.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-// Generated by swift-java
-
-import SwiftJava
-import SwiftJavaJNICore
-import SwiftJavaRuntimeSupport
-
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
-
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
similarity index 63%
rename from SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
index c6b0f3636..b4f58e69c 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Data.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
@@ -1,23 +1,32 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
-package org.swift.swiftkit.core.generated;
+package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-import java.util.*;
+
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Data implements JNISwiftInstance, DataProtocol {
- static final String LIB_NAME = "SwiftJava";
-
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -29,11 +38,11 @@ static boolean initializeLibs() {
private Data(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
-
+ }
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Data}.
*
@@ -46,30 +55,30 @@ private Data(long selfPointer, SwiftArena swiftArena) {
public static Data wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Data(selfPointer, swiftArena);
}
-
+
public static Data wrapMemoryAddressUnsafe(long selfPointer) {
return new Data(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
-
+
+
+
// ==== --------------------------------------------------
// Data.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -78,14 +87,14 @@ public static Data wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
return Data.wrapMemoryAddressUnsafe(Data.$init(Objects.requireNonNull(bytes, "bytes must not be null")), swiftArena);
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $init(byte[] bytes);
-
-
-
+
+
+
// ==== --------------------------------------------------
// getter:Data.count
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -94,23 +103,67 @@ public static Data init(@Unsigned byte[] bytes, SwiftArena swiftArena) {
*/
public long getCount() {
return Data.$getCount(this.$memoryAddress());
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $getCount(long selfPointer);
-
+
+ /**
+ * Creates a new Swift @{link Data} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the Data
+ * @param swiftArena The arena for memory management
+ * @return A new Data instance containing a copy of the bytes
+ */
+ public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return Data.init(bytes, swiftArena);
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * This is a relatively efficient implementation, which avoids native array copies,
+ * however it will still perform a copy of the data onto the JVM heap, so use this
+ * only when necessary.
+ *
+ * When utmost performance is necessary, you may want to investigate the FFM mode
+ * of jextract which is able to map memory more efficiently.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray() {
+ return $toByteArray(this.$memoryAddress());
+ }
+ private static native byte[] $toByteArray(long selfPointer);
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ *
+ * @deprecated Prefer using the `toByteArray` method as it is more performant.
+ * This implementation uses a naive conversion path from native bytes into jbytes
+ * and then copying them onto the jvm heap.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ @Deprecated(forRemoval = true)
+ public byte[] toByteArrayIndirectCopy() {
+ return $toByteArrayIndirectCopy(this.$memoryAddress());
+ }
+ private static native byte[] $toByteArrayIndirectCopy(long selfPointer);
+
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Data.$typeMetadataAddressDowncall();
- } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
-
+ }
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -129,5 +182,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
-} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
+ }
+}
diff --git a/Sources/FakeFoundation/DataProtocol.swift b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
similarity index 76%
rename from Sources/FakeFoundation/DataProtocol.swift
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
index d5a02d423..f3240bc0d 100644
--- a/Sources/FakeFoundation/DataProtocol.swift
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
@@ -12,10 +12,9 @@
//
//===----------------------------------------------------------------------===//
-#if canImport(FoundationEssentials)
-import FoundationEssentials
-#else
-import Foundation
-#endif
+package org.swift.swiftkit.core.foundation;
-public protocol DataProtocol {}
+import org.swift.swiftkit.core.JNISwiftInstance;
+
+public interface DataProtocol extends JNISwiftInstance {
+}
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
similarity index 62%
rename from SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
rename to SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
index 1e32774b5..157fe4f81 100644
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/Date.java
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
@@ -1,23 +1,31 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
-package org.swift.swiftkit.core.generated;
+package org.swift.swiftkit.core.foundation;
import org.swift.swiftkit.core.*;
import org.swift.swiftkit.core.util.*;
import org.swift.swiftkit.core.collections.*;
-import java.util.*;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.swift.swiftkit.core.annotations.*;
public final class Date implements JNISwiftInstance {
- static final String LIB_NAME = "SwiftJava";
-
@SuppressWarnings("unused")
private static final boolean INITIALIZED_LIBS = initializeLibs();
static boolean initializeLibs() {
System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
return true;
}
/**
@@ -29,11 +37,11 @@ static boolean initializeLibs() {
private Date(long selfPointer, SwiftArena swiftArena) {
SwiftObjects.requireNonZero(selfPointer, "selfPointer");
this.selfPointer = selfPointer;
-
+
// Only register once we have fully initialized the object since this will need the object pointer.
swiftArena.register(this);
- } // printConcreteType(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:230
-
+ }
+
/**
* Assume that the passed {@code long} represents a memory address of a {@link Date}.
*
@@ -46,29 +54,29 @@ private Date(long selfPointer, SwiftArena swiftArena) {
public static Date wrapMemoryAddressUnsafe(long selfPointer, SwiftArena swiftArena) {
return new Date(selfPointer, swiftArena);
}
-
+
public static Date wrapMemoryAddressUnsafe(long selfPointer) {
return new Date(selfPointer, SwiftMemoryManagement.DEFAULT_SWIFT_JAVA_AUTO_ARENA);
}
/** Pointer to the "self". */
private final long selfPointer;
-
+
/** Used to track additional state of the underlying object, e.g. if it was explicitly destroyed. */
private final AtomicBoolean $state$destroyed = new AtomicBoolean(false);
-
+
public long $memoryAddress() {
return this.selfPointer;
}
-
+
@Override
public AtomicBoolean $statusDestroyedFlag() {
return $state$destroyed;
}
-
-
+
+
// ==== --------------------------------------------------
// Date.init
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -77,13 +85,13 @@ public static Date wrapMemoryAddressUnsafe(long selfPointer) {
*/
public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
return Date.wrapMemoryAddressUnsafe(Date.$init(timeIntervalSince1970), swiftArena);
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native long $init(double timeIntervalSince1970);
-
-
+
+
// ==== --------------------------------------------------
// getter:Date.timeIntervalSince1970
-
+
/**
* Downcall to Swift:
* {@snippet lang=swift :
@@ -92,23 +100,66 @@ public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
*/
public double getTimeIntervalSince1970() {
return Date.$getTimeIntervalSince1970(this.$memoryAddress());
- } // printJavaBindingWrapperMethod(_:_:importedFunc:skipMethodBody:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:684
+ }
private static native double $getTimeIntervalSince1970(long selfPointer);
-
+
+ /**
+ * Converts this wrapped date to a Java {@link java.time.Instant}.
+ *
+ * This method constructs the {@code Instant} using the underlying {@code double} value
+ * representing seconds since the Unix Epoch (January 1, 1970).
+ *
+ *
+ * @return A {@code java.time.Instant} derived from the floating-point timestamp.
+ */
+ public java.time.Instant toInstant() {
+ long seconds = (long) this.getTimeIntervalSince1970();
+ long nanos = Math.round((this.getTimeIntervalSince1970() - seconds) * 1_000_000_000);
+ return java.time.Instant.ofEpochSecond(seconds, nanos);
+ }
+
+ /**
+ * Initializes a Swift {@code Foundation.Date} from a Java {@link java.time.Instant}.
+ *
+ * Warning: Precision Loss
+ *
+ * The input precision will be degraded.
+ *
+ *
+ * Java's {@code Instant} stores time with nanosecond precision (9 decimal places).
+ * However, this class stores time as a 64-bit floating-point value.
+ *
+ *
+ * This leaves enough capacity for microsecond precision (approx. 6 decimal places).
+ *
+ *
+ * Consequently, the last ~3 digits of the {@code Instant}'s nanosecond field will be
+ * truncated or subjected to rounding errors during conversion.
+ *
+ *
+ * @param instant The source timestamp to convert.
+ * @return A date derived from the input instant with microsecond precision.
+ */
+ public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
+ Objects.requireNonNull(instant, "Instant cannot be null");
+ double timeIntervalSince1970 = instant.getEpochSecond() + (instant.getNano() / 1_000_000_000.0);
+ return Date.init(timeIntervalSince1970, swiftArena);
+ }
+
private static native long $typeMetadataAddressDowncall();
@Override
public long $typeMetadataAddress() {
return Date.$typeMetadataAddressDowncall();
- } // printTypeMetadataAddressFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:776
-
+ }
+
public String toString() {
return SwiftObjects.toString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
public String toDebugString() {
return SwiftObjects.toDebugString(this.$memoryAddress(), this.$typeMetadataAddress());
}
-
+
@Override
public Runnable $createDestroyFunction() {
long self$ = this.$memoryAddress();
@@ -127,5 +178,5 @@ public void run() {
SwiftObjects.destroy(self$, selfType$);
}
};
- } // printDestroyFunction(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:790
-} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:402
+ }
+}
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
deleted file mode 100644
index 8e9c0b90f..000000000
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/DataProtocol.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
-
-package org.swift.swiftkit.core.generated;
-
-import org.swift.swiftkit.core.*;
-import org.swift.swiftkit.core.util.*;
-import org.swift.swiftkit.core.collections.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.swift.swiftkit.core.annotations.*;
-
-public interface DataProtocol extends JNISwiftInstance {
-} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:154
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
deleted file mode 100644
index 0a19e273c..000000000
--- a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/generated/SwiftJava.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Generated by jextract-swift
-// Swift module: SwiftJava
-
-package org.swift.swiftkit.core.generated;
-
-import org.swift.swiftkit.core.*;
-import org.swift.swiftkit.core.util.*;
-import org.swift.swiftkit.core.collections.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.swift.swiftkit.core.annotations.*;
-
-public final class SwiftJava {
- static final String LIB_NAME = "SwiftJava";
-
- static {
- System.loadLibrary(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
- System.loadLibrary(LIB_NAME);
- }
-} // printModuleClass(_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:410
From ce6ec4cde3af1f209ea0c964457384a6558f739a Mon Sep 17 00:00:00 2001
From: Iceman
Date: Mon, 6 Apr 2026 12:56:23 +0900
Subject: [PATCH 03/11] implement without macro for jbytearray returning
functions
---
.../test/java/com/example/swift/DateTest.java | 3 +-
.../java/com/example/swift/OptionalsTest.java | 5 +-
...ift2JavaGenerator+SwiftThunkPrinting.swift | 62 -------------------
.../Foundation/Data+JNI.swift | 55 ++++++++++------
4 files changed, 40 insertions(+), 85 deletions(-)
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
index 9b13f37ec..36da11d9d 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/DateTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Date;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -59,4 +60,4 @@ void date_timeIntervalSince1970() {
assertEquals(1000, date.getTimeIntervalSince1970());
}
}
-}
\ No newline at end of file
+}
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
index 771cffc33..941d2a545 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/test/java/com/example/swift/OptionalsTest.java
@@ -14,9 +14,10 @@
package com.example.swift;
-import com.example.swift.MySwiftLibrary;
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Data;
+import org.swift.swiftkit.core.foundation.Date;
import java.time.Instant;
import java.util.Optional;
@@ -143,4 +144,4 @@ void optionalThrows() {
assertEquals("swiftError", exception.getMessage());
}
}
-}
\ No newline at end of file
+}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 544b1b5ac..24c106c01 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -347,7 +347,6 @@ extension JNISwift2JavaGenerator {
printer.println()
}
- printSpecificTypeThunks(&printer, type)
printTypeMetadataAddressThunk(&printer, type)
printer.println()
}
@@ -856,67 +855,6 @@ extension JNISwift2JavaGenerator {
}
}
- /// Prints thunks for specific known types like Foundation.Date, Foundation.Data
- private func printSpecificTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
- guard let knownType = type.swiftNominal.knownTypeKind else { return }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataThunks(&printer, type)
- printer.println()
-
- default:
- break
- }
- }
-
- /// Prints Swift thunks for Foundation.Data helper methods
- private func printFoundationDataThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) {
- let selfPointerParam = JavaParameter(name: "selfPointer", type: .long)
- let parentName = type.qualifiedName
-
- // Rebind the memory instead of converting, and set the memory directly using 'jniSetArrayRegion' from the buffer
- printCDecl(
- &printer,
- javaMethodName: "$toByteArray",
- parentName: type.effectiveJavaName,
- parameters: [
- selfPointerParam
- ],
- resultType: .array(.byte),
- ) { printer in
- let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
-
- printer.print(
- """
- return \(selfVar).pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
- }
- """
- )
- }
-
- // Legacy API, also to compare with as a baseline, we could remove it
- printCDecl(
- &printer,
- javaMethodName: "$toByteArrayIndirectCopy",
- parentName: type.effectiveJavaName,
- parameters: [
- selfPointerParam
- ],
- resultType: .array(.byte),
- ) { printer in
- let selfVar = self.printSelfJLongToUnsafeMutablePointer(&printer, swiftParentName: parentName, selfPointerParam)
-
- printer.print(
- """
- // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
- return [UInt8](\(selfVar).pointee).getJNIValue(in: environment)
- """
- )
- }
- }
-
private func printFunctionOpenerCall(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
guard let translatedDecl = self.translatedDecl(for: decl) else {
fatalError("Cannot print function opener for a function that can't be translated: \(decl)")
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
index aa391639f..8110af8f3 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -39,29 +39,44 @@ extension Data {
return Int64(selfPointer$.pointee.count)
}
- @JavaMethod("$toByteArray")
- static func _toByteArray(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return selfPointer$.pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
- }
- }
-
- @JavaMethod("$toByteArrayIndirectCopy")
- static func _toByteArrayIndirectCopy(environment: UnsafeMutablePointer!, selfPointer: Int64) -> [UInt8] {
- let selfPointer$ = UnsafeMutablePointer(bitPattern: Int(selfPointer))
- guard let selfPointer$ else {
- fatalError("selfPointer memory address was null in call to \(#function)!")
- }
- return [UInt8](selfPointer$.pointee)
- }
-
@JavaMethod("$typeMetadataAddressDowncall")
static func _typeMetadataAddressDowncall(environment: UnsafeMutablePointer!) -> Int64 {
let metadataPointer = unsafeBitCast(Data.self, to: UnsafeRawPointer.self)
return Int64(Int(bitPattern: metadataPointer))
}
}
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ return selfPointer$.pointee.withUnsafeBytes { buffer in
+ return buffer.getJNIValue(in: environment)
+ }
+}
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+ guard let env$ = environment else {
+ fatalError("Missing JNIEnv in downcall to \(#function)")
+ }
+ assert(selfPointer != 0, "selfPointer memory address was null")
+ let selfPointerBits$ = Int(Int64(fromJNI: selfPointer, in: env$))
+ guard let selfPointer$ = UnsafeMutablePointer(bitPattern: selfPointerBits$) else {
+ fatalError("selfPointer memory address was null in call to \(#function)!")
+ }
+ // This is a double copy, we need to initialize the array and then copy into a JVM array in getJNIValue
+ return [UInt8](selfPointer$.pointee).getJNIValue(in: environment)
+}
From cc176f8508465bf559f022b3f1fb1875ce5bd5ab Mon Sep 17 00:00:00 2001
From: Iceman
Date: Mon, 6 Apr 2026 15:41:46 +0900
Subject: [PATCH 04/11] Remove generate script
---
scripts/swiftkit-jni-generate-bindings.sh | 50 -----------------------
1 file changed, 50 deletions(-)
delete mode 100755 scripts/swiftkit-jni-generate-bindings.sh
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
deleted file mode 100755
index a83e97309..000000000
--- a/scripts/swiftkit-jni-generate-bindings.sh
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-##===----------------------------------------------------------------------===##
-##
-## This source file is part of the Swift.org open source project
-##
-## Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-## Licensed under Apache License v2.0
-##
-## See LICENSE.txt for license information
-## See CONTRIBUTORS.txt for the list of Swift.org project authors
-##
-## SPDX-License-Identifier: Apache-2.0
-##
-##===----------------------------------------------------------------------===##
-
-# Regenerate FFM bindings for types in SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/
-#
-# Run from the swift-java repository root:
-# ./scripts/swiftkit-ffm-generate-bindings.sh
-
-set -euo pipefail
-
-REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
-
-JAVA_OUTPUT="${REPO_ROOT}/SwiftKitCore/src/main/java"
-JAVA_PACKAGE="org.swift.swiftkit.core.generated"
-
-# Declare types to generate: SWIFT_MODULE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
-TYPES=(
- "SwiftJava Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/generated"
-)
-
-for entry in "${TYPES[@]}"; do
- read -r MODULE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
-
- echo "==> Generating ${INPUT_SWIFT}..."
-
- xcrun swift run swift-java jextract \
- --mode jni \
- --swift-module "$MODULE" \
- --input-swift "${REPO_ROOT}/${INPUT_SWIFT}" \
- --output-swift "${REPO_ROOT}/${OUTPUT_SWIFT}" \
- --output-java "$JAVA_OUTPUT" \
- --java-package "$JAVA_PACKAGE"
-
- echo " Swift thunks: ${OUTPUT_SWIFT}/"
- echo " Java output: SwiftKitCore/src/main/java/$(echo "$JAVA_PACKAGE" | tr '.' '/')/"
-done
-
-echo "==> Done."
From ae82915f9e1610e366557fceb0efb3eff23cf92e Mon Sep 17 00:00:00 2001
From: Iceman
Date: Tue, 7 Apr 2026 17:38:11 +0900
Subject: [PATCH 05/11] Fix ffm java generated code
---
.../com/example/swift/HelloJava2Swift.java | 3 +-
...FMSwift2JavaGenerator+FoundationData.swift | 166 -------
...t2JavaGenerator+JavaBindingsPrinting.swift | 14 +-
...MSwift2JavaGenerator+JavaTranslation.swift | 48 ++-
.../FFM/FFMSwift2JavaGenerator.swift | 17 -
.../JavaTypes/JavaType+JDK.swift | 8 +
.../swift/swiftkit/ffm/foundation/Data.java | 406 ++++++++++++++++++
.../swiftkit/ffm/foundation/DataProtocol.java | 75 ++++
8 files changed, 543 insertions(+), 194 deletions(-)
delete mode 100644 Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
create mode 100644 SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
index 62c29482a..53fca07b6 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/main/java/com/example/swift/HelloJava2Swift.java
@@ -22,6 +22,7 @@
import org.swift.swiftkit.core.SwiftLibraries;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
import org.swift.swiftkit.ffm.SwiftRuntime;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.util.Optional;
import java.util.OptionalLong;
@@ -85,7 +86,7 @@ static void examples() {
var origBytes = arena.allocateFrom("foobar");
var origDat = Data.init(origBytes, origBytes.byteSize(), arena);
CallTraces.trace("origDat.count = " + origDat.getCount());
-
+
var retDat = MySwiftLibrary.globalReceiveReturnData(origDat, arena);
retDat.withUnsafeBytes((retBytes) -> {
var str = retBytes.getString(0);
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
deleted file mode 100644
index 7dd054f22..000000000
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+FoundationData.swift
+++ /dev/null
@@ -1,166 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift.org open source project
-//
-// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
-// Licensed under Apache License v2.0
-//
-// See LICENSE.txt for license information
-// See CONTRIBUTORS.txt for the list of Swift.org project authors
-//
-// SPDX-License-Identifier: Apache-2.0
-//
-//===----------------------------------------------------------------------===//
-
-import CodePrinting
-import SwiftJavaConfigurationShared
-import SwiftJavaJNICore
-import SwiftSyntax
-import SwiftSyntaxBuilder
-
-import struct Foundation.URL
-
-extension FFMSwift2JavaGenerator {
-
- /// Print Java helper methods for Foundation.Data type
- package func printFoundationDataHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- let typeName = decl.swiftNominal.name
- let thunkNameCopyBytes = "swiftjava_\(swiftModuleName)_\(typeName)_copyBytes__"
-
- printer.printSeparator("\(typeName) helper methods")
-
- // This is primarily here for API parity with the JNI version and easier discovery
- printer.print(
- """
- /**
- * Creates a new Swift {@link \(typeName)} instance from a byte array.
- *
- * @param bytes The byte array to copy into the \(typeName)
- * @param arena The arena for memory management
- * @return A new \(typeName) instance containing a copy of the bytes
- */
- public static \(typeName) fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
- Objects.requireNonNull(bytes, "bytes cannot be null");
- return \(typeName).init(bytes, arena);
- }
- """
- )
-
- // TODO: Implement a fromByteBuffer as well
-
- // Print the descriptor class for copyBytes native call using the shared helper
- let copyBytesCFunc = CFunction(
- resultType: .void,
- name: thunkNameCopyBytes,
- parameters: [
- CParameter(name: "self", type: .qualified(const: true, volatile: false, type: .pointer(.void))),
- CParameter(name: "destination", type: .pointer(.void)),
- CParameter(name: "count", type: .integral(.ptrdiff_t)),
- ],
- isVariadic: false
- )
- printJavaBindingDescriptorClass(&printer, copyBytesCFunc)
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new {@link MemorySegment}.
- *
- * This is the most efficient way to access \(typeName) bytes from Java when you don't
- * need a {@code byte[]}. The returned segment is valid for the lifetime of the arena.
- *
- * Copy count: 1 (Swift Data -> MemorySegment)
- *
- * @param arena The arena to allocate the segment in
- * @return A MemorySegment containing a copy of this \(typeName)'s bytes
- */
- public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return MemorySegment.NULL;
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment;
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new {@link ByteBuffer}.
- *
- * The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
- * lifetime of the arena. This avoids an additional copy to the Java heap.
- *
- *
Copy count: 1 (Swift Data -> native memory (managed by passed arena), then zero-copy view)
- *
- * @param arena The arena to allocate the underlying memory in
- * @return A ByteBuffer view of the copied bytes
- */
- public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return java.nio.ByteBuffer.allocate(0);
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.asByteBuffer();
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new byte array.
- * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
- *
- *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
- *
- *
For better performance when you can work with {@link MemorySegment} or
- * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
- *
- * @param arena The arena to use for temporary native memory allocation
- * @return A byte array containing a copy of this \(typeName)'s bytes
- */
- public byte[] toByteArray(AllocatingSwiftArena arena) {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return new byte[0];
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.toArray(ValueLayout.JAVA_BYTE);
- }
- """
- )
-
- printer.print(
- """
- /**
- * Copies the contents of this \(typeName) to a new byte array.
- * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
- *
- * This is a convenience method that creates a temporary arena for the copy.
- * For repeated calls, prefer {@link #toByteArray(AllocatingSwiftArena)} to reuse an arena.
- *
- *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
- *
- *
For better performance when you can work with {@link MemorySegment} or
- * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
- *
- * @return A byte array containing a copy of this \(typeName)'s bytes
- */
- public byte[] toByteArray() {
- $ensureAlive();
- long count = getCount();
- if (count == 0) return new byte[0];
- try (var arena = Arena.ofConfined()) {
- MemorySegment segment = arena.allocate(count);
- \(thunkNameCopyBytes).call(this.$memorySegment(), segment, count);
- return segment.toArray(ValueLayout.JAVA_BYTE);
- }
- }
- """
- )
- }
-}
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index cb7eac727..48cf4c331 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -456,6 +456,8 @@ extension FFMSwift2JavaGenerator {
let arena =
if let className = type.className,
analysis.importedTypes[className] != nil
+ || type == .swiftkitFFMFoundationData
+ || type == .swiftkitFFMFoundationDataProtocol
{
// Use passed-in 'SwiftArena' for 'SwiftValue'.
"swiftArena"
@@ -619,8 +621,14 @@ extension FFMSwift2JavaGenerator {
func renderMemoryLayoutValue(for javaType: JavaType) -> String {
if let layout = ForeignValueLayout(javaType: javaType) {
return layout.description
- } else if case .class(package: _, name: let customClass, _) = javaType {
- return ForeignValueLayout(customType: customClass).description
+ } else if case .class(let package, name: let customClass, _) = javaType {
+ let type =
+ if let package {
+ "\(package).\(customClass)"
+ } else {
+ customClass
+ }
+ return ForeignValueLayout(customType: type).description
} else {
fatalError("renderMemoryLayoutValue not supported for \(javaType)")
}
@@ -776,7 +784,7 @@ extension FFMSwift2JavaGenerator.JavaConversionStep {
case .wrapMemoryAddressUnsafe(let inner, let javaType):
let inner = inner.render(&printer, placeholder, placeholderForDowncall: placeholderForDowncall)
- return "\(javaType.className!).wrapMemoryAddressUnsafe(\(inner), swiftArena)"
+ return "\(javaType).wrapMemoryAddressUnsafe(\(inner), swiftArena)"
case .construct(let inner, let javaType):
let inner = inner.render(&printer, placeholder, placeholderForDowncall: placeholderForDowncall)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index c750fdc0a..decc8a547 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -464,7 +464,15 @@ extension FFMSwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- break
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(
+ name: parameterName,
+ type: .swiftkitFFMFoundationData
+ )
+ ],
+ conversion: .swiftValueSelfSegment(.placeholder)
+ )
case .swiftJavaError:
// SwiftJavaError is a class — treat as arbitrary nominal type below
@@ -635,10 +643,28 @@ extension FFMSwift2JavaGenerator {
case .nominal(let nominal):
if let knownType = nominal.nominalTypeDecl.knownTypeKind {
switch knownType {
- case .foundationData, .foundationDataProtocol:
- break
- case .essentialsData, .essentialsDataProtocol:
- break
+ case .foundationData, .essentialsData:
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(name: parameterName, type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationData]
+ ))
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
+ case .foundationDataProtocol, .essentialsDataProtocol:
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(name: parameterName, type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationDataProtocol]
+ ))
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
default:
throw JavaTranslationError.unhandledType(known: .optional(swiftType))
}
@@ -647,7 +673,7 @@ extension FFMSwift2JavaGenerator {
let translatedTy = try self.translate(swiftType: swiftType)
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: JavaType(className: "Optional<\(translatedTy.description)>"))
+ JavaParameter(name: parameterName, type: .class(package: nil, name: "Optional", typeParameters: [translatedTy]))
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
@@ -750,7 +776,15 @@ extension FFMSwift2JavaGenerator {
)
case .foundationData, .essentialsData:
- break // Implemented as wrapper
+ let javaType: JavaType = .swiftkitFFMFoundationData
+ return TranslatedResult(
+ javaResultType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [
+ JavaParameter(name: "", type: javaType)
+ ],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType)
+ )
case .unsafePointer, .unsafeMutablePointer:
// FIXME: Implement
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 6f5f1b8c6..bf4ef1e80 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -328,9 +328,6 @@ extension FFMSwift2JavaGenerator {
printFunctionDowncallMethods(&printer, funcDecl)
}
- // Special helper methods for known types (e.g. Data)
- printSpecificTypeHelpers(&printer, decl)
-
if let printSpecialPostExtras = self.getSpecialNominalPostMembersPrinting(decl) {
printSpecialPostExtras(&printer)
} else {
@@ -555,20 +552,6 @@ extension FFMSwift2JavaGenerator {
)
}
- /// Print special helper methods for known types like Foundation.Data
- func printSpecificTypeHelpers(_ printer: inout CodePrinter, _ decl: ImportedNominalType) {
- guard let knownType = decl.swiftNominal.knownTypeKind else {
- return
- }
-
- switch knownType {
- case .foundationData, .essentialsData:
- printFoundationDataHelpers(&printer, decl)
- default:
- break
- }
- }
-
/// Print the `fetchDescription` static helper for SwiftJavaError.
/// This calls the `errorDescription()` downcall to get the error message
/// for the super constructor
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 32e01b26f..6790c5af9 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -70,4 +70,12 @@ extension JavaType {
static var swiftkitCoreFoundationDataProtocol: JavaType {
.class(package: "org.swift.swiftkit.core.foundation", name: "DataProtocol")
}
+
+ static var swiftkitFFMFoundationData: JavaType {
+ .class(package: "org.swift.swiftkit.ffm.foundation", name: "Data")
+ }
+
+ static var swiftkitFFMFoundationDataProtocol: JavaType {
+ .class(package: "org.swift.swiftkit.ffm.foundation", name: "DataProtocol")
+ }
}
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
new file mode 100644
index 000000000..ffeaea2eb
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
@@ -0,0 +1,406 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+package org.swift.swiftkit.ffm.foundation;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.ffm.*;
+import org.swift.swiftkit.ffm.generated.*;
+import org.swift.swiftkit.core.annotations.*;
+import java.lang.foreign.*;
+import java.lang.invoke.*;
+import java.util.*;
+
+public final class Data extends FFMSwiftInstance implements SwiftValue {
+ static final String LIB_NAME = "SwiftRuntimeFunctions";
+ static final Arena LIBRARY_ARENA = Arena.ofAuto();
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_CORE);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
+ SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
+ return true;
+ }
+
+ public static final SwiftAnyType TYPE_METADATA =
+ new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "Data"));
+ public SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public GroupLayout $layout() {
+ return $LAYOUT;
+ }
+
+ private Data(MemorySegment segment, AllocatingSwiftArena arena) {
+ super(segment, arena);
+ }
+
+ /**
+ * Assume that the passed {@code MemorySegment} represents a memory address of a {@link Data}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual Data types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static Data wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
+ return new Data(selfPointer, arena);
+ }
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* bytes: */SwiftValueLayout.SWIFT_POINTER,
+ /* count: */SwiftValueLayout.SWIFT_INT,
+ /* _result: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(bytes, count, _result);
+ }
+ HANDLE.invokeExact(bytes, count, _result);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(bytes: UnsafeRawPointer, count: Int)
+ * }
+ */
+ public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena) throws SwiftIntegerOverflowException {
+ MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ if (SwiftValueLayout.has32bitSwiftInt) {
+ if (count < Integer.MIN_VALUE || count > Integer.MAX_VALUE) {
+ throw new SwiftIntegerOverflowException("Parameter 'count' overflow: " + count);
+ }
+ }
+ swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count.call(bytes, count, result$);
+ return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
+ }
+
+ // ==== --------------------------------------------------
+ // Data.init
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_init__(const void *bytes_pointer, ptrdiff_t bytes_count, void *_result)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_init__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* bytes_pointer: */SwiftValueLayout.SWIFT_POINTER,
+ /* bytes_count: */SwiftValueLayout.SWIFT_INT,
+ /* _result: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_init__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment bytes_pointer, long bytes_count, java.lang.foreign.MemorySegment _result) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(bytes_pointer, bytes_count, _result);
+ }
+ HANDLE.invokeExact(bytes_pointer, bytes_count, _result);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public init(_ bytes: [UInt8])
+ * }
+ */
+ public static Data init(@Unsigned byte[] bytes, AllocatingSwiftArena swiftArena) {
+ try(var arena$ = Arena.ofConfined()) {
+ MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ swiftjava_SwiftRuntimeFunctions_Data_init__.call(arena$.allocateFrom(ValueLayout.JAVA_BYTE, bytes), bytes.length, result$);
+ return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
+ }
+ }
+
+ // ==== --------------------------------------------------
+ // getter:Data.count
+
+ /**
+ * {@snippet lang=c :
+ * ptrdiff_t swiftjava_SwiftRuntimeFunctions_Data_count$get(const void *self)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_count$get {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.of(
+ /* -> */SwiftValueLayout.SWIFT_INT,
+ /* self: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_count$get");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static long call(java.lang.foreign.MemorySegment self) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(self);
+ }
+ return (long) HANDLE.invokeExact(self);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public var count: Int
+ * }
+ */
+ public long getCount() throws SwiftIntegerOverflowException {
+ $ensureAlive();
+ long result$checked = swiftjava_SwiftRuntimeFunctions_Data_count$get.call(this.$memorySegment());
+ if (SwiftValueLayout.has32bitSwiftInt) {
+ if (result$checked < Integer.MIN_VALUE || result$checked > Integer.MAX_VALUE) {
+ throw new SwiftIntegerOverflowException("Return value overflow: " + result$checked);
+ }
+ }
+ return result$checked;
+ }
+
+ // ==== --------------------------------------------------
+ // Data.withUnsafeBytes
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* body: */SwiftValueLayout.SWIFT_POINTER,
+ /* self: */SwiftValueLayout.SWIFT_POINTER
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(body, self);
+ }
+ HANDLE.invokeExact(body, self);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ /**
+ * {snippet lang=c :
+ * void (*)(const void *, ptrdiff_t)
+ * }
+ */
+ private static class $body {
+ @FunctionalInterface
+ public interface Function {
+ void apply(java.lang.foreign.MemorySegment _0, long _1);
+ }
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* _0: */SwiftValueLayout.SWIFT_POINTER,
+ /* _1: */SwiftValueLayout.SWIFT_INT
+ );
+ private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC);
+ private static MemorySegment toUpcallStub(Function fi, Arena arena) {
+ return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
+ }
+ }
+ }
+ public static class withUnsafeBytes {
+ @FunctionalInterface
+ public interface body {
+ void apply(java.lang.foreign.MemorySegment _0);
+ }
+ private static MemorySegment $toUpcallStub(body fi, Arena arena) {
+ return swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> {
+ fi.apply(_0_pointer.reinterpret(_0_count));
+ }, arena);
+ }
+ }
+
+ /**
+ * Downcall to Swift:
+ * {@snippet lang=swift :
+ * public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
+ * }
+ */
+ public void withUnsafeBytes(withUnsafeBytes.body body) {
+ $ensureAlive();
+ try(var arena$ = Arena.ofConfined()) {
+ swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment());
+ }
+ }
+
+ // ==== --------------------------------------------------
+ // Data helper methods
+
+ /**
+ * Creates a new Swift {@link Data} instance from a byte array.
+ *
+ * @param bytes The byte array to copy into the Data
+ * @param arena The arena for memory management
+ * @return A new Data instance containing a copy of the bytes
+ */
+ public static Data fromByteArray(byte[] bytes, AllocatingSwiftArena arena) {
+ Objects.requireNonNull(bytes, "bytes cannot be null");
+ return Data.init(bytes, arena);
+ }
+
+ /**
+ * {@snippet lang=c :
+ * void swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(void *const self, void *destination, ptrdiff_t count)
+ * }
+ */
+ private static class swiftjava_SwiftRuntimeFunctions_Data_copyBytes__ {
+ private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
+ /* self: */SwiftValueLayout.SWIFT_POINTER,
+ /* destination: */SwiftValueLayout.SWIFT_POINTER,
+ /* count: */SwiftValueLayout.SWIFT_INT
+ );
+ private static final MemorySegment ADDR =
+ SwiftRuntime.findOrThrow("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__");
+ private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
+ public static void call(java.lang.foreign.MemorySegment self, java.lang.foreign.MemorySegment destination, long count) {
+ try {
+ if (CallTraces.TRACE_DOWNCALLS) {
+ CallTraces.traceDowncall(self, destination, count);
+ }
+ HANDLE.invokeExact(self, destination, count);
+ } catch (Throwable ex$) {
+ throw new AssertionError("should not reach here", ex$);
+ }
+ }
+ }
+
+ /**
+ * Copies the contents of this Data to a new {@link MemorySegment}.
+ *
+ * This is the most efficient way to access Data bytes from Java when you don't
+ * need a {@code byte[]}. The returned segment is valid for the lifetime of the arena.
+ *
+ * Copy count: 1 (Swift Data -> MemorySegment)
+ *
+ * @param arena The arena to allocate the segment in
+ * @return A MemorySegment containing a copy of this Data's bytes
+ */
+ public MemorySegment toMemorySegment(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return MemorySegment.NULL;
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment;
+ }
+
+ /**
+ * Copies the contents of this Data to a new {@link java.nio.ByteBuffer}.
+ *
+ * The returned {@link java.nio.ByteBuffer} is a view over native memory and is valid for the
+ * lifetime of the arena. This avoids an additional copy to the Java heap.
+ *
+ *
Copy count: 1 (Swift Data -> native memory (managed by passed arena), then zero-copy view)
+ *
+ * @param arena The arena to allocate the underlying memory in
+ * @return A ByteBuffer view of the copied bytes
+ */
+ public java.nio.ByteBuffer toByteBuffer(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return java.nio.ByteBuffer.allocate(0);
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.asByteBuffer();
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @param arena The arena to use for temporary native memory allocation
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray(AllocatingSwiftArena arena) {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+
+ /**
+ * Copies the contents of this Data to a new byte array.
+ * The lifetime of the array is independent of the arena, the arena is just used for an intermediary copy.
+ *
+ * This is a convenience method that creates a temporary arena for the copy.
+ * For repeated calls, prefer {@link #toByteArray(AllocatingSwiftArena)} to reuse an arena.
+ *
+ *
Copy count: 2 (Swift Data -> MemorySegment -> byte[])
+ *
+ *
For better performance when you can work with {@link MemorySegment} or
+ * {@link java.nio.ByteBuffer}, prefer {@link #toMemorySegment} or {@link #toByteBuffer}.
+ *
+ * @return A byte array containing a copy of this Data's bytes
+ */
+ public byte[] toByteArray() {
+ $ensureAlive();
+ long count = getCount();
+ if (count == 0) return new byte[0];
+ try (var arena = Arena.ofConfined()) {
+ MemorySegment segment = arena.allocate(count);
+ swiftjava_SwiftRuntimeFunctions_Data_copyBytes__.call(this.$memorySegment(), segment, count);
+ return segment.toArray(ValueLayout.JAVA_BYTE);
+ }
+ }
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()
+ + "("
+ + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true)
+ + ")@"
+ + $memorySegment();
+ }
+}
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
new file mode 100644
index 000000000..2881ac85e
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+package org.swift.swiftkit.ffm.foundation;
+
+import org.swift.swiftkit.core.*;
+import org.swift.swiftkit.core.util.*;
+import org.swift.swiftkit.ffm.*;
+import org.swift.swiftkit.ffm.generated.*;
+import org.swift.swiftkit.core.annotations.*;
+import java.lang.foreign.*;
+import java.lang.invoke.*;
+import java.util.*;
+
+public final class DataProtocol extends FFMSwiftInstance implements SwiftValue {
+ static final String LIB_NAME = "SwiftRuntimeFunctions";
+ static final Arena LIBRARY_ARENA = Arena.ofAuto();
+ @SuppressWarnings("unused")
+ private static final boolean INITIALIZED_LIBS = initializeLibs();
+ static boolean initializeLibs() {
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_CORE);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_JAVA);
+ SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
+ SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
+ return true;
+ }
+
+ public static final SwiftAnyType TYPE_METADATA =
+ new SwiftAnyType(SwiftRuntime.swiftjava.getType("SwiftRuntimeFunctions", "DataProtocol"));
+ public SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public GroupLayout $layout() {
+ return $LAYOUT;
+ }
+
+ private DataProtocol(MemorySegment segment, AllocatingSwiftArena arena) {
+ super(segment, arena);
+ }
+
+ /**
+ * Assume that the passed {@code MemorySegment} represents a memory address of a {@link DataProtocol}.
+ *
+ * Warnings:
+ *
+ * - No checks are performed about the compatibility of the pointed at memory and the actual DataProtocol types.
+ * - This operation does not copy, or retain, the pointed at pointer, so its lifetime must be ensured manually to be valid when wrapping.
+ *
+ */
+ public static DataProtocol wrapMemoryAddressUnsafe(MemorySegment selfPointer, AllocatingSwiftArena arena) {
+ return new DataProtocol(selfPointer, arena);
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()
+ + "("
+ + SwiftRuntime.nameOfSwiftType($swiftType().$memorySegment(), true)
+ + ")@"
+ + $memorySegment();
+ }
+}
From c42156ff4b4b530532f12c4cc5cc5fc66ae10cd5 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Tue, 7 Apr 2026 17:52:44 +0900
Subject: [PATCH 06/11] native implementation and fix test import
---
.../swift/swiftkit/ffm/FFMDataBenchmark.java | 3 +-
.../com/example/swift/DataImportTest.java | 3 +-
.../com/example/swift/OptionalImportTest.java | 1 +
.../foundation/Data+FFM.swift | 70 +++++++++++++++++++
4 files changed, 74 insertions(+), 3 deletions(-)
create mode 100644 Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
index 39a64c7a9..2ce5950f2 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
@@ -14,7 +14,6 @@
package org.swift.swiftkit.ffm;
-import com.example.swift.Data;
import com.example.swift.MySwiftLibrary;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
@@ -79,7 +78,7 @@ public ByteBuffer ffm_data_withUnsafeBytes_asByteBuffer() {
});
return buf.value;
}
-
+
@Benchmark
public byte[] ffm_data_withUnsafeBytes_toArray() {
Holder buf = new Holder<>();
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
index 82fb09464..69ed9db31 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/DataImportTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.lang.foreign.ValueLayout;
@@ -134,7 +135,7 @@ void test_Data_toByteBuffer_emptyData() {
byte[] original = new byte[0];
var data = Data.fromByteArray(original, arena);
var buffer = data.toByteBuffer(arena);
-
+
assertEquals(0, buffer.capacity());
}
}
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
index 57e8dba61..306ce688c 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/test/java/com/example/swift/OptionalImportTest.java
@@ -16,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.ffm.AllocatingSwiftArena;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.util.Optional;
import java.util.OptionalLong;
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
new file mode 100644
index 000000000..157abe53e
--- /dev/null
+++ b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2026 Apple Inc. and the Swift.org project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of Swift.org project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+
+// ==== --------------------------------------------------
+// Thunks for Data
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_Data")
+public func swiftjava_getType_SwiftRuntimeFunctions_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
+ return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count")
+public func swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) {
+ _result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count))
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init__")
+public func swiftjava_SwiftRuntimeFunctions_Data_init__(_ bytes_pointer: UnsafeRawPointer, _ bytes_count: Int, _ _result: UnsafeMutableRawPointer) {
+ _result.assumingMemoryBound(to: Data.self).initialize(to: Data([UInt8](UnsafeRawBufferPointer(start: bytes_pointer, count: bytes_count))))
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_count$get")
+public func swiftjava_SwiftRuntimeFunctions_Data_count$get(_ self: UnsafeRawPointer) -> Int {
+ return self.assumingMemoryBound(to: Data.self).pointee.count
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__")
+public func swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
+ self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
+ return body(_0.baseAddress, _0.count)
+ })
+}
+
+@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_copyBytes__")
+public func swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(
+ selfPointer: UnsafeRawPointer,
+ destinationPointer: UnsafeMutableRawPointer,
+ count: Int
+) {
+ let data = selfPointer.assumingMemoryBound(to: Data.self).pointee
+ data.withUnsafeBytes { buffer in
+ destinationPointer.copyMemory(from: buffer.baseAddress!, byteCount: count)
+ }
+}
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
+public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
+ return unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
+}
From afae76e66ce8a779bc5955f68155252278bb313a Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 10:22:08 +0900
Subject: [PATCH 07/11] Fix test cases
---
.../JExtractSwiftTests/DataImportTests.swift | 253 +-----------------
Tests/JExtractSwiftTests/DateTests.swift | 149 +++--------
.../JNI/JNIDictionaryTest.swift | 16 +-
Tests/JExtractSwiftTests/JNI/JNISetTest.swift | 12 +-
.../OptionalImportTests.swift | 2 +-
.../SwiftSymbolTableTests.swift | 8 +-
6 files changed, 58 insertions(+), 382 deletions(-)
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index e67a3db87..c2ce81ca5 100644
--- a/Tests/JExtractSwiftTests/DataImportTests.swift
+++ b/Tests/JExtractSwiftTests/DataImportTests.swift
@@ -95,36 +95,6 @@ final class DataImportTests {
_result.assumingMemoryBound(to: Data.self).initialize(to: returnData())
}
""",
-
- """
- @_cdecl("swiftjava_getType_SwiftModule_Data")
- public func swiftjava_getType_SwiftModule_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_init_bytes_count")
- public func swiftjava_SwiftModule_Data_init_bytes_count(_ bytes: UnsafeRawPointer, _ count: Int, _ _result: UnsafeMutableRawPointer) {
- _result.assumingMemoryBound(to: Data.self).initialize(to: Data(bytes: bytes, count: count))
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_count$get")
- public func swiftjava_SwiftModule_Data_count$get(_ self: UnsafeRawPointer) -> Int {
- return self.assumingMemoryBound(to: Data.self).pointee.count
- }
- """,
-
- """
- @_cdecl("swiftjava_SwiftModule_Data_withUnsafeBytes__")
- public func swiftjava_SwiftModule_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
- self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
- return body(_0.baseAddress, _0.count)
- })
- }
- """,
]
)
}
@@ -174,7 +144,7 @@ final class DataImportTests {
* public func receiveData(dat: Data)
* }
*/
- public static void receiveData(Data dat) {
+ public static void receiveData(org.swift.swiftkit.ffm.foundation.Data dat) {
swiftjava_SwiftModule_receiveData_dat.call(dat.$memorySegment());
}
""",
@@ -212,178 +182,10 @@ final class DataImportTests {
* public func returnData() -> Data
* }
*/
- public static Data returnData(AllocatingSwiftArena swiftArena) {
- MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
+ public static org.swift.swiftkit.ffm.foundation.Data returnData(AllocatingSwiftArena swiftArena) {
+ MemorySegment result$ = swiftArena.allocate(org.swift.swiftkit.ffm.foundation.Data.$LAYOUT);
swiftjava_SwiftModule_returnData.call(result$);
- return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * void swiftjava_SwiftModule_Data_init_bytes_count(const void *bytes, ptrdiff_t count, void *_result)
- * }
- */
- private static class swiftjava_SwiftModule_Data_init_bytes_count {
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* bytes: */SwiftValueLayout.SWIFT_POINTER,
- /* count: */SwiftValueLayout.SWIFT_INT,
- /* _result: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_init_bytes_count");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static void call(java.lang.foreign.MemorySegment bytes, long count, java.lang.foreign.MemorySegment _result) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(bytes, count, _result);
- }
- HANDLE.invokeExact(bytes, count, _result);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public init(bytes: UnsafeRawPointer, count: Int)
- * }
- */
- public static Data init(java.lang.foreign.MemorySegment bytes, long count, AllocatingSwiftArena swiftArena) throws SwiftIntegerOverflowException {
- MemorySegment result$ = swiftArena.allocate(Data.$LAYOUT);
- if (SwiftValueLayout.has32bitSwiftInt) {
- if (count < Integer.MIN_VALUE || count > Integer.MAX_VALUE) {
- throw new SwiftIntegerOverflowException("Parameter 'count' overflow: " + count);
- }
- }
- swiftjava_SwiftModule_Data_init_bytes_count.call(bytes, count, result$);
- return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * ptrdiff_t swiftjava_SwiftModule_Data_count$get(const void *self)
- * }
- */
- private static class swiftjava_SwiftModule_Data_count$get {
- private static final FunctionDescriptor DESC = FunctionDescriptor.of(
- /* -> */SwiftValueLayout.SWIFT_INT,
- /* self: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_count$get");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static long call(java.lang.foreign.MemorySegment self) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(self);
- }
- return (long) HANDLE.invokeExact(self);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public var count: Int
- * }
- */
- public long getCount() throws SwiftIntegerOverflowException {
- $ensureAlive();
- long result$checked = swiftjava_SwiftModule_Data_count$get.call(this.$memorySegment());
- if (SwiftValueLayout.has32bitSwiftInt) {
- if (result$checked < Integer.MIN_VALUE || result$checked > Integer.MAX_VALUE) {
- throw new SwiftIntegerOverflowException("Return value overflow: " + result$checked);
- }
- }
- return result$checked;
- }
- """,
-
- """
- /**
- * {@snippet lang=c :
- * void swiftjava_SwiftModule_Data_withUnsafeBytes__(void (*body)(const void *, ptrdiff_t), const void *self)
- * }
- */
- private static class swiftjava_SwiftModule_Data_withUnsafeBytes__ {
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* body: */SwiftValueLayout.SWIFT_POINTER,
- /* self: */SwiftValueLayout.SWIFT_POINTER
- );
- private static final MemorySegment ADDR =
- SwiftModule.findOrThrow("swiftjava_SwiftModule_Data_withUnsafeBytes__");
- private static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
- public static void call(java.lang.foreign.MemorySegment body, java.lang.foreign.MemorySegment self) {
- try {
- if (CallTraces.TRACE_DOWNCALLS) {
- CallTraces.traceDowncall(body, self);
- }
- HANDLE.invokeExact(body, self);
- } catch (Throwable ex$) {
- throw new AssertionError("should not reach here", ex$);
- }
- }
- /**
- * {snippet lang=c :
- * void (*)(const void *, ptrdiff_t)
- * }
- */
- private static class $body {
- @FunctionalInterface
- public interface Function {
- void apply(java.lang.foreign.MemorySegment _0, long _1);
- }
- private static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
- /* _0: */SwiftValueLayout.SWIFT_POINTER,
- /* _1: */SwiftValueLayout.SWIFT_INT
- );
- private static final MethodHandle HANDLE = SwiftRuntime.upcallHandle(Function.class, "apply", DESC);
- private static MemorySegment toUpcallStub(Function fi, Arena arena) {
- return Linker.nativeLinker().upcallStub(HANDLE.bindTo(fi), DESC, arena);
- }
- }
- }
- """,
-
- """
- public static class withUnsafeBytes {
- @FunctionalInterface
- public interface body {
- void apply(java.lang.foreign.MemorySegment _0);
- }
- private static MemorySegment $toUpcallStub(body fi, Arena arena) {
- return swiftjava_SwiftModule_Data_withUnsafeBytes__.$body.toUpcallStub((_0_pointer, _0_count) -> {
- fi.apply(_0_pointer.reinterpret(_0_count));
- }, arena);
- }
- }
- """,
-
- """
- /**
- * Downcall to Swift:
- * {@snippet lang=swift :
- * public func withUnsafeBytes(_ body: (UnsafeRawBufferPointer) -> Void)
- * }
- */
- public void withUnsafeBytes(withUnsafeBytes.body body) {
- $ensureAlive();
- try(var arena$ = Arena.ofConfined()) {
- swiftjava_SwiftModule_Data_withUnsafeBytes__.call(withUnsafeBytes.$toUpcallStub(body, arena$), this.$memorySegment());
- }
+ return org.swift.swiftkit.ffm.foundation.Data.wrapMemoryAddressUnsafe(result$, swiftArena);
}
""",
]
@@ -413,11 +215,6 @@ final class DataImportTests {
receiveDataProtocol(dat: dat.assumingMemoryBound(to: Data.self).pointee, dat2: dat2?.assumingMemoryBound(to: Data.self).pointee)
}
""",
-
- // Just to make sure 'Data' is imported.
- """
- @_cdecl("swiftjava_getType_SwiftModule_Data")
- """,
]
)
}
@@ -470,15 +267,10 @@ final class DataImportTests {
* public func receiveDataProtocol(dat: some DataProtocol, dat2: T?)
* }
*/
- public static void receiveDataProtocol(Data dat, Optional dat2) {
+ public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, Optional dat2) {
swiftjava_SwiftModule_receiveDataProtocol_dat_dat2.call(dat.$memorySegment(), SwiftRuntime.toOptionalSegmentInstance(dat2));
}
""",
-
- // Just to make sure 'Data' is imported.
- """
- public final class Data extends FFMSwiftInstance implements SwiftValue {
- """,
]
)
}
@@ -499,7 +291,7 @@ final class DataImportTests {
detectChunkByInitialLines: 1,
expectedChunks: [
"""
- public static void acceptData(Data data) {
+ public static void acceptData(org.swift.swiftkit.core.foundation.Data data) {
SwiftModule.$acceptData(data.$memoryAddress());
}
"""
@@ -533,7 +325,7 @@ final class DataImportTests {
.java,
expectedChunks: [
"""
- public static Data returnData(SwiftArena swiftArena) {
+ public static org.swift.swiftkit.core.foundation.Data returnData(SwiftArena swiftArena) {
"""
]
)
@@ -551,33 +343,6 @@ final class DataImportTests {
)
}
- @Test("Import Data: JNI Data class")
- func data_jni_class() throws {
- let text = """
- import Foundation
- public func f() -> Data
- """
-
- try assertOutput(
- input: text,
- .jni,
- .java,
- detectChunkByInitialLines: 1,
- expectedChunks: [
- "public final class Data implements JNISwiftInstance, DataProtocol {",
- "public long getCount() {",
-
- "public static Data fromByteArray(byte[] bytes, SwiftArena swiftArena) {",
-
- "public byte[] toByteArray() {",
- "private static native byte[] $toByteArray(long selfPointer);",
-
- "public byte[] toByteArrayIndirectCopy() {",
- "private static native byte[] $toByteArrayIndirectCopy(long selfPointer);",
- ]
- )
- }
-
// ==== -----------------------------------------------------------------------
// MARK: JNI DataProtocol generic parameter
@@ -599,7 +364,7 @@ final class DataImportTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static MyResult processData(D data, SwiftArena swiftArena) {
+ public static MyResult processData(D data, SwiftArena swiftArena) {
"""
]
)
@@ -620,7 +385,7 @@ final class DataImportTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static boolean verify(D1 first, D2 second) {
+ public static boolean verify(D1 first, D2 second) {
"""
]
)
diff --git a/Tests/JExtractSwiftTests/DateTests.swift b/Tests/JExtractSwiftTests/DateTests.swift
index bf5e9ef8e..13a1e59f1 100644
--- a/Tests/JExtractSwiftTests/DateTests.swift
+++ b/Tests/JExtractSwiftTests/DateTests.swift
@@ -17,34 +17,8 @@ import SwiftJavaConfigurationShared
import Testing
struct DateTests {
- @Test(
- "Import: accept Date",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
- """
- public static void acceptDate(Date date) {
- SwiftModule.$acceptDate(date.$memoryAddress());
- }
- """
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
- public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
- """
- ],
- )
- ]
- )
- func func_accept_date(
- mode: JExtractGenerationMode,
- expectedJavaChunks: [String],
- expectedSwiftChunks: [String]
- ) throws {
+ @Test("Import: accept Date")
+ func func_accept_date() throws {
let text =
"""
import Foundation
@@ -54,47 +28,34 @@ struct DateTests {
try assertOutput(
input: text,
- mode,
+ .jni,
.java,
detectChunkByInitialLines: 1,
- expectedChunks: expectedJavaChunks
+ expectedChunks: [
+ """
+ public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
+ SwiftModule.$acceptDate(date.$memoryAddress());
+ }
+ """
+ ]
)
try assertOutput(
input: text,
- mode,
+ .jni,
.swift,
detectChunkByInitialLines: 1,
- expectedChunks: expectedSwiftChunks
+ expectedChunks: [
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
+ public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
+ """
+ ]
)
}
- @Test(
- "Import: return Date",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
- """
- public static Date returnDate(SwiftArena swiftArena) {
- """
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
- public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- """
- ]
- )
- ]
- )
- func func_return_Date(
- mode: JExtractGenerationMode,
- expectedJavaChunks: [String],
- expectedSwiftChunks: [String]
- ) throws {
+ @Test("Import: return Date")
+ func func_return_Date() throws {
let text =
"""
import Foundation
@@ -103,75 +64,25 @@ struct DateTests {
try assertOutput(
input: text,
- mode,
+ .jni,
.java,
- expectedChunks: expectedJavaChunks
- )
-
- try assertOutput(
- input: text,
- mode,
- .swift,
- expectedChunks: expectedSwiftChunks
- )
- }
-
- @Test(
- "Import: Date type",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
+ expectedChunks: [
"""
- public final class Date implements JNISwiftInstance {
- """,
+ public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
"""
- public static Date init(double timeIntervalSince1970, SwiftArena swiftArena) {
- """,
- """
- public double getTimeIntervalSince1970() {
- """,
- """
- public static Date fromInstant(java.time.Instant instant, SwiftArena swiftArena) {
- """,
- """
- public java.time.Instant toInstant() {
- """,
- ],
- /* expected Swift chunks */
- [
- """
- @_cdecl("Java_com_example_swift_Date__00024init__D")
- public func Java_com_example_swift_Date__00024init__D(environment: UnsafeMutablePointer!, thisClass: jclass, timeIntervalSince1970: jdouble) -> jlong {
- """,
- """
- @_cdecl("Java_com_example_swift_Date__00024getTimeIntervalSince1970__J")
- public func Java_com_example_swift_Date__00024getTimeIntervalSince1970__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jdouble {
- """,
- ]
- )
- ]
- )
- func date_class(mode: JExtractGenerationMode, expectedJavaChunks: [String], expectedSwiftChunks: [String]) throws {
- let text =
- """
- import Foundation
- public func f() -> Date
- """
-
- try assertOutput(
- input: text,
- mode,
- .java,
- expectedChunks: expectedJavaChunks
+ ],
)
try assertOutput(
input: text,
- mode,
+ .jni,
.swift,
- expectedChunks: expectedSwiftChunks
+ expectedChunks: [
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
+ public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ """
+ ]
)
}
}
diff --git a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
index 0690ee01d..ebb8ed163 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIDictionaryTest.swift
@@ -28,7 +28,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
""",
"""
@@ -104,7 +104,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -142,7 +142,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -183,7 +183,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -200,7 +200,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -217,7 +217,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -234,7 +234,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -295,7 +295,7 @@ struct JNIDictionaryTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftDictionaryMap f(org.swift.swiftkit.core.collections.SwiftDictionaryMap dict, java.lang.String key, long value, SwiftArena swiftArena) {
- return SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftDictionaryMap.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(dict, "dict must not be null").$memoryAddress(), key, value), swiftArena);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
index e654344d2..8adec8d58 100644
--- a/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNISetTest.swift
@@ -28,7 +28,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
""",
"""
@@ -104,7 +104,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress()), swiftArena);
}
""",
"""
@@ -145,7 +145,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -162,7 +162,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -179,7 +179,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(), swiftArena);
}
"""
]
@@ -240,7 +240,7 @@ struct JNISetTest {
expectedChunks: [
"""
public static org.swift.swiftkit.core.collections.SwiftSet f(org.swift.swiftkit.core.collections.SwiftSet set, java.lang.String element, SwiftArena swiftArena) {
- return SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena);
+ return org.swift.swiftkit.core.collections.SwiftSet.wrapMemoryAddressUnsafe(SwiftModule.$f(Objects.requireNonNull(set, "set must not be null").$memoryAddress(), element), swiftArena);
}
""",
"""
diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift
index fc169fe53..ea20272e3 100644
--- a/Tests/JExtractSwiftTests/OptionalImportTests.swift
+++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift
@@ -146,7 +146,7 @@ final class OptionalImportTests {
* public func receiveOptionalDataProto(_ arg: (some DataProtocol)?)
* }
*/
- public static void receiveOptionalDataProto(Optional arg) {
+ public static void receiveOptionalDataProto(Optional arg) {
swiftjava_SwiftModule_receiveOptionalDataProto__.call(SwiftRuntime.toOptionalSegmentInstance(arg));
}
""",
diff --git a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
index bdf00de18..a2b1fc9e3 100644
--- a/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
+++ b/Tests/JExtractSwiftTests/SwiftSymbolTableTests.swift
@@ -52,8 +52,8 @@ struct SwiftSymbolTableSuite {
#expect(symbolTable.lookupType("Z", parent: nil) == nil)
}
- @Test(arguments: [JExtractGenerationMode.jni, .ffm])
- func resolveSelfModuleName(mode: JExtractGenerationMode) throws {
+ @Test
+ func resolveSelfModuleName() throws {
try assertOutput(
input: """
import Foundation
@@ -62,13 +62,13 @@ struct SwiftSymbolTableSuite {
public func fullyQualifiedType() -> MyModule.MyValue
public func fullyQualifiedType2() -> Foundation.Data
""",
- mode,
+ .jni,
.java,
swiftModuleName: "MyModule",
detectChunkByInitialLines: 1,
expectedChunks: [
"public static MyValue fullyQualifiedType(",
- "public static Data fullyQualifiedType2(",
+ "public static org.swift.swiftkit.core.foundation.Data fullyQualifiedType2(",
],
)
}
From 9a6f3edd12e3d650e0f54d1a0f16d3849c955b25 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 10:33:14 +0900
Subject: [PATCH 08/11] Fix benchmark code imports
---
.../src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java | 1 +
.../src/jmh/java/com/example/swift/JNIDataBenchmark.java | 1 +
2 files changed, 2 insertions(+)
diff --git a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
index 2ce5950f2..6cac287ff 100644
--- a/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
+++ b/Samples/SwiftJavaExtractFFMSampleApp/src/jmh/java/org/swift/swiftkit/ffm/FFMDataBenchmark.java
@@ -17,6 +17,7 @@
import com.example.swift.MySwiftLibrary;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
diff --git a/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
index 283f1f7c0..52b1d16b8 100644
--- a/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
+++ b/Samples/SwiftJavaExtractJNISampleApp/src/jmh/java/com/example/swift/JNIDataBenchmark.java
@@ -18,6 +18,7 @@
import org.openjdk.jmh.infra.Blackhole;
import org.swift.swiftkit.core.ClosableSwiftArena;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Data;
import java.util.concurrent.TimeUnit;
From d9547652882b001a3e898b1f418441abd2f95010 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:02:15 +0900
Subject: [PATCH 09/11] swift format
---
...MSwift2JavaGenerator+JavaTranslation.swift | 26 +++++++++------
.../Foundation/Data+JNI.swift | 8 +++--
.../foundation/Data+FFM.swift | 8 ++---
Tests/JExtractSwiftTests/DateTests.swift | 32 +++++++++----------
4 files changed, 42 insertions(+), 32 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index decc8a547..d4387c234 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -646,22 +646,28 @@ extension FFMSwift2JavaGenerator {
case .foundationData, .essentialsData:
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationData]
- ))
+ JavaParameter(
+ name: parameterName,
+ type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationData]
+ )
+ )
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
case .foundationDataProtocol, .essentialsDataProtocol:
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationDataProtocol]
- ))
+ JavaParameter(
+ name: parameterName,
+ type: .class(
+ package: nil,
+ name: "Optional",
+ typeParameters: [.swiftkitFFMFoundationDataProtocol]
+ )
+ )
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
index 8110af8f3..2451ccd0b 100644
--- a/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+JNI.swift
@@ -60,7 +60,7 @@ public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(en
fatalError("selfPointer memory address was null in call to \(#function)!")
}
return selfPointer$.pointee.withUnsafeBytes { buffer in
- return buffer.getJNIValue(in: environment)
+ buffer.getJNIValue(in: environment)
}
}
@@ -68,7 +68,11 @@ public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArray__J(en
@used
#endif
@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J")
-public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(environment: UnsafeMutablePointer!, thisClass: jclass, selfPointer: jlong) -> jbyteArray? {
+public func Java_org_swift_swiftkit_core_foundation_Data__00024toByteArrayIndirectCopy__J(
+ environment: UnsafeMutablePointer!,
+ thisClass: jclass,
+ selfPointer: jlong
+) -> jbyteArray? {
guard let env$ = environment else {
fatalError("Missing JNIEnv in downcall to \(#function)")
}
diff --git a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
index 157abe53e..b7e2b6ab5 100644
--- a/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
+++ b/Sources/SwiftRuntimeFunctions/foundation/Data+FFM.swift
@@ -24,7 +24,7 @@ import Foundation
@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_Data")
public func swiftjava_getType_SwiftRuntimeFunctions_Data() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
+ unsafeBitCast(Data.self, to: UnsafeMutableRawPointer.self)
}
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count")
@@ -39,13 +39,13 @@ public func swiftjava_SwiftRuntimeFunctions_Data_init__(_ bytes_pointer: UnsafeR
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_count$get")
public func swiftjava_SwiftRuntimeFunctions_Data_count$get(_ self: UnsafeRawPointer) -> Int {
- return self.assumingMemoryBound(to: Data.self).pointee.count
+ self.assumingMemoryBound(to: Data.self).pointee.count
}
@_cdecl("swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__")
public func swiftjava_SwiftRuntimeFunctions_Data_withUnsafeBytes__(_ body: @convention(c) (UnsafeRawPointer?, Int) -> Void, _ self: UnsafeRawPointer) {
self.assumingMemoryBound(to: Data.self).pointee.withUnsafeBytes({ (_0) in
- return body(_0.baseAddress, _0.count)
+ body(_0.baseAddress, _0.count)
})
}
@@ -66,5 +66,5 @@ public func swiftjava_SwiftRuntimeFunctions_Data_copyBytes__(
@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
- return unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
+ unsafeBitCast((any DataProtocol).self, to: UnsafeMutableRawPointer.self)
}
diff --git a/Tests/JExtractSwiftTests/DateTests.swift b/Tests/JExtractSwiftTests/DateTests.swift
index 13a1e59f1..7e694640c 100644
--- a/Tests/JExtractSwiftTests/DateTests.swift
+++ b/Tests/JExtractSwiftTests/DateTests.swift
@@ -32,11 +32,11 @@ struct DateTests {
.java,
detectChunkByInitialLines: 1,
expectedChunks: [
- """
- public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
- SwiftModule.$acceptDate(date.$memoryAddress());
- }
- """
+ """
+ public static void acceptDate(org.swift.swiftkit.core.foundation.Date date) {
+ SwiftModule.$acceptDate(date.$memoryAddress());
+ }
+ """
]
)
@@ -46,10 +46,10 @@ struct DateTests {
.swift,
detectChunkByInitialLines: 1,
expectedChunks: [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
- public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
- """
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024acceptDate__J")
+ public func Java_com_example_swift_SwiftModule__00024acceptDate__J(environment: UnsafeMutablePointer!, thisClass: jclass, date: jlong) {
+ """
]
)
}
@@ -67,9 +67,9 @@ struct DateTests {
.jni,
.java,
expectedChunks: [
- """
- public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
- """
+ """
+ public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
+ """
],
)
@@ -78,10 +78,10 @@ struct DateTests {
.jni,
.swift,
expectedChunks: [
- """
- @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
- public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
- """
+ """
+ @_cdecl("Java_com_example_swift_SwiftModule__00024returnDate__")
+ public func Java_com_example_swift_SwiftModule__00024returnDate__(environment: UnsafeMutablePointer!, thisClass: jclass) -> jlong {
+ """
]
)
}
From f377d1c2d69a276c7acb904a34b056c21b26141c Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:20:03 +0900
Subject: [PATCH 10/11] simple collapling
---
...FFMSwift2JavaGenerator+JavaBindingsPrinting.swift | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index 48cf4c331..1385894d3 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -621,14 +621,10 @@ extension FFMSwift2JavaGenerator {
func renderMemoryLayoutValue(for javaType: JavaType) -> String {
if let layout = ForeignValueLayout(javaType: javaType) {
return layout.description
- } else if case .class(let package, name: let customClass, _) = javaType {
- let type =
- if let package {
- "\(package).\(customClass)"
- } else {
- customClass
- }
- return ForeignValueLayout(customType: type).description
+ } else if case .class(.some(let package), name: let customClass, _) = javaType {
+ return ForeignValueLayout(customType: "\(package).\(customClass)").description
+ } else if case .class(.none, name: let customClass, _) = javaType {
+ return ForeignValueLayout(customType: customClass).description
} else {
fatalError("renderMemoryLayoutValue not supported for \(javaType)")
}
From ab3e202e116c099080d7539b72a16e0e1a114e72 Mon Sep 17 00:00:00 2001
From: Iceman
Date: Wed, 8 Apr 2026 11:43:33 +0900
Subject: [PATCH 11/11] Add JavaType.optional utility function
---
.../FFMSwift2JavaGenerator+JavaTranslation.swift | 14 +++-----------
.../JNISwift2JavaGenerator+JavaTranslation.swift | 8 ++++----
.../JExtractSwiftLib/JavaTypes/JavaType+JDK.swift | 5 +++++
Tests/JExtractSwiftTests/DataImportTests.swift | 2 +-
Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift | 6 +++---
.../JNI/JNIGenericCombinationTests.swift | 4 ++--
.../JExtractSwiftTests/JNI/JNIOptionalTests.swift | 2 +-
Tests/JExtractSwiftTests/OptionalImportTests.swift | 2 +-
8 files changed, 20 insertions(+), 23 deletions(-)
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
index d4387c234..e4363b7a4 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift
@@ -648,11 +648,7 @@ extension FFMSwift2JavaGenerator {
javaParameters: [
JavaParameter(
name: parameterName,
- type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationData]
- )
+ type: .optional(.swiftkitFFMFoundationData)
)
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
@@ -662,11 +658,7 @@ extension FFMSwift2JavaGenerator {
javaParameters: [
JavaParameter(
name: parameterName,
- type: .class(
- package: nil,
- name: "Optional",
- typeParameters: [.swiftkitFFMFoundationDataProtocol]
- )
+ type: .optional(.swiftkitFFMFoundationDataProtocol)
)
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
@@ -679,7 +671,7 @@ extension FFMSwift2JavaGenerator {
let translatedTy = try self.translate(swiftType: swiftType)
return TranslatedParameter(
javaParameters: [
- JavaParameter(name: parameterName, type: .class(package: nil, name: "Optional", typeParameters: [translatedTy]))
+ JavaParameter(name: parameterName, type: .optional(translatedTy))
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
index 733cbac43..f5ce801cc 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift
@@ -176,7 +176,7 @@ extension JNISwift2JavaGenerator {
),
parameters: [],
resultType: TranslatedResult(
- javaType: .class(package: nil, name: "Optional", typeParameters: [.class(package: nil, name: caseName)]),
+ javaType: .optional(.class(package: nil, name: caseName)),
outParameters: conversions.flatMap(\.translated.outParameters),
conversion: enumCase.parameters.isEmpty
? constructRecordConversion
@@ -886,7 +886,7 @@ extension JNISwift2JavaGenerator {
return TranslatedParameter(
parameter: JavaParameter(
name: parameterName,
- type: .class(package: nil, name: "Optional", typeParameters: [javaType]),
+ type: .optional(javaType),
annotations: parameterAnnotations,
),
conversion: .method(
@@ -1077,7 +1077,7 @@ extension JNISwift2JavaGenerator {
genericParameters: genericParameters,
genericRequirements: genericRequirements,
)
- return .class(package: "java.util", name: "Optional", typeParameters: [wrappedType])
+ return .optional(wrappedType)
case .array:
guard let elementType = nominalType.genericArguments?.first else {
@@ -1361,7 +1361,7 @@ extension JNISwift2JavaGenerator {
.void
}
- let returnType = JavaType.class(package: nil, name: "Optional", typeParameters: [javaType])
+ let returnType = JavaType.optional(javaType)
return TranslatedResult(
javaType: returnType,
annotations: parameterAnnotations,
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 6790c5af9..246f8a8b1 100644
--- a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
+++ b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
@@ -45,6 +45,11 @@ extension JavaType {
.class(package: "java.lang", name: "Object")
}
+ /// The description of the type java.util.Optional..
+ static func optional(_ T: JavaType) -> JavaType {
+ .class(package: "java.util", name: "Optional", typeParameters: [T])
+ }
+
/// The description of the type java.util.concurrent.CompletableFuture
static func completableFuture(_ T: JavaType) -> JavaType {
.class(package: "java.util.concurrent", name: "CompletableFuture", typeParameters: [T.boxedType])
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index c2ce81ca5..42149c5ee 100644
--- a/Tests/JExtractSwiftTests/DataImportTests.swift
+++ b/Tests/JExtractSwiftTests/DataImportTests.swift
@@ -267,7 +267,7 @@ final class DataImportTests {
* public func receiveDataProtocol(dat: some DataProtocol, dat2: T?)
* }
*/
- public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, Optional dat2) {
+ public static void receiveDataProtocol(org.swift.swiftkit.ffm.foundation.Data dat, java.util.Optional dat2) {
swiftjava_SwiftModule_receiveDataProtocol_dat_dat2.call(dat.$memorySegment(), SwiftRuntime.toOptionalSegmentInstance(dat2));
}
""",
diff --git a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
index e09c215ca..0f3db0ca0 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIEnumTests.swift
@@ -268,7 +268,7 @@ struct JNIEnumTests {
detectChunkByInitialLines: 1,
expectedChunks: [
"""
- public Optional getAsFirst() {
+ public java.util.Optional getAsFirst() {
if (getDiscriminator() != Discriminator.FIRST) {
return Optional.empty();
}
@@ -276,7 +276,7 @@ struct JNIEnumTests {
}
""",
"""
- public Optional getAsSecond() {
+ public java.util.Optional getAsSecond() {
if (getDiscriminator() != Discriminator.SECOND) {
return Optional.empty();
}
@@ -285,7 +285,7 @@ struct JNIEnumTests {
}
""",
"""
- public Optional getAsThird() {
+ public java.util.Optional getAsThird() {
if (getDiscriminator() != Discriminator.THIRD) {
return Optional.empty();
}
diff --git a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
index 57651e1e1..45b4cb2ec 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIGenericCombinationTests.swift
@@ -55,7 +55,7 @@ struct JNIGenericCombinationTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static Optional> makeStringIDOptional(java.lang.String value, SwiftArena swiftArena) {
+ public static java.util.Optional> makeStringIDOptional(java.lang.String value, SwiftArena swiftArena) {
byte[] result$_discriminator$ = new byte[1];
org.swift.swiftkit.core._OutSwiftGenericInstance resultWrapped$ = new org.swift.swiftkit.core._OutSwiftGenericInstance();
SwiftModule.$makeStringIDOptional(value, result$_discriminator$, resultWrapped$);
@@ -113,7 +113,7 @@ struct JNIGenericCombinationTests {
detectChunkByInitialLines: 2,
expectedChunks: [
"""
- public static void takeStringIDOptional(Optional> value) {
+ public static void takeStringIDOptional(java.util.Optional> value) {
SwiftModule.$takeStringIDOptional(value.map(MyID::$memoryAddress).orElse(0L));
}
""",
diff --git a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
index 728165bf8..d01c4b103 100644
--- a/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
+++ b/Tests/JExtractSwiftTests/JNI/JNIOptionalTests.swift
@@ -155,7 +155,7 @@ struct JNIOptionalTests {
* public func optionalClass(_ arg: MyClass?) -> MyClass?
* }
*/
- public static Optional optionalClass(Optional arg, SwiftArena swiftArena) {
+ public static java.util.Optional optionalClass(java.util.Optional arg, SwiftArena swiftArena) {
byte[] result$_discriminator$ = new byte[1];
long result$ = SwiftModule.$optionalClass(arg.map(MyClass::$memoryAddress).orElse(0L), result$_discriminator$);
return (result$_discriminator$[0] == 1) ? Optional.of(MyClass.wrapMemoryAddressUnsafe(result$, swiftArena)) : Optional.empty();
diff --git a/Tests/JExtractSwiftTests/OptionalImportTests.swift b/Tests/JExtractSwiftTests/OptionalImportTests.swift
index ea20272e3..60473bd3a 100644
--- a/Tests/JExtractSwiftTests/OptionalImportTests.swift
+++ b/Tests/JExtractSwiftTests/OptionalImportTests.swift
@@ -146,7 +146,7 @@ final class OptionalImportTests {
* public func receiveOptionalDataProto(_ arg: (some DataProtocol)?)
* }
*/
- public static void receiveOptionalDataProto(Optional arg) {
+ public static void receiveOptionalDataProto(java.util.Optional arg) {
swiftjava_SwiftModule_receiveOptionalDataProto__.call(SwiftRuntime.toOptionalSegmentInstance(arg));
}
""",