@@ -3,40 +3,171 @@ package io.github.projectmapk.jackson.module.kogera
33import com.fasterxml.jackson.databind.JavaType
44import com.fasterxml.jackson.databind.ser.std.StdDelegatingSerializer
55import com.fasterxml.jackson.databind.type.TypeFactory
6- import com.fasterxml.jackson.databind.util.ClassUtil
76import com.fasterxml.jackson.databind.util.StdConverter
7+ import java.lang.invoke.MethodHandle
8+ import java.lang.invoke.MethodHandles
9+ import java.lang.invoke.MethodType
10+ import java.lang.reflect.Method
11+ import java.lang.reflect.Type
12+ import java.util.UUID
13+
14+ internal sealed class ValueClassBoxConverter <S : Any ?, D : Any > : StdConverter <S , D >() {
15+ abstract val boxedClass: Class <D >
16+ abstract val boxHandle: MethodHandle
17+
18+ protected fun rawBoxHandle (
19+ unboxedClass : Class <* >,
20+ ): MethodHandle = MethodHandles .lookup().findStatic(
21+ boxedClass,
22+ " box-impl" ,
23+ MethodType .methodType(boxedClass, unboxedClass),
24+ )
25+
26+ val delegatingSerializer: StdDelegatingSerializer by lazy { StdDelegatingSerializer (this ) }
27+
28+ companion object {
29+ fun create (
30+ unboxedClass : Class <* >,
31+ valueClass : Class <* >,
32+ ): ValueClassBoxConverter <* , * > = when (unboxedClass) {
33+ INT_CLASS -> IntValueClassBoxConverter (valueClass)
34+ LONG_CLASS -> LongValueClassBoxConverter (valueClass)
35+ STRING_CLASS -> StringValueClassBoxConverter (valueClass)
36+ JAVA_UUID_CLASS -> JavaUuidValueClassBoxConverter (valueClass)
37+ else -> GenericValueClassBoxConverter (unboxedClass, valueClass)
38+ }
39+ }
40+
41+ // If the wrapped type is explicitly specified, it is inherited for the sake of distinction
42+ internal sealed class Specified <S : Any ?, D : Any > : ValueClassBoxConverter <S , D >()
43+ }
44+
45+ // region: Converters for common classes as wrapped values, add as needed.
46+ internal class IntValueClassBoxConverter <D : Any >(
47+ override val boxedClass : Class <D >,
48+ ) : ValueClassBoxConverter.Specified<Int, D>() {
49+ override val boxHandle: MethodHandle = rawBoxHandle(INT_CLASS ).asType(INT_TO_ANY_METHOD_TYPE )
50+
51+ @Suppress(" UNCHECKED_CAST" )
52+ override fun convert (value : Int ): D = boxHandle.invokeExact(value) as D
53+ }
54+
55+ internal class LongValueClassBoxConverter <D : Any >(
56+ override val boxedClass : Class <D >,
57+ ) : ValueClassBoxConverter.Specified<Long, D>() {
58+ override val boxHandle: MethodHandle = rawBoxHandle(LONG_CLASS ).asType(LONG_TO_ANY_METHOD_TYPE )
59+
60+ @Suppress(" UNCHECKED_CAST" )
61+ override fun convert (value : Long ): D = boxHandle.invokeExact(value) as D
62+ }
63+
64+ internal class StringValueClassBoxConverter <D : Any >(
65+ override val boxedClass : Class <D >,
66+ ) : ValueClassBoxConverter.Specified<String?, D>() {
67+ override val boxHandle: MethodHandle = rawBoxHandle(STRING_CLASS ).asType(STRING_TO_ANY_METHOD_TYPE )
68+
69+ @Suppress(" UNCHECKED_CAST" )
70+ override fun convert (value : String? ): D = boxHandle.invokeExact(value) as D
71+ }
72+
73+ internal class JavaUuidValueClassBoxConverter <D : Any >(
74+ override val boxedClass : Class <D >,
75+ ) : ValueClassBoxConverter.Specified<UUID?, D>() {
76+ override val boxHandle: MethodHandle = rawBoxHandle(JAVA_UUID_CLASS ).asType(JAVA_UUID_TO_ANY_METHOD_TYPE )
77+
78+ @Suppress(" UNCHECKED_CAST" )
79+ override fun convert (value : UUID ? ): D = boxHandle.invokeExact(value) as D
80+ }
81+ // endregion
882
983/* *
1084 * A converter that only performs box processing for the value class.
1185 * Note that constructor-impl is not called.
1286 * @param S is nullable because value corresponds to a nullable value class.
1387 * see [io.github.projectmapk.jackson.module.kogera.annotationIntrospector.KotlinFallbackAnnotationIntrospector.findNullSerializer]
1488 */
15- internal class ValueClassBoxConverter <S : Any ?, D : Any >(
89+ internal class GenericValueClassBoxConverter <S : Any ?, D : Any >(
1690 unboxedClass : Class <S >,
17- val boxedClass : Class <D >,
18- ) : StdConverter<S, D>() {
19- private val boxMethod = boxedClass.getDeclaredMethod(" box-impl" , unboxedClass).apply {
20- ClassUtil .checkAndFixAccess(this , false )
21- }
91+ override val boxedClass : Class <D >,
92+ ) : ValueClassBoxConverter<S, D>() {
93+ override val boxHandle: MethodHandle = rawBoxHandle(unboxedClass).asType(ANY_TO_ANY_METHOD_TYPE )
2294
2395 @Suppress(" UNCHECKED_CAST" )
24- override fun convert (value : S ): D = boxMethod.invoke(null , value) as D
96+ override fun convert (value : S ): D = boxHandle.invokeExact(value) as D
97+ }
98+
99+ internal sealed class ValueClassUnboxConverter <S : Any , D : Any ?> : StdConverter <S , D >() {
100+ abstract val valueClass: Class <S >
101+ abstract val unboxedType: Type
102+ abstract val unboxHandle: MethodHandle
103+
104+ final override fun getInputType (typeFactory : TypeFactory ): JavaType = typeFactory.constructType(valueClass)
105+ final override fun getOutputType (typeFactory : TypeFactory ): JavaType = typeFactory.constructType(unboxedType)
25106
26107 val delegatingSerializer: StdDelegatingSerializer by lazy { StdDelegatingSerializer (this ) }
27- }
28108
29- internal class ValueClassUnboxConverter <T : Any >(val valueClass : Class <T >) : StdConverter<T, Any?>() {
30- private val unboxMethod = valueClass.getDeclaredMethod(" unbox-impl" ).apply {
31- ClassUtil .checkAndFixAccess(this , false )
109+ companion object {
110+ fun create (valueClass : Class <* >): ValueClassUnboxConverter <* , * > {
111+ val unboxMethod = valueClass.getDeclaredMethod(" unbox-impl" )
112+ val unboxedType = unboxMethod.genericReturnType
113+
114+ return when (unboxedType) {
115+ INT_CLASS -> IntValueClassUnboxConverter (valueClass, unboxMethod)
116+ LONG_CLASS -> LongValueClassUnboxConverter (valueClass, unboxMethod)
117+ STRING_CLASS -> StringValueClassUnboxConverter (valueClass, unboxMethod)
118+ JAVA_UUID_CLASS -> JavaUuidValueClassUnboxConverter (valueClass, unboxMethod)
119+ else -> GenericValueClassUnboxConverter (valueClass, unboxedType, unboxMethod)
120+ }
121+ }
32122 }
123+ }
33124
34- override fun convert (value : T ): Any? = unboxMethod.invoke(value)
125+ internal class IntValueClassUnboxConverter <T : Any >(
126+ override val valueClass : Class <T >,
127+ unboxMethod : Method ,
128+ ) : ValueClassUnboxConverter<T, Int>() {
129+ override val unboxedType: Type get() = INT_CLASS
130+ override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_INT_METHOD_TYPE )
35131
36- override fun getInputType (typeFactory : TypeFactory ): JavaType = typeFactory.constructType(valueClass)
37- override fun getOutputType (
38- typeFactory : TypeFactory ,
39- ): JavaType = typeFactory.constructType(unboxMethod.genericReturnType)
132+ override fun convert (value : T ): Int = unboxHandle.invokeExact(value) as Int
133+ }
40134
41- val delegatingSerializer: StdDelegatingSerializer by lazy { StdDelegatingSerializer (this ) }
135+ internal class LongValueClassUnboxConverter <T : Any >(
136+ override val valueClass : Class <T >,
137+ unboxMethod : Method ,
138+ ) : ValueClassUnboxConverter<T, Long>() {
139+ override val unboxedType: Type get() = LONG_CLASS
140+ override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_LONG_METHOD_TYPE )
141+
142+ override fun convert (value : T ): Long = unboxHandle.invokeExact(value) as Long
143+ }
144+
145+ internal class StringValueClassUnboxConverter <T : Any >(
146+ override val valueClass : Class <T >,
147+ unboxMethod : Method ,
148+ ) : ValueClassUnboxConverter<T, String?>() {
149+ override val unboxedType: Type get() = STRING_CLASS
150+ override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_STRING_METHOD_TYPE )
151+
152+ override fun convert (value : T ): String? = unboxHandle.invokeExact(value) as String?
153+ }
154+
155+ internal class JavaUuidValueClassUnboxConverter <T : Any >(
156+ override val valueClass : Class <T >,
157+ unboxMethod : Method ,
158+ ) : ValueClassUnboxConverter<T, UUID?>() {
159+ override val unboxedType: Type get() = JAVA_UUID_CLASS
160+ override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_JAVA_UUID_METHOD_TYPE )
161+
162+ override fun convert (value : T ): UUID ? = unboxHandle.invokeExact(value) as UUID ?
163+ }
164+
165+ internal class GenericValueClassUnboxConverter <T : Any >(
166+ override val valueClass : Class <T >,
167+ override val unboxedType : Type ,
168+ unboxMethod : Method ,
169+ ) : ValueClassUnboxConverter<T, Any?>() {
170+ override val unboxHandle: MethodHandle = unreflectAsType(unboxMethod, ANY_TO_ANY_METHOD_TYPE )
171+
172+ override fun convert (value : T ): Any? = unboxHandle.invokeExact(value)
42173}
0 commit comments