1 /*
2  * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 package kotlinx.serialization.descriptors
6 
7 import kotlinx.serialization.*
8 import kotlinx.serialization.encoding.*
9 import kotlinx.serialization.modules.*
10 
11 /**
12  * Serial kind is an intrinsic property of [SerialDescriptor] that indicates how
13  * the corresponding type is structurally represented by its serializer.
14  *
15  * Kind is used by serialization formats to determine how exactly the given type
16  * should be serialized. For example, JSON format detects the kind of the value and,
17  * depending on that, may write it as a plain value for primitive kinds, open a
18  * curly brace '{' for class-like structures and square bracket '[' for list- and array- like structures.
19  *
20  * Kinds are used both during serialization, to serialize a value properly and statically, and
21  * to introspect the type structure or build serialization schema.
22  *
23  * Kind should match the structure of the serialized form, not the structure of the corresponding Kotlin class.
24  * Meaning that if serializable class `class IntPair(val left: Int, val right: Int)` is represented by the serializer
25  * as a single `Long` value, its descriptor should have [PrimitiveKind.LONG] without nested elements even though the class itself
26  * represents a structure with two primitive fields.
27  */
28 @ExperimentalSerializationApi
29 public sealed class SerialKind {
30 
31     /**
32      * Represents a Kotlin [Enum] with statically known values.
33      * All enum values should be enumerated in descriptor elements.
34      * Each element descriptor of a [Enum] kind represents an instance of a particular enum
35      * and has an [StructureKind.OBJECT] kind.
36      * Each [positional name][SerialDescriptor.getElementName] contains a corresponding enum element [name][Enum.name].
37      *
38      * Corresponding encoder and decoder methods are [Encoder.encodeEnum] and [Decoder.decodeEnum].
39      */
40     @ExperimentalSerializationApi
41     public object ENUM : SerialKind()
42 
43     /**
44      * Represents an "unknown" type that will be known only at the moment of the serialization.
45      * Effectively it defers the choice of the serializer to a moment of the serialization, and can
46      * be used for [contextual][Contextual] serialization.
47      *
48      * To introspect descriptor of this kind, an instance of [SerializersModule] is required.
49      * See [capturedKClass] extension property for more details.
50      * However, if possible options are known statically (e.g. for sealed classes), they can be
51      * enumerated in child descriptors similarly to [ENUM].
52      */
53     @ExperimentalSerializationApi
54     public object CONTEXTUAL : SerialKind()
55 
toStringnull56     override fun toString(): String {
57         // KNPE should never happen, because SerialKind is sealed and all inheritors are non-anonymous
58         return this::class.simpleName!!
59     }
60 
61     // Provide a stable hashcode for objects
hashCodenull62     override fun hashCode(): Int = toString().hashCode()
63 }
64 
65 /**
66  * Values of primitive kinds usually are represented as a single value.
67  * All default serializers for Kotlin [primitives types](https://kotlinlang.org/docs/tutorials/kotlin-for-py/primitive-data-types-and-their-limitations.html)
68  * and [String] have primitive kind.
69  *
70  * ### Serializers interaction
71  *
72  * Serialization formats typically handle these kinds by calling a corresponding primitive method on encoder or decoder.
73  * For example, if the following serializable class `class Color(val red: Byte, val green: Byte, val blue: Byte)` is represented by your serializer
74  * as a single [Int] value, a typical serializer will serialize its value in the following manner:
75  * ```
76  * val intValue = color.rgbToInt()
77  * encoder.encodeInt(intValue)
78  * ```
79  * and a corresponding [Decoder] counterpart.
80  *
81  * ### Implementation note
82  *
83  * Serial descriptors for primitive kinds are not expected to have any nested elements, thus its element count should be zero.
84  * If a class is represented as a primitive value, its corresponding serial name *should not* be equal to the corresponding primitive type name.
85  * For the `Color` example, represented as single [Int], its descriptor should have [INT] kind, zero elements and serial name **not equals**
86  * to `kotlin.Int`: `PrimitiveDescriptor("my.package.ColorAsInt", PrimitiveKind.INT)`
87  */
88 @OptIn(ExperimentalSerializationApi::class) // May be @Experimental, but break clients + makes impossible to use stable PrimitiveSerialDescriptor
89 public sealed class PrimitiveKind : SerialKind() {
90     /**
91      * Primitive kind that represents a boolean `true`/`false` value.
92      * Corresponding Kotlin primitive is [Boolean].
93      * Corresponding encoder and decoder methods are [Encoder.encodeBoolean] and [Decoder.decodeBoolean].
94      */
95     public object BOOLEAN : PrimitiveKind()
96 
97     /**
98      * Primitive kind that represents a single byte value.
99      * Corresponding Kotlin primitive is [Byte].
100      * Corresponding encoder and decoder methods are [Encoder.encodeByte] and [Decoder.decodeByte].
101      */
102     public object BYTE : PrimitiveKind()
103 
104     /**
105      * Primitive kind that represents a 16-bit unicode character value.
106      * Corresponding Kotlin primitive is [Char].
107      * Corresponding encoder and decoder methods are [Encoder.encodeChar] and [Decoder.decodeChar].
108      */
109     public object CHAR : PrimitiveKind()
110 
111     /**
112      * Primitive kind that represents a 16-bit short value.
113      * Corresponding Kotlin primitive is [Short].
114      * Corresponding encoder and decoder methods are [Encoder.encodeShort] and [Decoder.decodeShort].
115      */
116     public object SHORT : PrimitiveKind()
117 
118     /**
119      * Primitive kind that represents a 32-bit int value.
120      * Corresponding Kotlin primitive is [Int].
121      * Corresponding encoder and decoder methods are [Encoder.encodeInt] and [Decoder.decodeInt].
122      */
123     public object INT : PrimitiveKind()
124 
125     /**
126      * Primitive kind that represents a 64-bit long value.
127      * Corresponding Kotlin primitive is [Long].
128      * Corresponding encoder and decoder methods are [Encoder.encodeLong] and [Decoder.decodeLong].
129      */
130     public object LONG : PrimitiveKind()
131 
132     /**
133      * Primitive kind that represents a 32-bit IEEE 754 floating point value.
134      * Corresponding Kotlin primitive is [Float].
135      * Corresponding encoder and decoder methods are [Encoder.encodeFloat] and [Decoder.decodeFloat].
136      */
137     public object FLOAT : PrimitiveKind()
138 
139     /**
140      * Primitive kind that represents a 64-bit IEEE 754 floating point value.
141      * Corresponding Kotlin primitive is [Double].
142      * Corresponding encoder and decoder methods are [Encoder.encodeDouble] and [Decoder.decodeDouble].
143      */
144     public object DOUBLE : PrimitiveKind()
145 
146     /**
147      * Primitive kind that represents a string value.
148      * Corresponding Kotlin primitive is [String].
149      * Corresponding encoder and decoder methods are [Encoder.encodeString] and [Decoder.decodeString].
150      */
151     public object STRING : PrimitiveKind()
152 }
153 
154 /**
155  * Structure kind represents values with composite structure of nested elements of depth and arbitrary number.
156  * We acknowledge following structured kinds:
157  *
158  * ### Regular classes
159  * The most common case for serialization, that represents an arbitrary structure with fixed count of elements.
160  * When the regular Kotlin class is marked as [Serializable], its descriptor kind will be [CLASS].
161  *
162  * ### Lists
163  * [LIST] represent a structure with potentially unknown in advance number of elements of the same type.
164  * All standard serializable [List] implementors and arrays are represented as [LIST] kind of the same type.
165  *
166  * ### Maps
167  * [MAP] represent a structure with potentially unknown in advance number of key-value pairs of the same type.
168  * All standard serializable [Map] implementors are represented as [Map] kind of the same type.
169  *
170  * ### Kotlin objects
171  * A singleton object defined with `object` keyword with an [OBJECT] kind.
172  * By default, objects are serialized as empty structures without any states and their identity is preserved
173  * across serialization within the same process, so you always have the same instance of the object.
174  *
175  * ### Serializers interaction
176  * Serialization formats typically handle these kinds by marking structure start and end.
177  * E.g. the following serializable class `class IntHolder(myValue: Int)` of structure kind [CLASS] is handled by
178  * serializer as the following call sequence:
179  * ```
180  * val composite = encoder.beginStructure(descriptor) // Denotes the start of the structure
181  * composite.encodeIntElement(descriptor, index = 0, holder.myValue)
182  * composite.endStructure(descriptor) // Denotes the end of the structure
183  * ```
184  * and its corresponding [Decoder] counterpart.
185  *
186  * ### Serial descriptor implementors note
187  * These kinds can be used not only for collection and regular classes.
188  * For example, provided serializer for [Map.Entry] represents it as [Map] type, so it is serialized
189  * as `{"actualKey": "actualValue"}` map directly instead of `{"key": "actualKey", "value": "actualValue"}`
190  */
191 @ExperimentalSerializationApi
192 public sealed class StructureKind : SerialKind() {
193 
194     /**
195      * Structure kind for regular classes with an arbitrary, but known statically, structure.
196      * Serializers typically encode classes with calls to [Encoder.beginStructure] and [CompositeEncoder.endStructure],
197      * writing the elements of the class between these calls.
198      */
199     public object CLASS : StructureKind()
200 
201     /**
202      * Structure kind for lists and arrays of an arbitrary length.
203      * Serializers typically encode classes with calls to [Encoder.beginCollection] and [CompositeEncoder.endStructure],
204      * writing the elements of the list between these calls.
205      * Built-in list serializers treat elements as homogeneous, though application-specific serializers may impose
206      * application-specific restrictions on specific [LIST] types.
207      *
208      * Example of such application-specific serialization may be class `class ListOfThreeElements() : List<Any>`,
209      * for which an author of the serializer knows that while it is `List<Any>`, in fact, is always has three elements
210      * of a known type (e.g. the first is always a string, the second one is always an int etc.)
211      */
212     public object LIST : StructureKind()
213 
214     /**
215      * Structure kind for maps of an arbitrary length.
216      * Serializers typically encode classes with calls to [Encoder.beginCollection] and [CompositeEncoder.endStructure],
217      * writing the elements of the map between these calls.
218      *
219      * Built-in map serializers treat elements as homogeneous, though application-specific serializers may impose
220      * application-specific restrictions on specific [MAP] types.
221      */
222     public object MAP : StructureKind()
223 
224     /**
225      * Structure kind for singleton objects defined with `object` keyword.
226      * By default, objects are serialized as empty structures without any state and their identity is preserved
227      * across serialization within the same process, so you always have the same instance of the object.
228      *
229      * Empty structure is represented as a call to [Encoder.beginStructure] with the following [CompositeEncoder.endStructure]
230      * without any intermediate encodings.
231      */
232     public object OBJECT : StructureKind()
233 }
234 
235 /**
236  * Polymorphic kind represents a (bounded) polymorphic value, that is referred
237  * by some base class or interface, but its structure is defined by one of the possible implementations.
238  * Polymorphic kind is, by its definition, a union kind and is extracted to its own subtype to emphasize
239  * bounded and sealed polymorphism common property: not knowing the actual type statically and requiring
240  * formats to additionally encode it.
241  */
242 @ExperimentalSerializationApi
243 public sealed class PolymorphicKind : SerialKind() {
244     /**
245      * Sealed kind represents Kotlin sealed classes, where all subclasses are known statically at the moment of declaration.
246      * [SealedClassSerializer] can be used as an example of sealed serialization.
247      */
248     public object SEALED : PolymorphicKind()
249 
250     /**
251      * Open polymorphic kind represents statically unknown type that is hidden behind a given base class or interface.
252      * [PolymorphicSerializer] can be used as an example of polymorphic serialization.
253      *
254      * Due to security concerns and typical mistakes that arises from polymorphic serialization, by default
255      * `kotlinx.serialization` provides only bounded polymorphic serialization, forcing users to register all possible
256      * serializers for a given base class or interface.
257      *
258      * To introspect descriptor of this kind (e.g. list possible subclasses), an instance of [SerializersModule] is required.
259      * See [capturedKClass] extension property for more details.
260      */
261     public object OPEN : PolymorphicKind()
262 }
263