diff --git a/.licenseignore b/.licenseignore
index a49ab625d..b8009e6df 100644
--- a/.licenseignore
+++ b/.licenseignore
@@ -52,3 +52,7 @@ Samples/JavaDependencySampleApp/gradle
Sources/_Subprocess/**
Sources/_SubprocessCShims/**
Samples/gradle
+Sources/SwiftJavaRuntimeSupport/Foundation/*
+Sources/SwiftRuntimeFunctions/Foundation/*
+SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/*
+SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/*
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..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
@@ -14,10 +14,10 @@
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;
+import org.swift.swiftkit.ffm.foundation.Data;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
@@ -79,7 +79,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/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/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/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;
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..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,6 +16,7 @@
import org.junit.jupiter.api.Test;
import org.swift.swiftkit.core.SwiftArena;
+import org.swift.swiftkit.core.foundation.Data;
import static org.junit.jupiter.api.Assertions.*;
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/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/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift
index cb7eac727..1385894d3 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,7 +621,9 @@ 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 {
+ } 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)")
@@ -776,7 +780,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 e3a61dc75..6fe7ccb6e 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,26 @@ 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: .optional(.swiftkitFFMFoundationData)
+ )
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
+ case .foundationDataProtocol, .essentialsDataProtocol:
+ return TranslatedParameter(
+ javaParameters: [
+ JavaParameter(
+ name: parameterName,
+ type: .optional(.swiftkitFFMFoundationDataProtocol)
+ )
+ ],
+ conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
+ )
default:
throw JavaTranslationError.unhandledType(known: .optional(swiftType))
}
@@ -647,7 +671,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: .optional(translatedTy))
],
conversion: .call(.placeholder, function: "SwiftRuntime.toOptionalSegmentInstance", withArena: false)
)
@@ -750,7 +774,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+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
index fe7372759..99b2640f3 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -71,6 +71,7 @@ extension FFMSwift2JavaGenerator {
// === All types
// We have to write all types to their corresponding output file that matches the file they were declared in,
// because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input.
+
let filteredTypes: [String: ImportedNominalType]
if let singleType = config.singleType {
filteredTypes = self.analysis.importedTypes.filter { $0.key == singleType }
@@ -92,14 +93,13 @@ extension FFMSwift2JavaGenerator {
let filename = "\(inputFileName)".replacing(".swift", with: "+SwiftJava.swift")
// Print file header before all type thunks
- printer.print(
- """
- // Generated by swift-java
-
- import SwiftRuntimeFunctions
+ printer.print("// Generated by swift-java")
+ printer.println()
+ if !group.value.allSatisfy({ $0.value.swiftNominal.moduleName == "SwiftRuntimeFunctions" }) {
+ printer.print("import SwiftRuntimeFunctions")
+ }
+ printer.println()
- """
- )
self.lookupContext.symbolTable.printImportedModules(&printer)
for ty in importedTypesForThisFile {
@@ -263,16 +263,15 @@ struct SwiftThunkTranslator {
/// Render special thunks for known types like Foundation.Data
func renderSpecificTypeThunks(_ nominal: ImportedNominalType) -> [DeclSyntax] {
- guard let knownType = nominal.swiftNominal.knownTypeKind else {
- return []
- }
-
- switch knownType {
- case .foundationData, .essentialsData:
- return renderFoundationDataThunks(nominal)
- default:
- return []
+ if nominal.swiftNominal.moduleName == "SwiftRuntimeFunctions" {
+ switch nominal.swiftNominal.qualifiedName {
+ case "Data":
+ return renderFoundationDataThunks(nominal)
+ default:
+ break
+ }
}
+ return []
}
/// Render Swift thunks for Foundation.Data helper methods
diff --git a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
index 41c063048..65a3d9d65 100644
--- a/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
+++ b/Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator.swift
@@ -448,7 +448,7 @@ extension FFMSwift2JavaGenerator {
printer.print(
"""
- static MemorySegment findOrThrow(String symbol) {
+ public static MemorySegment findOrThrow(String symbol) {
return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol)));
}
@@ -557,15 +557,13 @@ 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
+ if decl.swiftNominal.moduleName == "SwiftRuntimeFunctions" {
+ switch decl.swiftNominal.qualifiedName {
+ case "Data":
+ printFoundationDataHelpers(&printer, decl)
+ default:
+ break
+ }
}
}
diff --git a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
index e6b3c71b8..ffee615f7 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift
@@ -42,13 +42,21 @@ extension JNISwift2JavaGenerator {
}
package func writeExportedJavaSources(_ printer: inout CodePrinter) throws {
- let importedTypes = analysis.importedTypes.sorted(by: { (lhs, rhs) in lhs.key < rhs.key })
+ let typesToExport: [(key: String, value: ImportedNominalType)]
+ if let singleType = config.singleType {
+ typesToExport = analysis.importedTypes
+ .filter { $0.key == singleType }
+ .sorted(by: { $0.key < $1.key })
+ } else {
+ typesToExport = analysis.importedTypes
+ .sorted(by: { $0.key < $1.key })
+ }
var exportedFileNames: OrderedSet = []
// Each parent type goes into its own file
// any nested types are printed inside the body as `static class`
- for (_, ty) in importedTypes.filter({ _, type in type.parent == nil }) {
+ for (_, ty) in typesToExport.filter({ _, type in type.parent == nil }) {
let filename = "\(ty.effectiveJavaSimpleName).java"
logger.debug("Printing contents: \(filename)")
printImportedNominal(&printer, ty)
@@ -63,17 +71,20 @@ extension JNISwift2JavaGenerator {
}
}
- let filename = "\(self.swiftModuleName).java"
- logger.trace("Printing module class: \(filename)")
- printModule(&printer)
+ // Skip the module-level .swift file when generating for a single type
+ if config.singleType == nil {
+ let filename = "\(self.swiftModuleName).java"
+ logger.trace("Printing module class: \(filename)")
+ printModule(&printer)
- if let outputFile = try printer.writeContents(
- outputDirectory: javaOutputDirectory,
- javaPackagePath: javaPackagePath,
- filename: filename,
- ) {
- exportedFileNames.append(outputFile.path(percentEncoded: false))
- logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))")
+ if let outputFile = try printer.writeContents(
+ outputDirectory: javaOutputDirectory,
+ javaPackagePath: javaPackagePath,
+ filename: filename,
+ ) {
+ exportedFileNames.append(outputFile.path(percentEncoded: false))
+ logger.info("[swift-java] Generated: \(self.swiftModuleName).java (at \(outputFile))")
+ }
}
// Write java sources list file
@@ -338,17 +349,15 @@ 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
+ if decl.swiftNominal.moduleName == "SwiftJava" {
+ switch decl.swiftNominal.qualifiedName {
+ case "Date":
+ printFoundationDateHelpers(&printer, decl)
+ case "Data":
+ printFoundationDataHelpers(&printer, decl)
+ default:
+ break
+ }
}
}
@@ -616,7 +625,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 f5a2fe320..410887f86 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
@@ -505,10 +505,24 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreFoundationDate),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .foundationData, .essentialsData:
- break // Handled as wrapped struct
+ return TranslatedParameter(
+ parameter: JavaParameter(
+ name: parameterName,
+ type: .concrete(.swiftkitCoreFoundationData),
+ annotations: parameterAnnotations,
+ ),
+ conversion: .valueMemoryAddress(.placeholder),
+ )
case .unsafeRawBufferPointer, .unsafeMutableRawBufferPointer:
return TranslatedParameter(
@@ -872,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(
@@ -945,12 +959,22 @@ extension JNISwift2JavaGenerator {
)
case .foundationDate, .essentialsDate:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreFoundationDate
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationData, .essentialsData:
- // Handled as wrapped struct
- break
+ let javaType = JavaType.swiftkitCoreFoundationData
+ return TranslatedResult(
+ javaType: javaType,
+ annotations: resultAnnotations,
+ outParameters: [],
+ conversion: .wrapMemoryAddressUnsafe(.placeholder, javaType),
+ )
case .foundationUUID, .essentialsUUID:
return TranslatedResult(
@@ -1053,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 {
@@ -1094,13 +1118,13 @@ extension JNISwift2JavaGenerator {
return .swiftSet(elementJavaType)
case .foundationDate, .essentialsDate:
- return .class(package: nil, name: "Date")
+ return .swiftkitCoreFoundationDate
case .foundationData, .essentialsData:
- return .class(package: nil, name: "Data")
+ return .swiftkitCoreFoundationData
case .foundationDataProtocol, .essentialsDataProtocol:
- return .class(package: nil, name: "DataProtocol")
+ return .swiftkitCoreFoundationDataProtocol
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] = []
@@ -1338,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,
@@ -1896,16 +1919,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/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
index 544b1b5ac..fdf1db9f3 100644
--- a/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
+++ b/Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+SwiftThunkPrinting.swift
@@ -57,24 +57,35 @@ extension JNISwift2JavaGenerator {
let moduleFilename = "\(moduleFilenameBase).swift"
do {
- logger.trace("Printing swift module class: \(moduleFilename)")
-
- try printGlobalSwiftThunkSources(&printer)
-
- if let outputFile = try printer.writeContents(
- outputDirectory: self.swiftOutputDirectory,
- javaPackagePath: nil,
- filename: moduleFilename,
- ) {
- logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))")
- self.expectedOutputSwiftFileNames.remove(moduleFilename)
+ // Skip the module-level .swift file when generating for a single type
+ if config.singleType == nil {
+ logger.trace("Printing swift module class: \(moduleFilename)")
+
+ try printGlobalSwiftThunkSources(&printer)
+
+ if let outputFile = try printer.writeContents(
+ outputDirectory: self.swiftOutputDirectory,
+ javaPackagePath: nil,
+ filename: moduleFilename,
+ ) {
+ logger.info("Generated: \(moduleFilenameBase.bold).swift (at \(outputFile.absoluteString))")
+ self.expectedOutputSwiftFileNames.remove(moduleFilename)
+ }
}
// === All types
// We have to write all types to their corresponding output file that matches the file they were declared in,
// because otherwise SwiftPM plugins will not pick up files apropriately -- we expect 1 output +SwiftJava.swift file for every input.
+
+ let filteredTypes: [String: ImportedNominalType]
+ if let singleType = config.singleType {
+ filteredTypes = self.analysis.importedTypes.filter { $0.key == singleType }
+ } else {
+ filteredTypes = self.analysis.importedTypes
+ }
+
for group: (key: String, value: [Dictionary.Element]) in Dictionary(
- grouping: self.analysis.importedTypes,
+ grouping: filteredTypes,
by: { $0.value.sourceFilePath },
) {
logger.warning("Writing types in file group: \(group.key): \(group.value.map(\.key))")
@@ -275,7 +286,7 @@ extension JNISwift2JavaGenerator {
}
private func printGlobalSwiftThunkSources(_ printer: inout CodePrinter) throws {
- printHeader(&printer)
+ printHeader(&printer, nil)
for decl in analysis.importedGlobalFuncs {
printSwiftFunctionThunk(&printer, decl)
@@ -289,7 +300,7 @@ extension JNISwift2JavaGenerator {
}
private func printNominalTypeThunks(_ printer: inout CodePrinter, _ type: ImportedNominalType) throws {
- printHeader(&printer)
+ printHeader(&printer, type)
printJNICache(&printer, type)
printer.println()
@@ -818,17 +829,20 @@ extension JNISwift2JavaGenerator {
}
}
- private func printHeader(_ printer: inout CodePrinter) {
- printer.print(
- """
- // Generated by swift-java
-
- import SwiftJava
- import SwiftJavaJNICore
- import SwiftJavaRuntimeSupport
-
- """
- )
+ private func printHeader(_ printer: inout CodePrinter, _ type: ImportedNominalType?) {
+ var imports = [
+ "SwiftJava",
+ "SwiftJavaJNICore",
+ ]
+ if !(type?.swiftNominal.moduleName == "SwiftJava") {
+ imports.append("SwiftJavaRuntimeSupport")
+ }
+ printer.print("// Generated by swift-java")
+ printer.println()
+ for package in imports {
+ printer.print("import \(package)")
+ }
+ printer.println()
self.lookupContext.symbolTable.printImportedModules(&printer)
}
@@ -858,15 +872,14 @@ 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
+ if type.swiftNominal.moduleName == "SwiftJava" {
+ switch type.swiftNominal.qualifiedName {
+ case "Data":
+ printFoundationDataThunks(&printer, type)
+ printer.println()
+ default:
+ break
+ }
}
}
diff --git a/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift b/Sources/JExtractSwiftLib/JavaTypes/JavaType+JDK.swift
index 34cb7f458..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])
@@ -59,4 +64,23 @@ extension JavaType {
.class(package: "java.util", name: "UUID")
}
+ static var swiftkitCoreFoundationDate: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Date")
+ }
+
+ static var swiftkitCoreFoundationData: JavaType {
+ .class(package: "org.swift.swiftkit.core.foundation", name: "Data")
+ }
+
+ 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/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
index 106247a48..5ac2384d7 100644
--- a/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
+++ b/Sources/JExtractSwiftLib/Swift2JavaTranslator.swift
@@ -127,39 +127,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/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
new file mode 100644
index 000000000..3e8c20d68
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Data+SwiftJava.swift
@@ -0,0 +1,90 @@
+// ==== --------------------------------------------------
+// Thunks for Data
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Data {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024init___3B")
+public func Java_org_swift_swiftkit_core_foundation_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:819
+
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024getCount__J")
+public func Java_org_swift_swiftkit_core_foundation_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:819
+
+#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
+ buffer.getJNIValue(in: environment)
+ }
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+#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)
+} // printCDecl(_:javaMethodName:parentName:parameters:resultType:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Data__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_foundation_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:819
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..ad62ac0a0
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/DataProtocol+SwiftJava.swift
@@ -0,0 +1,16 @@
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_DataProtocol {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
diff --git a/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
new file mode 100644
index 000000000..6a240919a
--- /dev/null
+++ b/Sources/SwiftJavaRuntimeSupport/Foundation/Date+SwiftJava.swift
@@ -0,0 +1,54 @@
+// ==== --------------------------------------------------
+// Thunks for Date
+
+// Generated by swift-java
+
+import SwiftJava
+import SwiftJavaJNICore
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+enum _JNI_Date {
+} // printJNICache(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+SwiftThunkPrinting.swift:177
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024init__D")
+public func Java_org_swift_swiftkit_core_foundation_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:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024getTimeIntervalSince1970__J")
+public func Java_org_swift_swiftkit_core_foundation_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:819
+
+#if compiler(>=6.3)
+@used
+#endif
+@_cdecl("Java_org_swift_swiftkit_core_foundation_Date__00024typeMetadataAddressDowncall__")
+public func Java_org_swift_swiftkit_core_foundation_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:819
diff --git a/Sources/SwiftRuntimeFunctions/Foundation/Data+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/Foundation/Data+SwiftJava.swift
new file mode 100644
index 000000000..2f9970b8a
--- /dev/null
+++ b/Sources/SwiftRuntimeFunctions/Foundation/Data+SwiftJava.swift
@@ -0,0 +1,51 @@
+// Generated by swift-java
+
+
+#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 */ {
+ 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 {
+ 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
+ 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)
+ }
+}
diff --git a/Sources/SwiftRuntimeFunctions/Foundation/DataProtocol+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/Foundation/DataProtocol+SwiftJava.swift
new file mode 100644
index 000000000..30db7ec84
--- /dev/null
+++ b/Sources/SwiftRuntimeFunctions/Foundation/DataProtocol+SwiftJava.swift
@@ -0,0 +1,17 @@
+// Generated by swift-java
+
+
+#if canImport(FoundationEssentials)
+import FoundationEssentials
+#else
+import Foundation
+#endif
+
+
+// ==== --------------------------------------------------
+// Thunks for DataProtocol
+
+@_cdecl("swiftjava_getType_SwiftRuntimeFunctions_DataProtocol")
+public func swiftjava_getType_SwiftRuntimeFunctions_DataProtocol() -> UnsafeMutableRawPointer /* Any.Type */ {
+ unsafeBitCast(DataProtocol.self, to: UnsafeMutableRawPointer.self)
+}
diff --git a/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift b/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
index bdc2d8494..3faaa80b5 100644
--- a/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
+++ b/Sources/SwiftRuntimeFunctions/generated/SwiftJavaError+SwiftJava.swift
@@ -1,6 +1,5 @@
// Generated by swift-java
-import SwiftRuntimeFunctions
// ==== --------------------------------------------------
// Thunks for SwiftJavaError
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
new file mode 100644
index 000000000..bd9afe7cb
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Data.java
@@ -0,0 +1,176 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+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.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:241
+
+ /**
+ * 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:693
+ 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:693
+ 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:785
+
+ 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:799
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:411
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
new file mode 100644
index 000000000..1a9f82f73
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/DataProtocol.java
@@ -0,0 +1,14 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+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.concurrent.atomic.AtomicBoolean;
+import org.swift.swiftkit.core.annotations.*;
+
+public interface DataProtocol extends JNISwiftInstance {
+} // printProtocol(_:_:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:165
diff --git a/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
new file mode 100644
index 000000000..59368c852
--- /dev/null
+++ b/SwiftKitCore/src/main/java/org/swift/swiftkit/core/foundation/Date.java
@@ -0,0 +1,173 @@
+// Generated by jextract-swift
+// Swift module: SwiftJava
+
+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.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:241
+
+ /**
+ * 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:693
+ 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:693
+ 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:785
+
+ 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:799
+} // printNominal(_:_:body:) @ JExtractSwiftLib/JNISwift2JavaGenerator+JavaBindingsPrinting.swift:411
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..04a9603e5
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/Data.java
@@ -0,0 +1,387 @@
+// Generated by jextract-swift
+// Swift module: SwiftRuntimeFunctions
+
+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.*;
+import java.nio.charset.StandardCharsets;
+
+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 final SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public final 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 =
+ SwiftRuntimeFunctions.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$);
+ }
+ }
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
+ /**
+ * 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);
+ } // printDowncall(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:506
+ } // printDowncall(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:498
+ swiftjava_SwiftRuntimeFunctions_Data_init_bytes_count.call(bytes, count, result$);
+ return Data.wrapMemoryAddressUnsafe(result$, swiftArena);
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
+ // ==== --------------------------------------------------
+ // 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 =
+ SwiftRuntimeFunctions.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$);
+ }
+ }
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
+ /**
+ * 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);
+ }
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
+ // ==== --------------------------------------------------
+ // 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 =
+ SwiftRuntimeFunctions.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$);
+ }
+ }
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
+ /**
+ * 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);
+ } // printReturnWithOverflowCheck(_:value:overflowCheck:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:603
+ } // printReturnWithOverflowCheck(_:value:overflowCheck:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:602
+ return result$checked;
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
+ // ==== --------------------------------------------------
+ // 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 =
+ SwiftRuntimeFunctions.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);
+ }
+ } // printFunctionPointerParameterDescriptorClass(_:_:_:impl:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:223
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
+ 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);
+ } // printJavaBindingWrapperFunctionTypeHelper(_:_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:327
+ } // printJavaBindingWrapperHelperClass(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:280
+ /**
+ * 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());
+ }
+ } // printJavaBindingWrapperMethod(_:_:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:403
+
+ // ==== --------------------------------------------------
+ // 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 =
+ SwiftRuntimeFunctions.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$);
+ }
+ }
+ } // printJavaBindingDescriptorClass(_:_:symbolLookup:additionalContent:) @ JExtractSwiftLib/FFMSwift2JavaGenerator+JavaBindingsPrinting.swift:65
+ /**
+ * 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 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();
+ }
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
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..8d16ef379
--- /dev/null
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/foundation/DataProtocol.java
@@ -0,0 +1,64 @@
+// Generated by jextract-swift
+// Swift module: SwiftRuntimeFunctions
+
+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.*;
+import java.nio.charset.StandardCharsets;
+
+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 final SwiftAnyType $swiftType() {
+ return TYPE_METADATA;
+ }
+
+ public static final GroupLayout $LAYOUT = (GroupLayout) SwiftValueWitnessTable.layoutOfSwiftType(TYPE_METADATA.$memorySegment());
+ public final 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();
+ }
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
index ce276caa7..aff2eccee 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftJavaErrorException.java
@@ -127,4 +127,4 @@ private static String fetchDescription(MemorySegment errorPointer) {
return "Swift error (address: 0x" + Long.toHexString(errorPointer.address()) + ")";
}
}
-} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:385
+} // printNominal(_:_:body:) @ JExtractSwiftLib/FFMSwift2JavaGenerator.swift:395
diff --git a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
index ec27f2a29..ff7765dfb 100644
--- a/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
+++ b/SwiftKitFFM/src/main/java/org/swift/swiftkit/ffm/generated/SwiftRuntimeFunctions.java
@@ -17,14 +17,14 @@ public final class SwiftRuntimeFunctions {
private SwiftRuntimeFunctions() {
// Should not be called directly
}
-
+
// Static enum to force initialization
private static enum Initializer {
FORCE; // Refer to this to force outer Class initialization (and static{} blocks to trigger)
}
static final String LIB_NAME = "SwiftRuntimeFunctions";
static final Arena LIBRARY_ARENA = Arena.ofAuto();
- static MemorySegment findOrThrow(String symbol) {
+ public static MemorySegment findOrThrow(String symbol) {
return SYMBOL_LOOKUP.find(symbol)
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: %s".formatted(symbol)));
}
@@ -49,7 +49,7 @@ private static SymbolLookup getSymbolLookup() {
SwiftLibraries.loadLibraryWithFallbacks(SwiftLibraries.LIB_NAME_SWIFT_RUNTIME_FUNCTIONS);
SwiftLibraries.loadLibraryWithFallbacks(LIB_NAME);
}
-
+
if (PlatformUtils.isMacOS()) {
return SymbolLookup.libraryLookup(System.mapLibraryName(LIB_NAME), LIBRARY_ARENA)
.or(SymbolLookup.loaderLookup())
diff --git a/Tests/JExtractSwiftTests/DataImportTests.swift b/Tests/JExtractSwiftTests/DataImportTests.swift
index e67a3db87..42149c5ee 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, java.util.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..7e694640c 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
+ expectedChunks: [
+ """
+ public static org.swift.swiftkit.core.foundation.Date returnDate(SwiftArena swiftArena) {
+ """
+ ],
)
try assertOutput(
input: text,
- mode,
+ .jni,
.swift,
- expectedChunks: expectedSwiftChunks
- )
- }
-
- @Test(
- "Import: Date type",
- arguments: [
- (
- JExtractGenerationMode.jni,
- /* expected Java chunks */
- [
- """
- public final class Date implements JNISwiftInstance {
- """,
- """
- 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,
- .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/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/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..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));
}
""",
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(",
],
)
}
diff --git a/scripts/swiftkit-ffm-generate-bindings.sh b/scripts/swiftkit-ffm-generate-bindings.sh
index 9f706a77c..43cb277e9 100755
--- a/scripts/swiftkit-ffm-generate-bindings.sh
+++ b/scripts/swiftkit-ffm-generate-bindings.sh
@@ -23,15 +23,18 @@ set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
JAVA_OUTPUT="${REPO_ROOT}/SwiftKitFFM/src/main/java"
-JAVA_PACKAGE="org.swift.swiftkit.ffm.generated"
+PACKAGE_GENERATED="org.swift.swiftkit.ffm.generated"
+PACKAGE_FOUNDATION="org.swift.swiftkit.ffm.foundation"
-# Declare types to generate: SWIFT_MODULE SINGLE_TYPE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+# Declare types to generate: SWIFT_MODULE SINGLE_TYPE JAVA_PACKAGE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
TYPES=(
- "SwiftRuntimeFunctions SwiftJavaError Sources/SwiftRuntimeFunctions Sources/SwiftRuntimeFunctions/generated"
+ "SwiftRuntimeFunctions SwiftJavaError ${PACKAGE_GENERATED} Sources/SwiftRuntimeFunctions Sources/SwiftRuntimeFunctions/generated"
+ "SwiftRuntimeFunctions Data ${PACKAGE_FOUNDATION} Sources/FakeFoundation Sources/SwiftRuntimeFunctions/foundation"
+ "SwiftRuntimeFunctions DataProtocol ${PACKAGE_FOUNDATION} Sources/FakeFoundation Sources/SwiftRuntimeFunctions/foundation"
)
for entry in "${TYPES[@]}"; do
- read -r MODULE SINGLE_TYPE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+ read -r MODULE SINGLE_TYPE JAVA_PACKAGE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
echo "==> Generating ${SINGLE_TYPE} (module: ${MODULE})..."
diff --git a/scripts/swiftkit-jni-generate-bindings.sh b/scripts/swiftkit-jni-generate-bindings.sh
new file mode 100755
index 000000000..285350b64
--- /dev/null
+++ b/scripts/swiftkit-jni-generate-bindings.sh
@@ -0,0 +1,53 @@
+#!/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.foundation"
+
+# Declare types to generate: SWIFT_MODULE SINGLE_TYPE INPUT_SWIFT_DIR OUTPUT_SWIFT_DIR
+TYPES=(
+ "SwiftJava Data Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "SwiftJava DataProtocol Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+ "SwiftJava Date Sources/FakeFoundation Sources/SwiftJavaRuntimeSupport/foundation"
+)
+
+for entry in "${TYPES[@]}"; do
+ read -r MODULE SINGLE_TYPE INPUT_SWIFT OUTPUT_SWIFT <<< "$entry"
+
+ echo "==> Generating ${INPUT_SWIFT} ${SINGLE_TYPE}..."
+
+ xcrun swift run swift-java jextract \
+ --mode jni \
+ --single-type "$SINGLE_TYPE" \
+ --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."