Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -485,18 +485,30 @@ extension JNISwift2JavaGenerator {
throw JavaTranslationError.unsupportedSwiftType(swiftType)
}

let indirectStepType = JNIJavaTypeTranslator.indirectConversionStepSwiftType(
for: knownType,
from: knownTypes
)
let indirectCheck = JNIJavaTypeTranslator.checkStep(for: knownType, from: knownTypes)
let valueConversion: NativeSwiftConversionStep =
if indirectStepType != nil {
.labelessAssignmentOfVariable(.constant(parameterName), swiftType: swiftType)
} else {
.initFromJNI(.placeholder, swiftType: swiftType)
}

return NativeParameter(
parameters: [
JavaParameter(name: discriminatorName, type: .byte),
JavaParameter(name: valueName, type: javaType),
],
conversion: .optionalLowering(
.initFromJNI(.placeholder, swiftType: swiftType),
valueConversion,
discriminatorName: discriminatorName,
valueName: valueName
),
indirectConversion: nil,
conversionCheck: nil
indirectConversion: indirectStepType.flatMap { .initFromJNI(.constant(valueName), swiftType: $0) },
conversionCheck: indirectCheck
)
}
}
Expand Down Expand Up @@ -568,11 +580,20 @@ extension JNISwift2JavaGenerator {
)
} else {
// Use indirect byte array to store discriminator
let valueConversion: NativeSwiftConversionStep =
if let indirectReturnType = JNIJavaTypeTranslator.indirectConversionStepSwiftType(
for: knownType,
from: knownTypes
) {
.getJNIValue(.labelessInitializer(.placeholder, swiftType: indirectReturnType))
} else {
.getJNIValue(.placeholder)
}

return NativeResult(
javaType: javaType,
conversion: .optionalRaisingIndirectReturn(
.getJNIValue(.placeholder),
valueConversion,
resultName: "\(resultName)$",
returnType: javaType,
discriminatorParameterName: discriminatorName
Expand Down
108 changes: 108 additions & 0 deletions Tests/JExtractSwiftTests/JNI/JNIIntConversionChecksTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ struct JNIIntConversionChecksTests {
}
}
"""
private let optionalSignedSource = """
public struct MyStruct {
public var optionalInt: Int? = nil

public init(optionalInt: Int?) {
self.optionalInt = optionalInt
}
}
"""
private let optionalUnsignedSource = """
public struct MyStruct {
public var optionalUInt: UInt? = nil

public init(optionalUInt: UInt?) {
self.optionalUInt = optionalUInt
}
}
"""
private let signedFuncSource = """
public struct MyStruct {
public func dummyFunc(arg: Int) -> Int {
Expand Down Expand Up @@ -109,6 +127,96 @@ struct JNIIntConversionChecksTests {
)
}

@Test func generatesOptionalInitWithSignedCheck() throws {
try assertOutput(
input: optionalSignedSource,
.jni,
.swift,
expectedChunks: [
"""
@_cdecl("Java_com_example_swift_MyStruct__00024init__BJ")
public func Java_com_example_swift_MyStruct__00024init__BJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, optionalInt_discriminator: jbyte, optionalInt_value: jlong) -> jlong {
let optionalInt$indirect = Int64(fromJNI: optionalInt_value, in: environment)
#if _pointerBitWidth(_32)
guard optionalInt$indirect >= Int32.min && optionalInt$indirect <= Int32.max else {
environment.throwJavaException(javaException: .integerOverflow)
return 0
""",
"""
#endif
let result$ = UnsafeMutablePointer<MyStruct>.allocate(capacity: 1)
result$.initialize(to: MyStruct.init(optionalInt: optionalInt_discriminator == 1 ? Int(optionalInt$indirect) : nil))
let resultBits$ = Int64(Int(bitPattern: result$))
return resultBits$.getJNILocalRefValue(in: environment)
""",
]
)
}

@Test func generatesOptionalInitWithUnsignedCheck() throws {
try assertOutput(
input: optionalUnsignedSource,
.jni,
.swift,
expectedChunks: [
"""
@_cdecl("Java_com_example_swift_MyStruct__00024init__BJ")
public func Java_com_example_swift_MyStruct__00024init__BJ(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, optionalUInt_discriminator: jbyte, optionalUInt_value: jlong) -> jlong {
let optionalUInt$indirect = UInt64(fromJNI: optionalUInt_value, in: environment)
#if _pointerBitWidth(_32)
guard optionalUInt$indirect >= UInt32.min && optionalUInt$indirect <= UInt32.max else {
environment.throwJavaException(javaException: .integerOverflow)
return 0
""",
"""
#endif
let result$ = UnsafeMutablePointer<MyStruct>.allocate(capacity: 1)
result$.initialize(to: MyStruct.init(optionalUInt: optionalUInt_discriminator == 1 ? UInt(optionalUInt$indirect) : nil))
let resultBits$ = Int64(Int(bitPattern: result$))
return resultBits$.getJNILocalRefValue(in: environment)
""",
]
)
}

@Test func generatesOptionalSignedGetterWithoutCheck() throws {
try assertOutput(
input: optionalSignedSource,
.jni,
.swift,
expectedChunks: [
"""
@_cdecl("Java_com_example_swift_MyStruct__00024getOptionalInt__J_3B")
public func Java_com_example_swift_MyStruct__00024getOptionalInt__J_3B(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, result_discriminator$: jbyteArray?) -> jlong {
""",
"""
let result$: jlong
if let innerResult$ = selfPointer$.pointee.optionalInt {
result$ = Int64(innerResult$).getJNIValue(in: environment)
""",
]
)
}

@Test func generatesOptionalUnsignedGetterWithoutCheck() throws {
try assertOutput(
input: optionalUnsignedSource,
.jni,
.swift,
expectedChunks: [
"""
@_cdecl("Java_com_example_swift_MyStruct__00024getOptionalUInt__J_3B")
public func Java_com_example_swift_MyStruct__00024getOptionalUInt__J_3B(environment: UnsafeMutablePointer<JNIEnv?>!, thisClass: jclass, selfPointer: jlong, result_discriminator$: jbyteArray?) -> jlong {
""",
"""
let result$: jlong
if let innerResult$ = selfPointer$.pointee.optionalUInt {
result$ = UInt64(innerResult$).getJNIValue(in: environment)
""",
]
)
}

@Test func generatesUnsignedSetterWithCheck() throws {
try assertOutput(
input: unsignedSource,
Expand Down
Loading