Skip to content

Commit f4b7be4

Browse files
wkornewaldosipxd
authored andcommitted
KTOR-7620 Make Url class @serializable and JVM Serializable (#4421)
1 parent bb64e9c commit f4b7be4

File tree

14 files changed

+231
-10
lines changed

14 files changed

+231
-10
lines changed

ktor-http/api/ktor-http.api

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public final class io/ktor/http/ContentTypesKt {
262262
public static final fun withCharsetIfNeeded (Lio/ktor/http/ContentType;Ljava/nio/charset/Charset;)Lio/ktor/http/ContentType;
263263
}
264264

265-
public final class io/ktor/http/Cookie {
265+
public final class io/ktor/http/Cookie : java/io/Serializable {
266266
public static final field Companion Lio/ktor/http/Cookie$Companion;
267267
public fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/ktor/http/CookieEncoding;Ljava/lang/Integer;Lio/ktor/util/date/GMTDate;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/Map;)V
268268
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Lio/ktor/http/CookieEncoding;Ljava/lang/Integer;Lio/ktor/util/date/GMTDate;Ljava/lang/String;Ljava/lang/String;ZZLjava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -966,7 +966,7 @@ public final class io/ktor/http/URLParserKt {
966966
public static final fun takeFrom (Lio/ktor/http/URLBuilder;Ljava/lang/String;)Lio/ktor/http/URLBuilder;
967967
}
968968

969-
public final class io/ktor/http/URLProtocol {
969+
public final class io/ktor/http/URLProtocol : java/io/Serializable {
970970
public static final field Companion Lio/ktor/http/URLProtocol$Companion;
971971
public fun <init> (Ljava/lang/String;I)V
972972
public final fun component1 ()Ljava/lang/String;
@@ -1026,7 +1026,7 @@ public final class io/ktor/http/UnsafeHeaderException : java/lang/IllegalArgumen
10261026
public fun <init> (Ljava/lang/String;)V
10271027
}
10281028

1029-
public final class io/ktor/http/Url {
1029+
public final class io/ktor/http/Url : java/io/Serializable {
10301030
public static final field Companion Lio/ktor/http/Url$Companion;
10311031
public fun equals (Ljava/lang/Object;)Z
10321032
public final fun getEncodedFragment ()Ljava/lang/String;
@@ -1053,13 +1053,23 @@ public final class io/ktor/http/Url {
10531053
}
10541054

10551055
public final class io/ktor/http/Url$Companion {
1056+
public final fun serializer ()Lkotlinx/serialization/KSerializer;
10561057
}
10571058

10581059
public final class io/ktor/http/UrlKt {
10591060
public static final fun getAuthority (Lio/ktor/http/Url;)Ljava/lang/String;
10601061
public static final fun getProtocolWithAuthority (Lio/ktor/http/Url;)Ljava/lang/String;
10611062
}
10621063

1064+
public final class io/ktor/http/UrlSerializer : kotlinx/serialization/KSerializer {
1065+
public static final field INSTANCE Lio/ktor/http/UrlSerializer;
1066+
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lio/ktor/http/Url;
1067+
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
1068+
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
1069+
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lio/ktor/http/Url;)V
1070+
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
1071+
}
1072+
10631073
public final class io/ktor/http/auth/AuthScheme {
10641074
public static final field Basic Ljava/lang/String;
10651075
public static final field Bearer Ljava/lang/String;

ktor-http/api/ktor-http.klib.api

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ final class io.ktor.http/ContentType : io.ktor.http/HeaderValueWithParameters {
573573
}
574574
}
575575

576-
final class io.ktor.http/Cookie { // io.ktor.http/Cookie|null[0]
576+
final class io.ktor.http/Cookie : io.ktor.utils.io/JvmSerializable { // io.ktor.http/Cookie|null[0]
577577
constructor <init>(kotlin/String, kotlin/String, io.ktor.http/CookieEncoding = ..., kotlin/Int? = ..., io.ktor.util.date/GMTDate? = ..., kotlin/String? = ..., kotlin/String? = ..., kotlin/Boolean = ..., kotlin/Boolean = ..., kotlin.collections/Map<kotlin/String, kotlin/String?> = ...) // io.ktor.http/Cookie.<init>|<init>(kotlin.String;kotlin.String;io.ktor.http.CookieEncoding;kotlin.Int?;io.ktor.util.date.GMTDate?;kotlin.String?;kotlin.String?;kotlin.Boolean;kotlin.Boolean;kotlin.collections.Map<kotlin.String,kotlin.String?>){}[0]
578578

579579
final val domain // io.ktor.http/Cookie.domain|{}domain[0]
@@ -1048,7 +1048,7 @@ final class io.ktor.http/URLParserException : kotlin/IllegalStateException { //
10481048
constructor <init>(kotlin/String, kotlin/Throwable) // io.ktor.http/URLParserException.<init>|<init>(kotlin.String;kotlin.Throwable){}[0]
10491049
}
10501050

1051-
final class io.ktor.http/URLProtocol { // io.ktor.http/URLProtocol|null[0]
1051+
final class io.ktor.http/URLProtocol : io.ktor.utils.io/JvmSerializable { // io.ktor.http/URLProtocol|null[0]
10521052
constructor <init>(kotlin/String, kotlin/Int) // io.ktor.http/URLProtocol.<init>|<init>(kotlin.String;kotlin.Int){}[0]
10531053

10541054
final val defaultPort // io.ktor.http/URLProtocol.defaultPort|{}defaultPort[0]
@@ -1085,7 +1085,7 @@ final class io.ktor.http/UnsafeHeaderException : kotlin/IllegalArgumentException
10851085
constructor <init>(kotlin/String) // io.ktor.http/UnsafeHeaderException.<init>|<init>(kotlin.String){}[0]
10861086
}
10871087

1088-
final class io.ktor.http/Url { // io.ktor.http/Url|null[0]
1088+
final class io.ktor.http/Url : io.ktor.utils.io/JvmSerializable { // io.ktor.http/Url|null[0]
10891089
final val encodedFragment // io.ktor.http/Url.encodedFragment|{}encodedFragment[0]
10901090
final fun <get-encodedFragment>(): kotlin/String // io.ktor.http/Url.encodedFragment.<get-encodedFragment>|<get-encodedFragment>(){}[0]
10911091
final val encodedPassword // io.ktor.http/Url.encodedPassword|{}encodedPassword[0]
@@ -1129,7 +1129,9 @@ final class io.ktor.http/Url { // io.ktor.http/Url|null[0]
11291129
final fun hashCode(): kotlin/Int // io.ktor.http/Url.hashCode|hashCode(){}[0]
11301130
final fun toString(): kotlin/String // io.ktor.http/Url.toString|toString(){}[0]
11311131

1132-
final object Companion // io.ktor.http/Url.Companion|null[0]
1132+
final object Companion { // io.ktor.http/Url.Companion|null[0]
1133+
final fun serializer(): kotlinx.serialization/KSerializer<io.ktor.http/Url> // io.ktor.http/Url.Companion.serializer|serializer(){}[0]
1134+
}
11331135
}
11341136

11351137
sealed class io.ktor.http.auth/HttpAuthHeader { // io.ktor.http.auth/HttpAuthHeader|null[0]
@@ -1580,6 +1582,14 @@ final object io.ktor.http/HttpHeaders { // io.ktor.http/HttpHeaders|null[0]
15801582
final fun isUnsafe(kotlin/String): kotlin/Boolean // io.ktor.http/HttpHeaders.isUnsafe|isUnsafe(kotlin.String){}[0]
15811583
}
15821584

1585+
final object io.ktor.http/UrlSerializer : kotlinx.serialization/KSerializer<io.ktor.http/Url> { // io.ktor.http/UrlSerializer|null[0]
1586+
final val descriptor // io.ktor.http/UrlSerializer.descriptor|{}descriptor[0]
1587+
final fun <get-descriptor>(): kotlinx.serialization.descriptors/SerialDescriptor // io.ktor.http/UrlSerializer.descriptor.<get-descriptor>|<get-descriptor>(){}[0]
1588+
1589+
final fun deserialize(kotlinx.serialization.encoding/Decoder): io.ktor.http/Url // io.ktor.http/UrlSerializer.deserialize|deserialize(kotlinx.serialization.encoding.Decoder){}[0]
1590+
final fun serialize(kotlinx.serialization.encoding/Encoder, io.ktor.http/Url) // io.ktor.http/UrlSerializer.serialize|serialize(kotlinx.serialization.encoding.Encoder;io.ktor.http.Url){}[0]
1591+
}
1592+
15831593
final const val io.ktor.http/DEFAULT_PORT // io.ktor.http/DEFAULT_PORT|{}DEFAULT_PORT[0]
15841594
final fun <get-DEFAULT_PORT>(): kotlin/Int // io.ktor.http/DEFAULT_PORT.<get-DEFAULT_PORT>|<get-DEFAULT_PORT>(){}[0]
15851595

ktor-http/build.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,12 @@ kotlin {
1414
api(libs.kotlinx.serialization.core)
1515
}
1616
}
17+
jvmTest {
18+
dependencies {
19+
implementation(project(":ktor-shared:ktor-junit"))
20+
implementation(project(":ktor-shared:ktor-serialization:ktor-serialization-kotlinx"))
21+
implementation(project(":ktor-shared:ktor-serialization:ktor-serialization-kotlinx:ktor-serialization-kotlinx-json"))
22+
}
23+
}
1724
}
1825
}

ktor-http/common/src/io/ktor/http/Cookie.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
@file:OptIn(InternalAPI::class)
6+
57
package io.ktor.http
68

79
import io.ktor.util.*
810
import io.ktor.util.date.*
11+
import io.ktor.utils.io.*
912
import kotlinx.serialization.*
1013
import kotlin.jvm.*
1114

@@ -37,7 +40,17 @@ public data class Cookie(
3740
val secure: Boolean = false,
3841
val httpOnly: Boolean = false,
3942
val extensions: Map<String, String?> = emptyMap()
40-
)
43+
) : JvmSerializable {
44+
private fun writeReplace(): Any = JvmSerializerReplacement(CookieJvmSerializer, this)
45+
}
46+
47+
internal object CookieJvmSerializer : JvmSerializer<Cookie> {
48+
override fun jvmSerialize(value: Cookie): ByteArray =
49+
renderSetCookieHeader(value).encodeToByteArray()
50+
51+
override fun jvmDeserialize(value: ByteArray): Cookie =
52+
parseServerSetCookieHeader(value.decodeToString())
53+
}
4154

4255
/**
4356
* Cooke encoding strategy

ktor-http/common/src/io/ktor/http/URLProtocol.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
package io.ktor.http
66

77
import io.ktor.util.*
8+
import io.ktor.utils.io.*
89

910
/**
1011
* Represents URL protocol
1112
* @property name of protocol (schema)
1213
* @property defaultPort default port for protocol or `-1` if not known
1314
*/
14-
public data class URLProtocol(val name: String, val defaultPort: Int) {
15+
@OptIn(InternalAPI::class)
16+
public data class URLProtocol(val name: String, val defaultPort: Int) : JvmSerializable {
1517
init {
1618
require(name.all { it.isLowerCase() }) { "All characters should be lower case" }
1719
}

ktor-http/common/src/io/ktor/http/Url.kt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,15 @@
22
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
33
*/
44

5+
@file:OptIn(InternalAPI::class)
6+
57
package io.ktor.http
68

9+
import io.ktor.utils.io.*
10+
import kotlinx.serialization.*
11+
import kotlinx.serialization.descriptors.*
12+
import kotlinx.serialization.encoding.*
13+
714
/**
815
* Represents an immutable URL
916
*
@@ -18,6 +25,7 @@ package io.ktor.http
1825
* @property password password part of URL
1926
* @property trailingQuery keep trailing question character even if there are no query parameters
2027
*/
28+
@Serializable(with = UrlSerializer::class)
2129
public class Url internal constructor(
2230
protocol: URLProtocol?,
2331
public val host: String,
@@ -29,7 +37,7 @@ public class Url internal constructor(
2937
public val password: String?,
3038
public val trailingQuery: Boolean,
3139
private val urlString: String
32-
) {
40+
) : JvmSerializable {
3341
init {
3442
require(specifiedPort in 0..65535) {
3543
"Port must be between 0 and 65535, or $DEFAULT_PORT if not set. Provided: $specifiedPort"
@@ -222,6 +230,8 @@ public class Url internal constructor(
222230
return urlString.hashCode()
223231
}
224232

233+
private fun writeReplace(): Any = JvmSerializerReplacement(UrlJvmSerializer, this)
234+
225235
public companion object
226236
}
227237

@@ -254,3 +264,23 @@ internal val Url.encodedUserAndPassword: String
254264
get() = buildString {
255265
appendUserAndPassword(encodedUser, encodedPassword)
256266
}
267+
268+
public object UrlSerializer : KSerializer<Url> {
269+
override val descriptor: SerialDescriptor =
270+
PrimitiveSerialDescriptor("io.ktor.http.Url", PrimitiveKind.STRING)
271+
272+
override fun deserialize(decoder: Decoder): Url =
273+
Url(decoder.decodeString())
274+
275+
override fun serialize(encoder: Encoder, value: Url) {
276+
encoder.encodeString(value.toString())
277+
}
278+
}
279+
280+
internal object UrlJvmSerializer : JvmSerializer<Url> {
281+
override fun jvmSerialize(value: Url): ByteArray =
282+
value.toString().encodeToByteArray()
283+
284+
override fun jvmDeserialize(value: ByteArray): Url =
285+
Url(value.decodeToString())
286+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2014-2019 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.tests.http
6+
7+
import io.ktor.http.*
8+
import io.ktor.junit.*
9+
import kotlin.test.*
10+
11+
class SerializableTest {
12+
@Test
13+
fun urlTest() {
14+
assertSerializable(Url("https://localhost/path?key=value#fragment"))
15+
}
16+
17+
@Test
18+
fun cookieTest() {
19+
assertSerializable(Cookie("key", "value"))
20+
}
21+
}

ktor-io/api/ktor-io.api

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,17 @@ public final class io/ktor/utils/io/CountedByteWriteChannelKt {
214214
public static final fun counted (Lio/ktor/utils/io/ByteWriteChannel;)Lio/ktor/utils/io/CountedByteWriteChannel;
215215
}
216216

217+
public final class io/ktor/utils/io/DefaultJvmSerializerReplacement : java/io/Externalizable {
218+
public static final field Companion Lio/ktor/utils/io/DefaultJvmSerializerReplacement$Companion;
219+
public fun <init> ()V
220+
public fun <init> (Lio/ktor/utils/io/JvmSerializer;Ljava/lang/Object;)V
221+
public fun readExternal (Ljava/io/ObjectInput;)V
222+
public fun writeExternal (Ljava/io/ObjectOutput;)V
223+
}
224+
225+
public final class io/ktor/utils/io/DefaultJvmSerializerReplacement$Companion {
226+
}
227+
217228
public final class io/ktor/utils/io/DeprecationKt {
218229
public static final fun readText (Lkotlinx/io/Source;)Ljava/lang/String;
219230
public static final fun release (Lkotlinx/io/Sink;)V
@@ -222,6 +233,15 @@ public final class io/ktor/utils/io/DeprecationKt {
222233
public abstract interface annotation class io/ktor/utils/io/InternalAPI : java/lang/annotation/Annotation {
223234
}
224235

236+
public final class io/ktor/utils/io/JvmSerializable_jvmKt {
237+
public static final fun JvmSerializerReplacement (Lio/ktor/utils/io/JvmSerializer;Ljava/lang/Object;)Ljava/lang/Object;
238+
}
239+
240+
public abstract interface class io/ktor/utils/io/JvmSerializer : java/io/Serializable {
241+
public abstract fun jvmDeserialize ([B)Ljava/lang/Object;
242+
public abstract fun jvmSerialize (Ljava/lang/Object;)[B
243+
}
244+
225245
public abstract interface annotation class io/ktor/utils/io/KtorDsl : java/lang/annotation/Annotation {
226246
}
227247

ktor-io/api/ktor-io.klib.api

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ abstract interface <#A: kotlin/Any> io.ktor.utils.io.pool/ObjectPool : kotlin/Au
5353
open fun close() // io.ktor.utils.io.pool/ObjectPool.close|close(){}[0]
5454
}
5555

56+
abstract interface <#A: kotlin/Any?> io.ktor.utils.io/JvmSerializer : io.ktor.utils.io/JvmSerializable { // io.ktor.utils.io/JvmSerializer|null[0]
57+
abstract fun jvmDeserialize(kotlin/ByteArray): #A // io.ktor.utils.io/JvmSerializer.jvmDeserialize|jvmDeserialize(kotlin.ByteArray){}[0]
58+
abstract fun jvmSerialize(#A): kotlin/ByteArray // io.ktor.utils.io/JvmSerializer.jvmSerialize|jvmSerialize(1:0){}[0]
59+
}
60+
5661
abstract interface io.ktor.utils.io.core/Closeable : kotlin/AutoCloseable { // io.ktor.utils.io.core/Closeable|null[0]
5762
abstract fun close() // io.ktor.utils.io.core/Closeable.close|close(){}[0]
5863
}
@@ -97,6 +102,8 @@ abstract interface io.ktor.utils.io/ChannelJob { // io.ktor.utils.io/ChannelJob|
97102
abstract fun <get-job>(): kotlinx.coroutines/Job // io.ktor.utils.io/ChannelJob.job.<get-job>|<get-job>(){}[0]
98103
}
99104

105+
abstract interface io.ktor.utils.io/JvmSerializable // io.ktor.utils.io/JvmSerializable|null[0]
106+
100107
abstract class <#A: kotlin/Any> io.ktor.utils.io.pool/DefaultPool : io.ktor.utils.io.pool/ObjectPool<#A> { // io.ktor.utils.io.pool/DefaultPool|null[0]
101108
constructor <init>(kotlin/Int) // io.ktor.utils.io.pool/DefaultPool.<init>|<init>(kotlin.Int){}[0]
102109

@@ -400,6 +407,7 @@ final fun (kotlinx.io/Source).io.ktor.utils.io.core/readTextExactCharacters(kotl
400407
final fun (kotlinx.io/Source).io.ktor.utils.io.core/release() // io.ktor.utils.io.core/release|[email protected](){}[0]
401408
final fun (kotlinx.io/Source).io.ktor.utils.io.core/takeWhile(kotlin/Function1<kotlinx.io/Buffer, kotlin/Boolean>) // io.ktor.utils.io.core/takeWhile|[email protected](kotlin.Function1<kotlinx.io.Buffer,kotlin.Boolean>){}[0]
402409
final fun (kotlinx.io/Source).io.ktor.utils.io/readText(): kotlin/String // io.ktor.utils.io/readText|[email protected](){}[0]
410+
final fun <#A: kotlin/Any> io.ktor.utils.io/JvmSerializerReplacement(io.ktor.utils.io/JvmSerializer<#A>, #A): kotlin/Any // io.ktor.utils.io/JvmSerializerReplacement|JvmSerializerReplacement(io.ktor.utils.io.JvmSerializer<0:0>;0:0){0§<kotlin.Any>}[0]
403411
final fun <#A: kotlin/Any?> (kotlinx.io/Sink).io.ktor.utils.io.core/preview(kotlin/Function1<kotlinx.io/Source, #A>): #A // io.ktor.utils.io.core/preview|[email protected](kotlin.Function1<kotlinx.io.Source,0:0>){0§<kotlin.Any?>}[0]
404412
final fun <#A: kotlin/Any?> (kotlinx.io/Source).io.ktor.utils.io.core/preview(kotlin/Function1<kotlinx.io/Source, #A>): #A // io.ktor.utils.io.core/preview|[email protected](kotlin.Function1<kotlinx.io.Source,0:0>){0§<kotlin.Any?>}[0]
405413
final fun <#A: kotlin/Any?> io.ktor.utils.io.core/withMemory(kotlin/Int, kotlin/Function1<kotlin/ByteArray, #A>): #A // io.ktor.utils.io.core/withMemory|withMemory(kotlin.Int;kotlin.Function1<kotlin.ByteArray,0:0>){0§<kotlin.Any?>}[0]
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.utils.io
6+
7+
/** Alias for `java.io.Serializable` on JVM. Empty interface otherwise. */
8+
@InternalAPI
9+
public expect interface JvmSerializable
10+
11+
@InternalAPI
12+
public interface JvmSerializer<T> : JvmSerializable {
13+
public fun jvmSerialize(value: T): ByteArray
14+
public fun jvmDeserialize(value: ByteArray): T
15+
}
16+
17+
@InternalAPI
18+
public expect fun <T : Any> JvmSerializerReplacement(serializer: JvmSerializer<T>, value: T): Any
19+
20+
internal object DummyJvmSimpleSerializerReplacement
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.utils.io
6+
7+
@InternalAPI
8+
public actual interface JvmSerializable
9+
10+
@InternalAPI
11+
public actual fun <T : Any> JvmSerializerReplacement(serializer: JvmSerializer<T>, value: T): Any =
12+
DummyJvmSimpleSerializerReplacement
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2014-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package io.ktor.utils.io
6+
7+
import java.io.*
8+
9+
@InternalAPI
10+
public actual typealias JvmSerializable = Serializable
11+
12+
@Suppress("UNCHECKED_CAST")
13+
@InternalAPI
14+
public actual fun <T : Any> JvmSerializerReplacement(serializer: JvmSerializer<T>, value: T): Any =
15+
DefaultJvmSerializerReplacement(serializer, value)
16+
17+
@OptIn(InternalAPI::class)
18+
@PublishedApi // IMPORTANT: changing the class name would result in serialization incompatibility
19+
internal class DefaultJvmSerializerReplacement<T : Any>(
20+
private var serializer: JvmSerializer<T>?,
21+
private var value: T?
22+
) : Externalizable {
23+
constructor() : this(null, null)
24+
25+
override fun writeExternal(out: ObjectOutput) {
26+
out.writeObject(serializer)
27+
out.writeObject(serializer!!.jvmSerialize(value!!))
28+
}
29+
30+
@Suppress("UNCHECKED_CAST")
31+
override fun readExternal(`in`: ObjectInput) {
32+
serializer = `in`.readObject() as JvmSerializer<T>
33+
value = serializer!!.jvmDeserialize(`in`.readObject() as ByteArray)
34+
}
35+
36+
private fun readResolve(): Any =
37+
value!!
38+
39+
companion object {
40+
private const val serialVersionUID: Long = 0L
41+
}
42+
}

0 commit comments

Comments
 (0)