@@ -254,11 +254,11 @@ extension JNISwift2JavaGenerator {
254254
255255 let ( translatedClass, orElseValue) = switch javaType {
256256 case . boolean: ( " Optional<Boolean> " , " false " )
257- case . byte: ( " Optional<Byte> " , " 0 " )
258- case . char: ( " Optional<Character> " , " 0 " )
259- case . short: ( " Optional<Short> " , " 0 " )
257+ case . byte: ( " Optional<Byte> " , " (byte) 0" )
258+ case . char: ( " Optional<Character> " , " (char) 0" )
259+ case . short: ( " Optional<Short> " , " (short) 0" )
260260 case . int: ( " OptionalInt " , " 0 " )
261- case . long: ( " OptionalLong " , " 0 " )
261+ case . long: ( " OptionalLong " , " 0L " )
262262 case . float: ( " Optional<Float> " , " 0 " )
263263 case . double: ( " OptionalDouble " , " 0 " )
264264 case . javaLangString: ( " Optional<String> " , #""""# )
@@ -302,17 +302,28 @@ extension JNISwift2JavaGenerator {
302302 func translate(
303303 swiftResult: SwiftResult
304304 ) throws -> TranslatedResult {
305- switch swiftResult. type {
305+ let swiftType = swiftResult. type
306+
307+ switch swiftType {
306308 case . nominal( let nominalType) :
307309 if let knownType = nominalType. nominalTypeDecl. knownTypeKind {
308- guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
309- throw JavaTranslationError . unsupportedSwiftType ( swiftResult. type)
310- }
310+ switch knownType {
311+ case . optional:
312+ guard let genericArgs = nominalType. genericArguments, genericArgs. count == 1 else {
313+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
314+ }
315+ return try translateOptionalResult ( wrappedType: genericArgs [ 0 ] )
311316
312- return TranslatedResult (
313- javaType: javaType,
314- conversion: . placeholder
315- )
317+ default :
318+ guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
319+ throw JavaTranslationError . unsupportedSwiftType ( swiftResult. type)
320+ }
321+
322+ return TranslatedResult (
323+ javaType: javaType,
324+ conversion: . placeholder
325+ )
326+ }
316327 }
317328
318329 if nominalType. isJavaKitWrapper {
@@ -329,10 +340,70 @@ extension JNISwift2JavaGenerator {
329340 case . tuple( [ ] ) :
330341 return TranslatedResult ( javaType: . void, conversion: . placeholder)
331342
332- case . metatype, . optional, . tuple, . function, . existential, . opaque:
343+ case . optional( let wrapped) :
344+ return try translateOptionalResult ( wrappedType: wrapped)
345+
346+ case . metatype, . tuple, . function, . existential, . opaque:
333347 throw JavaTranslationError . unsupportedSwiftType ( swiftResult. type)
334348 }
335349 }
350+
351+ func translateOptionalResult(
352+ wrappedType swiftType: SwiftType
353+ ) throws -> TranslatedResult {
354+ switch swiftType {
355+ case . nominal( let nominalType) :
356+ let nominalTypeName = nominalType. nominalTypeDecl. name
357+
358+ if let knownType = nominalType. nominalTypeDecl. knownTypeKind {
359+ guard let javaType = JNISwift2JavaGenerator . translate ( knownType: knownType) else {
360+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
361+ }
362+
363+ let ( returnType, staticCallee) = switch javaType {
364+ case . boolean: ( " Optional<Boolean> " , " Optional " )
365+ case . byte: ( " Optional<Byte> " , " Optional " )
366+ case . char: ( " Optional<Character> " , " Optional " )
367+ case . short: ( " Optional<Short> " , " Optional " )
368+ case . int: ( " OptionalInt " , " OptionalInt " )
369+ case . long: ( " OptionalLong " , " OptionalLong " )
370+ case . float: ( " Optional<Float> " , " Optional " )
371+ case . double: ( " OptionalDouble " , " OptionalDouble " )
372+ case . javaLangString: ( " Optional<String> " , " Optional " )
373+ default :
374+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
375+ }
376+
377+ // Check if we can fit the value and a discriminator byte in a primitive.
378+ // so the return JNI value will be (value || discriminator)
379+ if let nextIntergralTypeWithSpaceForByte = javaType. nextIntergralTypeWithSpaceForByte {
380+ return TranslatedResult (
381+ javaType: . class( package : nil , name: returnType) ,
382+ conversion: . combinedValueToOptional(
383+ . placeholder,
384+ nextIntergralTypeWithSpaceForByte. java,
385+ valueType: javaType,
386+ valueSizeInBytes: nextIntergralTypeWithSpaceForByte. valueBytes,
387+ optionalType: staticCallee
388+ )
389+ )
390+ } else {
391+ // Otherwise, we are forced to use an array.
392+ fatalError ( )
393+ }
394+ }
395+
396+ guard !nominalType. isJavaKitWrapper else {
397+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
398+ }
399+
400+ // Assume JExtract imported class
401+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
402+
403+ default :
404+ throw JavaTranslationError . unsupportedSwiftType ( swiftType)
405+ }
406+ }
336407 }
337408
338409 struct TranslatedFunctionDecl {
@@ -433,6 +504,8 @@ extension JNISwift2JavaGenerator {
433504
434505 case isOptionalPresent
435506
507+ indirect case combinedValueToOptional( JavaNativeConversionStep , JavaType , valueType: JavaType , valueSizeInBytes: Int , optionalType: String )
508+
436509 /// Returns the conversion string applied to the placeholder.
437510 func render( _ printer: inout CodePrinter , _ placeholder: String ) -> String {
438511 // NOTE: 'printer' is used if the conversion wants to cause side-effects.
@@ -466,6 +539,22 @@ extension JNISwift2JavaGenerator {
466539 let argsStr = args. joined ( separator: " , " )
467540 return " \( inner) . \( methodName) ( \( argsStr) ) "
468541
542+ case . combinedValueToOptional( let combined, let combinedType, let valueType, let valueSizeInBytes, let optionalType) :
543+ let combined = combined. render ( & printer, placeholder)
544+ printer. print (
545+ """
546+ \( combinedType) combined$ = \( combined) ;
547+ byte discriminator$ = (byte) (combined$ & 0xFF);
548+ """
549+ )
550+
551+ if valueType == . boolean {
552+ printer. print ( " boolean value$ = ((byte) (combined$ >> 8)) != 0; " )
553+ } else {
554+ printer. print ( " \( valueType) value$ = ( \( valueType) ) (combined$ >> \( valueSizeInBytes * 8 ) ); " )
555+ }
556+
557+ return " discriminator$ == 1 ? \( optionalType) .of(value$) : \( optionalType) .empty() "
469558 }
470559 }
471560
@@ -486,6 +575,9 @@ extension JNISwift2JavaGenerator {
486575
487576 case . method( let inner, _, _) :
488577 return inner. requiresSwiftArena
578+
579+ case . combinedValueToOptional( let inner, _, _, _, _) :
580+ return inner. requiresSwiftArena
489581 }
490582 }
491583 }
0 commit comments