Skip to content

Commit bdc5219

Browse files
committed
Document and cleanup how we import unsigned swift types
1 parent 297a241 commit bdc5219

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

Samples/SwiftKitSampleApp/Sources/MySwiftLibrary/MySwiftClass.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ public class MySwiftClass {
6161
return Int.random(in: 1..<256)
6262
}
6363

64+
public func takeUnsignedShort(arg: UInt16) {
65+
p("\(UInt32.self) = \(arg)")
66+
}
67+
6468
public func takeUnsignedInt(arg: UInt32) {
6569
p("\(UInt32.self) = \(arg)")
6670
}

Sources/JExtractSwiftLib/JavaTypes/JavaType+SwiftKit.swift

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ extension JavaType {
3030
}
3131

3232
case "Int16": self = .short
33-
case "UInt16":
34-
self = switch unsigned {
35-
case .ignoreSign: .short
36-
case .wrapAsUnsignedNumbers: JavaType.swiftkit.primitives.UnsignedShort
37-
}
33+
case "UInt16": self = .char
3834

3935
case "Int32": self = .int
4036
case "UInt32":
@@ -77,14 +73,13 @@ extension JavaType {
7773
enum swiftkit {
7874
enum primitives {
7975
static let package = "org.swift.swiftkit.core.primitives"
80-
static var UnsignedShort: JavaType {
81-
.class(package: primitives.package, name: "UnsignedShort")
82-
}
8376

8477
static var UnsignedByte: JavaType {
8578
.class(package: primitives.package, name: "UnsignedByte")
8679
}
8780

81+
// UnsignedShort is not necessary because UInt16 is directly expressible as Java's unsigned 'char'.
82+
8883
static var UnsignedInteger: JavaType {
8984
.class(package: primitives.package, name: "UnsignedInteger")
9085
}

Sources/JavaTypes/JavaType+SwiftNames.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,26 @@ extension JavaType {
8787

8888
}
8989

90+
/// Determines how type conversion should deal with Swift's unsigned numeric types.
91+
///
92+
/// When `ignoreSign` is used, unsigned Swift types are imported directly as their corresponding bit-width types,
93+
/// which may yield surprising values when an unsigned Swift value is interpreted as a signed Java type:
94+
/// - `UInt8` is imported as `byte`
95+
/// - `UInt16` is imported as `char` (this is always correct, since `char` is unsigned in Java)
96+
/// - `UInt32` is imported as `int`
97+
/// - `UInt64` is imported as `long`
98+
///
99+
/// When `wrapAsUnsignedNumbers` is used, unsigned Swift types are imported as safe "wrapper" types on the Java side.
100+
/// These make the Unsigned nature of the types explicit in Java, however they come at a cost of allocating the wrapper
101+
/// object, and indirection when accessing the underlying numeric value. These are often useful as a signal to watch out
102+
/// when dealing with a specific API, however in high performance use-cases, one may want to choose using the primitive
103+
/// values directly, and interact with them using {@code UnsignedIntegers} SwiftKit helper classes on the Java side.
104+
///
105+
/// The type mappings in this mode are as follows:
106+
/// - `UInt8` is imported as `org.swift.swiftkit.core.primitives.UnsignedByte`
107+
/// - `UInt16` is imported as `char` (this is always correct, since `char` is unsigned in Java)
108+
/// - `UInt32` is imported as `org.swift.swiftkit.core.primitives.UnsignedInteger`
109+
/// - `UInt64` is imported as `org.swift.swiftkit.core.primitives.UnsignedLong`
90110
public enum UnsignedNumericsMode {
91111
case ignoreSign
92112
case wrapAsUnsignedNumbers

0 commit comments

Comments
 (0)