1 /*
2  * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 @file:OptIn(ExperimentalSerializationApi::class)
5 package kotlinx.serialization.internal
6 
7 import kotlinx.serialization.*
8 import kotlinx.serialization.descriptors.*
9 import kotlinx.serialization.encoding.*
10 
11 /**
12  * Use [KSerializer.nullable][nullable] instead.
13  * @suppress internal API
14  */
15 @PublishedApi
16 @OptIn(ExperimentalSerializationApi::class)
17 internal class NullableSerializer<T : Any>(private val serializer: KSerializer<T>) : KSerializer<T?> {
18     override val descriptor: SerialDescriptor = SerialDescriptorForNullable(serializer.descriptor)
19 
serializenull20     override fun serialize(encoder: Encoder, value: T?) {
21         if (value != null) {
22             encoder.encodeNotNullMark()
23             encoder.encodeSerializableValue(serializer, value)
24         } else {
25             encoder.encodeNull()
26         }
27     }
28 
deserializenull29     override fun deserialize(decoder: Decoder): T? {
30         return if (decoder.decodeNotNullMark()) decoder.decodeSerializableValue(serializer) else decoder.decodeNull()
31     }
32 
equalsnull33     override fun equals(other: Any?): Boolean {
34         if (this === other) return true
35         if (other == null || this::class != other::class) return false
36         other as NullableSerializer<*>
37         if (serializer != other.serializer) return false
38         return true
39     }
40 
hashCodenull41     override fun hashCode(): Int {
42         return serializer.hashCode()
43     }
44 }
45 
46 @OptIn(ExperimentalSerializationApi::class)
47 internal class SerialDescriptorForNullable(
48     internal val original: SerialDescriptor
49 ) : SerialDescriptor by original, CachedNames {
50 
51     override val serialName: String = original.serialName + "?"
52     override val serialNames: Set<String> = original.cachedSerialNames()
53     override val isNullable: Boolean
54         get() = true
55 
equalsnull56     override fun equals(other: Any?): Boolean {
57         if (this === other) return true
58         if (other !is SerialDescriptorForNullable) return false
59         if (original != other.original) return false
60         return true
61     }
62 
toStringnull63     override fun toString(): String {
64         return "$original?"
65     }
66 
hashCodenull67     override fun hashCode(): Int {
68         return original.hashCode() * 31
69     }
70 }
71