1
+ package org.utbot.framework
2
+
3
+ import kotlinx.serialization.ExperimentalSerializationApi
4
+ import kotlinx.serialization.InternalSerializationApi
5
+ import kotlinx.serialization.KSerializer
6
+ import kotlinx.serialization.descriptors.*
7
+ import kotlinx.serialization.encoding.*
8
+ import kotlinx.serialization.serializer
9
+ import org.utbot.common.IntRangeSerializer
10
+ import org.utbot.framework.plugin.api.*
11
+ import org.utbot.framework.plugin.api.util.*
12
+
13
+ private val classIdSerializer = serializer<ClassId >()
14
+
15
+ object UtContextThrowableSerializer : KSerializer<Throwable> {
16
+ override val descriptor: SerialDescriptor
17
+ get() = TODO (" Not yet implemented" )
18
+
19
+ override fun deserialize (decoder : Decoder ): Throwable {
20
+ TODO (" Not yet implemented" )
21
+ }
22
+
23
+ override fun serialize (encoder : Encoder , value : Throwable ) {
24
+ TODO (" Not yet implemented" )
25
+ }
26
+
27
+ }
28
+
29
+ object UtContextClassSerializer : KSerializer<Class<*>> {
30
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor (" utClass" , PrimitiveKind .STRING )
31
+
32
+ override fun deserialize (decoder : Decoder ): Class <* > {
33
+ val name = decoder.decodeString()
34
+
35
+ return utContext.classLoader.loadClass(name)
36
+ }
37
+
38
+ override fun serialize (encoder : Encoder , value : Class <* >) {
39
+ encoder.encodeString(value.name)
40
+ }
41
+ }
42
+
43
+ object UtContextNullableClassSerializer : KSerializer<Class<*>?> {
44
+ override fun deserialize (decoder : Decoder ): Class <* >? {
45
+ val decoded = decoder.decodeString()
46
+
47
+ return if (decoded == " 1" ) null else utContext.classLoader.loadClass(decoded)
48
+ }
49
+
50
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor (" utClassNullable" , PrimitiveKind .STRING )
51
+
52
+ override fun serialize (encoder : Encoder , value : Class <* >? ) {
53
+ encoder.encodeString(value?.name ? : " 1" ) // 1 because classes cannot be named with numbers
54
+ }
55
+ }
56
+
57
+ private val surrogateBuiltinClassIdSerializer = serializer<SurrogateBuiltinClassId >()
58
+
59
+ object BuiltinClassIdSerializer : KSerializer<BuiltinClassId> {
60
+ @InternalSerializationApi
61
+ @ExperimentalSerializationApi
62
+ override val descriptor: SerialDescriptor = buildClassSerialDescriptor(" BuiltinClassId" ) {
63
+ element<SurrogateBuiltinClassId >(" surrogate" )
64
+ element(" outerClass" , UtContextNullableClassSerializer .descriptor)
65
+ }
66
+
67
+ @InternalSerializationApi
68
+ @ExperimentalSerializationApi
69
+ override fun deserialize (decoder : Decoder ): BuiltinClassId {
70
+ return decoder.decodeStructure(descriptor) {
71
+ var surrogate: SurrogateBuiltinClassId ? = null
72
+ var outerClass: Class <* >? = null
73
+
74
+ while (true ) {
75
+ val index = decodeElementIndex(descriptor)
76
+
77
+ when (index) {
78
+ 0 -> surrogate = decodeSerializableElement(descriptor, 0 , surrogateBuiltinClassIdSerializer)
79
+ 1 -> outerClass = decodeSerializableElement(descriptor, 1 , UtContextNullableClassSerializer )
80
+ CompositeDecoder .DECODE_DONE -> break
81
+ else -> error(" unknown element $index " )
82
+ }
83
+ }
84
+
85
+ return BuiltinClassId (
86
+ surrogate!! .name,
87
+ surrogate.canonicalName,
88
+ surrogate.simpleName,
89
+ surrogate.simpleNameWithEnclosings,
90
+ surrogate.isPublic,
91
+ surrogate.isProtected,
92
+ surrogate.isPrivate,
93
+ surrogate.isFinal,
94
+ surrogate.isStatic,
95
+ surrogate.isAbstract,
96
+ surrogate.isAnonymous,
97
+ surrogate.isLocal,
98
+ surrogate.isInner,
99
+ surrogate.isNested,
100
+ surrogate.isSynthetic,
101
+ surrogate.allMethods,
102
+ surrogate.allConstructors,
103
+ surrogate.outerClass
104
+ )
105
+ }
106
+ }
107
+
108
+ @InternalSerializationApi
109
+ @ExperimentalSerializationApi
110
+ override fun serialize (encoder : Encoder , value : BuiltinClassId ) {
111
+ encoder.encodeStructure(descriptor) {
112
+ encodeSerializableElement(
113
+ descriptor,
114
+ 0 ,
115
+ surrogateBuiltinClassIdSerializer,
116
+ value as SurrogateBuiltinClassId
117
+ )
118
+ encodeSerializableElement(descriptor, 1 , UtContextNullableClassSerializer , value.outerClass)
119
+ }
120
+ }
121
+ }
122
+
123
+ private fun <T : Enum <T >> safeValueOf (enumType : Class <T >, type : String ): T {
124
+ return java.lang.Enum .valueOf(enumType, type)
125
+ }
126
+
127
+ object UtEnumConstantModelSerializer : KSerializer<UtEnumConstantModel> {
128
+ @InternalSerializationApi
129
+ @ExperimentalSerializationApi
130
+ override val descriptor: SerialDescriptor = buildClassSerialDescriptor(" UtEnumConstantModel" ) {
131
+ element(" classId" , classIdSerializer.descriptor)
132
+ element<String >(" enum" )
133
+ }
134
+
135
+ @InternalSerializationApi
136
+ @ExperimentalSerializationApi
137
+ override fun deserialize (decoder : Decoder ): UtEnumConstantModel {
138
+ return decoder.decodeStructure(descriptor) {
139
+ var classId: ClassId ? = null
140
+ var enum: String? = null
141
+
142
+ while (true ) {
143
+ when (val index = decodeElementIndex(IntRangeSerializer .descriptor)) {
144
+ 0 -> classId = decodeSerializableElement(descriptor, 0 , classIdSerializer)
145
+ 1 -> enum = decodeStringElement(descriptor, 1 )
146
+ CompositeDecoder .DECODE_DONE -> break
147
+ else -> error(" Unexpected token $index " )
148
+ }
149
+ }
150
+
151
+
152
+ @Suppress(" UNCHECKED_CAST" )
153
+ // suppose that UtEnumConstantModel.classId is underlying enum class
154
+ UtEnumConstantModel (classId!! , safeValueOf(classId.jClass as Class <out Enum <* >>, enum!! ))
155
+ }
156
+ }
157
+
158
+ @InternalSerializationApi
159
+ @ExperimentalSerializationApi
160
+ override fun serialize (encoder : Encoder , value : UtEnumConstantModel ) {
161
+ encoder.encodeStructure(descriptor) {
162
+ encodeSerializableElement(descriptor, 0 , classIdSerializer, value.classId)
163
+ encodeStringElement(descriptor, 1 , value.value.name)
164
+ }
165
+ }
166
+
167
+ }
168
+
169
+ private fun String.parseToPrimitiveTypeJvmName (primitiveType : Char ): Any {
170
+ return when (primitiveType) {
171
+ ' V' -> Unit
172
+ ' Z' -> toBoolean()
173
+ ' B' -> toByte()
174
+ ' C' -> single()
175
+ ' S' -> toShort()
176
+ ' I' -> toInt()
177
+ ' J' -> toLong()
178
+ ' F' -> toFloat()
179
+ ' D' -> toDouble()
180
+ else -> error(" Primitive expected here, but got: $primitiveType " )
181
+ }
182
+ }
183
+
184
+ object UtPrimitiveModelSerializer : KSerializer<UtPrimitiveModel> {
185
+ // todo kononov: possible speed up - char+string instead to remove string concatenation, it is just premilinary version
186
+ override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor (" UtPrimitiveModel" , PrimitiveKind .STRING )
187
+
188
+ override fun deserialize (decoder : Decoder ): UtPrimitiveModel {
189
+ val decodedString = decoder.decodeString()
190
+
191
+ return UtPrimitiveModel (decodedString.substring(1 ).parseToPrimitiveTypeJvmName(decodedString.first()))
192
+ }
193
+
194
+ override fun serialize (encoder : Encoder , value : UtPrimitiveModel ) {
195
+ // because name `value` comes from KSerializer interface,
196
+ // so that name collision is kept to confront calling this function with named parameters
197
+ @Suppress(" UnnecessaryVariable" )
198
+ val primitiveModel = value
199
+
200
+ if (! primitiveModel.classId.isPrimitive || primitiveModelValueToClassId(primitiveModel.value) != primitiveModel.classId) {
201
+ throw IllegalStateException (" PrimitiveModel invariant corrupted: has ${primitiveModel.classId} for ${primitiveModel.value} " )
202
+ }
203
+
204
+ val jvmTypeName = primitiveModel.classId.primitiveTypeJvmNameOrNull()!!
205
+ val valueString = primitiveModel.value.toString()
206
+
207
+ encoder.encodeString(jvmTypeName + valueString)
208
+ }
209
+ }
210
+
211
+ object UtClassRefModelSerializer : KSerializer<UtClassRefModel> {
212
+ @InternalSerializationApi
213
+ @ExperimentalSerializationApi
214
+ override val descriptor: SerialDescriptor = buildClassSerialDescriptor(" UtClassRefModel" ) {
215
+ element(" classId" , classIdSerializer.descriptor)
216
+ }
217
+
218
+ override fun deserialize (decoder : Decoder ): UtClassRefModel {
219
+ val classId = decoder.decodeSerializableValue(classIdSerializer)
220
+
221
+ // if serialization succeeded - expecting deserialization be succeeded
222
+ return UtClassRefModel (classId, classId.jClass)
223
+ }
224
+
225
+ override fun serialize (encoder : Encoder , value : UtClassRefModel ) {
226
+ // because name `value` comes from KSerializer interface,
227
+ // so that name collision is kept to confront calling this function with named parameters
228
+ @Suppress(" UnnecessaryVariable" )
229
+ val classRefModel = value
230
+ val underlyingClassId = classRefModel.value.id
231
+
232
+ if (underlyingClassId != classRefModel.classId) {
233
+ throw IllegalStateException (" classRefModel invariant corrupted: has ${classRefModel.classId} for $underlyingClassId " )
234
+ }
235
+
236
+ encoder.encodeSerializableValue(classIdSerializer, classRefModel.classId)
237
+ }
238
+ }
0 commit comments