1 /*
2 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
5 package kotlinx.serialization.encoding
6
7 import kotlinx.serialization.*
8 import kotlinx.serialization.builtins.*
9 import kotlinx.serialization.descriptors.*
10 import kotlinx.serialization.modules.*
11
12 /**
13 * Decoder is a core deserialization primitive that encapsulates the knowledge of the underlying
14 * format and an underlying storage, exposing only structural methods to the deserializer, making it completely
15 * format-agnostic. Deserialization process takes a decoder and asks him for a sequence of primitive elements,
16 * defined by a deserializer serial form, while decoder knows how to retrieve these primitive elements from an actual format
17 * representations.
18 *
19 * Decoder provides high-level API that operates with basic primitive types, collections
20 * and nested structures. Internally, the decoder represents input storage, and operates with its state
21 * and lower level format-specific details.
22 *
23 * To be more specific, serialization asks a decoder for a sequence of "give me an int, give me
24 * a double, give me a list of strings and give me another object that is a nested int", while decoding
25 * transforms this sequence into a format-specific commands such as "parse the part of the string until the next quotation mark
26 * as an int to retrieve an int, parse everything within the next curly braces to retrieve elements of a nested object etc."
27 *
28 * The symmetric interface for the serialization process is [Encoder].
29 *
30 * ### Deserialization. Primitives
31 *
32 * If a class is represented as a single [primitive][PrimitiveKind] value in its serialized form,
33 * then one of the `decode*` methods (e.g. [decodeInt]) can be used directly.
34 *
35 * ### Deserialization. Structured types
36 *
37 * If a class is represented as a structure or has multiple values in its serialized form,
38 * `decode*` methods are not that helpful, because format may not require a strict order of data
39 * (e.g. JSON or XML), do not allow working with collection types or establish structure boundaries.
40 * All these capabilities are delegated to the [CompositeDecoder] interface with a more specific API surface.
41 * To denote a structure start, [beginStructure] should be used.
42 * ```
43 * // Denote the structure start,
44 * val composite = decoder.beginStructure(descriptor)
45 * // Decode all elements within the structure using 'composite'
46 * ...
47 * // Denote the structure end
48 * composite.endStructure(descriptor)
49 * ```
50 *
51 * E.g. if the decoder belongs to JSON format, then [beginStructure] will parse an opening bracket
52 * (`{` or `[`, depending on the descriptor kind), returning the [CompositeDecoder] that is aware of colon separator,
53 * that should be read after each key-value pair, whilst [CompositeDecoder.endStructure] will parse a closing bracket.
54 *
55 * ### Exception guarantees.
56 * For the regular exceptions, such as invalid input, missing control symbols or attributes and unknown symbols,
57 * [SerializationException] can be thrown by any decoder methods. It is recommended to declare a format-specific
58 * subclass of [SerializationException] and throw it.
59 *
60 * ### Format encapsulation
61 *
62 * For example, for the following deserializer:
63 * ```
64 * class StringHolder(val stringValue: String)
65 *
66 * object StringPairDeserializer : DeserializationStrategy<StringHolder> {
67 * override val descriptor = ...
68 *
69 * override fun deserializer(decoder: Decoder): StringHolder {
70 * // Denotes start of the structure, StringHolder is not a "plain" data type
71 * val composite = decoder.beginStructure(descriptor)
72 * if (composite.decodeElementIndex(descriptor) != 0)
73 * throw MissingFieldException("Field 'stringValue' is missing")
74 * // Decode the nested string value
75 * val value = composite.decodeStringElement(descriptor, index = 0)
76 * // Denotes end of the structure
77 * composite.endStructure(descriptor)
78 * }
79 * }
80 * ```
81 *
82 * ### Exception safety
83 *
84 * In general, catching [SerializationException] from any of `decode*` methods is not allowed and produces unspecified behaviour.
85 * After thrown exception, current decoder is left in an arbitrary state, no longer suitable for further decoding.
86 *
87 * This deserializer does not know anything about the underlying data and will work with any properly-implemented decoder.
88 * JSON, for example, parses an opening bracket `{` during the `beginStructure` call, checks that the next key
89 * after this bracket is `stringValue` (using the descriptor), returns the value after the colon as string value
90 * and parses closing bracket `}` during the `endStructure`.
91 * XML would do roughly the same, but with different separators and parsing structures, while ProtoBuf
92 * machinery could be completely different.
93 * In any case, all these parsing details are encapsulated by a decoder.
94 *
95 * ### Decoder implementation
96 *
97 * While being strictly typed, an underlying format can transform actual types in the way it wants.
98 * For example, a format can support only string types and encode/decode all primitives in a string form:
99 * ```
100 * StringFormatDecoder : Decoder {
101 *
102 * ...
103 * override fun decodeDouble(): Double = decodeString().toDouble()
104 * override fun decodeInt(): Int = decodeString().toInt()
105 * ...
106 * }
107 * ```
108 *
109 * ### Not stable for inheritance
110 *
111 * `Decoder` interface is not stable for inheritance in 3rd-party libraries, as new methods
112 * might be added to this interface or contracts of the existing methods can be changed.
113 */
114 public interface Decoder {
115 /**
116 * Context of the current serialization process, including contextual and polymorphic serialization and,
117 * potentially, a format-specific configuration.
118 */
119 public val serializersModule: SerializersModule
120
121 /**
122 * Returns `true` if the current value in decoder is not null, false otherwise.
123 * This method is usually used to decode potentially nullable data:
124 * ```
125 * // Could be String? deserialize() method
126 * public fun deserialize(decoder: Decoder): String? {
127 * if (decoder.decodeNotNullMark()) {
128 * return decoder.decodeString()
129 * } else {
130 * return decoder.decodeNull()
131 * }
132 * }
133 * ```
134 */
135 @ExperimentalSerializationApi
decodeNotNullMarknull136 public fun decodeNotNullMark(): Boolean
137
138 /**
139 * Decodes the `null` value and returns it.
140 *
141 * It is expected that `decodeNotNullMark` was called
142 * prior to `decodeNull` invocation and the case when it returned `true` was handled.
143 */
144 @ExperimentalSerializationApi
145 public fun decodeNull(): Nothing?
146
147 /**
148 * Decodes a boolean value.
149 * Corresponding kind is [PrimitiveKind.BOOLEAN].
150 */
151 public fun decodeBoolean(): Boolean
152
153 /**
154 * Decodes a single byte value.
155 * Corresponding kind is [PrimitiveKind.BYTE].
156 */
157 public fun decodeByte(): Byte
158
159 /**
160 * Decodes a 16-bit short value.
161 * Corresponding kind is [PrimitiveKind.SHORT].
162 */
163 public fun decodeShort(): Short
164
165 /**
166 * Decodes a 16-bit unicode character value.
167 * Corresponding kind is [PrimitiveKind.CHAR].
168 */
169 public fun decodeChar(): Char
170
171 /**
172 * Decodes a 32-bit integer value.
173 * Corresponding kind is [PrimitiveKind.INT].
174 */
175 public fun decodeInt(): Int
176
177 /**
178 * Decodes a 64-bit integer value.
179 * Corresponding kind is [PrimitiveKind.LONG].
180 */
181 public fun decodeLong(): Long
182
183 /**
184 * Decodes a 32-bit IEEE 754 floating point value.
185 * Corresponding kind is [PrimitiveKind.FLOAT].
186 */
187 public fun decodeFloat(): Float
188
189 /**
190 * Decodes a 64-bit IEEE 754 floating point value.
191 * Corresponding kind is [PrimitiveKind.DOUBLE].
192 */
193 public fun decodeDouble(): Double
194
195 /**
196 * Decodes a string value.
197 * Corresponding kind is [PrimitiveKind.STRING].
198 */
199 public fun decodeString(): String
200
201 /**
202 * Decodes a enum value and returns its index in [enumDescriptor] elements collection.
203 * Corresponding kind is [SerialKind.ENUM].
204 *
205 * E.g. for the enum `enum class Letters { A, B, C, D }` and
206 * underlying input "C", [decodeEnum] method should return `2` as a result.
207 *
208 * This method does not imply any restrictions on the input format,
209 * the format is free to store the enum by its name, index, ordinal or any other enum representation.
210 */
211 public fun decodeEnum(enumDescriptor: SerialDescriptor): Int
212
213 /**
214 * Returns [Decoder] for decoding an underlying type of a value class in an inline manner.
215 * [descriptor] describes a target value class.
216 *
217 * Namely, for the `@Serializable @JvmInline value class MyInt(val my: Int)`, the following sequence is used:
218 * ```
219 * thisDecoder.decodeInline(MyInt.serializer().descriptor).decodeInt()
220 * ```
221 *
222 * Current decoder may return any other instance of [Decoder] class, depending on the provided [descriptor].
223 * For example, when this function is called on `Json` decoder with
224 * `UInt.serializer().descriptor`, the returned decoder is able to decode unsigned integers.
225 *
226 * Note that this function returns [Decoder] instead of the [CompositeDecoder]
227 * because value classes always have the single property.
228 *
229 * Calling [Decoder.beginStructure] on returned instance leads to an unspecified behavior and, in general, is prohibited.
230 */
231 public fun decodeInline(descriptor: SerialDescriptor): Decoder
232
233 /**
234 * Decodes the beginning of the nested structure in a serialized form
235 * and returns [CompositeDecoder] responsible for decoding this very structure.
236 *
237 * Typically, classes, collections and maps are represented as a nested structure in a serialized form.
238 * E.g. the following JSON
239 * ```
240 * {
241 * "a": 2,
242 * "b": { "nested": "c" }
243 * "c": [1, 2, 3],
244 * "d": null
245 * }
246 * ```
247 * has three nested structures: the very beginning of the data, "b" value and "c" value.
248 */
249 public fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder
250
251 /**
252 * Decodes the value of type [T] by delegating the decoding process to the given [deserializer].
253 * For example, `decodeInt` call us equivalent to delegating integer decoding to [Int.serializer][Int.Companion.serializer]:
254 * `decodeSerializableValue(IntSerializer)`
255 */
256 public fun <T : Any?> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T =
257 deserializer.deserialize(this)
258
259 /**
260 * Decodes the nullable value of type [T] by delegating the decoding process to the given [deserializer].
261 */
262 @ExperimentalSerializationApi
263 public fun <T : Any> decodeNullableSerializableValue(deserializer: DeserializationStrategy<T?>): T? = decodeIfNullable(deserializer) {
264 decodeSerializableValue(deserializer)
265 }
266 }
267
268 @OptIn(ExperimentalSerializationApi::class)
decodeIfNullablenull269 internal inline fun <T : Any> Decoder.decodeIfNullable(deserializer: DeserializationStrategy<T?>, block: () -> T?): T? {
270 val isNullabilitySupported = deserializer.descriptor.isNullable
271 return if (isNullabilitySupported || decodeNotNullMark()) block() else decodeNull()
272 }
273
274 /**
275 * [CompositeDecoder] is a part of decoding process that is bound to a particular structured part of
276 * the serialized form, described by the serial descriptor passed to [Decoder.beginStructure].
277 *
278 * Typically, for unordered data, [CompositeDecoder] is used by a serializer withing a [decodeElementIndex]-based
279 * loop that decodes all the required data one-by-one in any order and then terminates by calling [endStructure].
280 * Please refer to [decodeElementIndex] for example of such loop.
281 *
282 * All `decode*` methods have `index` and `serialDescriptor` parameters with a strict semantics and constraints:
283 * * `descriptor` argument is always the same as one used in [Decoder.beginStructure].
284 * * `index` of the element being decoded. For [sequential][decodeSequentially] decoding, it is always a monotonic
285 * sequence from `0` to `descriptor.elementsCount` and for indexing-loop it is always an index that [decodeElementIndex]
286 * has returned from the last call.
287 *
288 * The symmetric interface for the serialization process is [CompositeEncoder].
289 *
290 * ### Not stable for inheritance
291 *
292 * `CompositeDecoder` interface is not stable for inheritance in 3rd party libraries, as new methods
293 * might be added to this interface or contracts of the existing methods can be changed.
294 */
295 public interface CompositeDecoder {
296
297 /**
298 * Results of [decodeElementIndex] used for decoding control flow.
299 */
300 public companion object {
301 /**
302 * Value returned by [decodeElementIndex] when the underlying input has no more data in the current structure.
303 * When this value is returned, no methods of the decoder should be called but [endStructure].
304 */
305 public const val DECODE_DONE: Int = -1
306
307 /**
308 * Value returned by [decodeElementIndex] when the format encountered an unknown element
309 * (expected neither by the structure of serial descriptor, nor by the format itself).
310 */
311 public const val UNKNOWN_NAME: Int = -3
312 }
313
314 /**
315 * Context of the current decoding process, including contextual and polymorphic serialization and,
316 * potentially, a format-specific configuration.
317 */
318 public val serializersModule: SerializersModule
319
320 /**
321 * Denotes the end of the structure associated with current decoder.
322 * For example, composite decoder of JSON format will expect (and parse)
323 * a closing bracket in the underlying input.
324 */
endStructurenull325 public fun endStructure(descriptor: SerialDescriptor)
326
327 /**
328 * Checks whether the current decoder supports strictly ordered decoding of the data
329 * without calling to [decodeElementIndex].
330 * If the method returns `true`, the caller might skip [decodeElementIndex] calls
331 * and start invoking `decode*Element` directly, incrementing the index of the element one by one.
332 * This method can be called by serializers (either generated or user-defined) as a performance optimization,
333 * but there is no guarantee that the method will be ever called. Practically, it means that implementations
334 * that may benefit from sequential decoding should also support a regular [decodeElementIndex]-based decoding as well.
335 *
336 * Example of usage:
337 * ```
338 * class MyPair(i: Int, d: Double)
339 *
340 * object MyPairSerializer : KSerializer<MyPair> {
341 * // ... other methods omitted
342 *
343 * fun deserialize(decoder: Decoder): MyPair {
344 * val composite = decoder.beginStructure(descriptor)
345 * if (composite.decodeSequentially()) {
346 * val i = composite.decodeIntElement(descriptor, index = 0) // Mind the sequential indexing
347 * val d = composite.decodeIntElement(descriptor, index = 1)
348 * composite.endStructure(descriptor)
349 * return MyPair(i, d)
350 * } else {
351 * // Fallback to `decodeElementIndex` loop, refer to its documentation for details
352 * }
353 * }
354 * }
355 * ```
356 * This example is a rough equivalent of what serialization plugin generates for serializable pair class.
357 *
358 * Sequential decoding is a performance optimization for formats with strictly ordered schema,
359 * usually binary ones. Regular formats such as JSON or ProtoBuf cannot use this optimization,
360 * because e.g. in the latter example, the same data can be represented both as
361 * `{"i": 1, "d": 1.0}`"` and `{"d": 1.0, "i": 1}` (thus, unordered).
362 */
363 @ExperimentalSerializationApi
364 public fun decodeSequentially(): Boolean = false
365
366 /**
367 * Decodes the index of the next element to be decoded.
368 * Index represents a position of the current element in the serial descriptor element that can be found
369 * with [SerialDescriptor.getElementIndex].
370 *
371 * If this method returns non-negative index, the caller should call one of the `decode*Element` methods
372 * with a resulting index.
373 * Apart from positive values, this method can return [DECODE_DONE] to indicate that no more elements
374 * are left or [UNKNOWN_NAME] to indicate that symbol with an unknown name was encountered.
375 *
376 * Example of usage:
377 * ```
378 * class MyPair(i: Int, d: Double)
379 *
380 * object MyPairSerializer : KSerializer<MyPair> {
381 * // ... other methods omitted
382 *
383 * fun deserialize(decoder: Decoder): MyPair {
384 * val composite = decoder.beginStructure(descriptor)
385 * var i: Int? = null
386 * var d: Double? = null
387 * while (true) {
388 * when (val index = composite.decodeElementIndex(descriptor)) {
389 * 0 -> i = composite.decodeIntElement(descriptor, 0)
390 * 1 -> d = composite.decodeDoubleElement(descriptor, 1)
391 * DECODE_DONE -> break // Input is over
392 * else -> error("Unexpected index: $index)
393 * }
394 * }
395 * composite.endStructure(descriptor)
396 * require(i != null && d != null)
397 * return MyPair(i, d)
398 * }
399 * }
400 * ```
401 * This example is a rough equivalent of what serialization plugin generates for serializable pair class.
402 *
403 * The need in such a loop comes from unstructured nature of most serialization formats.
404 * For example, JSON for the following input `{"d": 2.0, "i": 1}`, will first read `d` key with index `1`
405 * and only after `i` with the index `0`.
406 *
407 * A potential implementation of this method for JSON format can be the following:
408 * ```
409 * fun decodeElementIndex(descriptor: SerialDescriptor): Int {
410 * // Ignore arrays
411 * val nextKey: String? = myStringJsonParser.nextKey()
412 * if (nextKey == null) return DECODE_DONE
413 * return descriptor.getElementIndex(nextKey) // getElementIndex can return UNKNOWN_NAME
414 * }
415 * ```
416 *
417 * If [decodeSequentially] returns `true`, the caller might skip calling this method.
418 */
419 public fun decodeElementIndex(descriptor: SerialDescriptor): Int
420
421 /**
422 * Method to decode collection size that may be called before the collection decoding.
423 * Collection type includes [Collection], [Map] and [Array] (including primitive arrays).
424 * Method can return `-1` if the size is not known in advance, though for [sequential decoding][decodeSequentially]
425 * knowing precise size is a mandatory requirement.
426 */
427 public fun decodeCollectionSize(descriptor: SerialDescriptor): Int = -1
428
429 /**
430 * Decodes a boolean value from the underlying input.
431 * The resulting value is associated with the [descriptor] element at the given [index].
432 * The element at the given index should have [PrimitiveKind.BOOLEAN] kind.
433 */
434 public fun decodeBooleanElement(descriptor: SerialDescriptor, index: Int): Boolean
435
436 /**
437 * Decodes a single byte value from the underlying input.
438 * The resulting value is associated with the [descriptor] element at the given [index].
439 * The element at the given index should have [PrimitiveKind.BYTE] kind.
440 */
441 public fun decodeByteElement(descriptor: SerialDescriptor, index: Int): Byte
442
443 /**
444 * Decodes a 16-bit unicode character value from the underlying input.
445 * The resulting value is associated with the [descriptor] element at the given [index].
446 * The element at the given index should have [PrimitiveKind.CHAR] kind.
447 */
448 public fun decodeCharElement(descriptor: SerialDescriptor, index: Int): Char
449
450 /**
451 * Decodes a 16-bit short value from the underlying input.
452 * The resulting value is associated with the [descriptor] element at the given [index].
453 * The element at the given index should have [PrimitiveKind.SHORT] kind.
454 */
455 public fun decodeShortElement(descriptor: SerialDescriptor, index: Int): Short
456
457 /**
458 * Decodes a 32-bit integer value from the underlying input.
459 * The resulting value is associated with the [descriptor] element at the given [index].
460 * The element at the given index should have [PrimitiveKind.INT] kind.
461 */
462 public fun decodeIntElement(descriptor: SerialDescriptor, index: Int): Int
463
464 /**
465 * Decodes a 64-bit integer value from the underlying input.
466 * The resulting value is associated with the [descriptor] element at the given [index].
467 * The element at the given index should have [PrimitiveKind.LONG] kind.
468 */
469 public fun decodeLongElement(descriptor: SerialDescriptor, index: Int): Long
470
471 /**
472 * Decodes a 32-bit IEEE 754 floating point value from the underlying input.
473 * The resulting value is associated with the [descriptor] element at the given [index].
474 * The element at the given index should have [PrimitiveKind.FLOAT] kind.
475 */
476 public fun decodeFloatElement(descriptor: SerialDescriptor, index: Int): Float
477
478 /**
479 * Decodes a 64-bit IEEE 754 floating point value from the underlying input.
480 * The resulting value is associated with the [descriptor] element at the given [index].
481 * The element at the given index should have [PrimitiveKind.DOUBLE] kind.
482 */
483 public fun decodeDoubleElement(descriptor: SerialDescriptor, index: Int): Double
484
485 /**
486 * Decodes a string value from the underlying input.
487 * The resulting value is associated with the [descriptor] element at the given [index].
488 * The element at the given index should have [PrimitiveKind.STRING] kind.
489 */
490 public fun decodeStringElement(descriptor: SerialDescriptor, index: Int): String
491
492 /**
493 * Returns [Decoder] for decoding an underlying type of a value class in an inline manner.
494 * Serializable value class is described by the [child descriptor][SerialDescriptor.getElementDescriptor]
495 * of given [descriptor] at [index].
496 *
497 * Namely, for the `@Serializable @JvmInline value class MyInt(val my: Int)`,
498 * and `@Serializable class MyData(val myInt: MyInt)` the following sequence is used:
499 * ```
500 * thisDecoder.decodeInlineElement(MyData.serializer().descriptor, 0).decodeInt()
501 * ```
502 *
503 * This method provides an opportunity for the optimization to avoid boxing of a carried value
504 * and its invocation should be equivalent to the following:
505 * ```
506 * thisDecoder.decodeSerializableElement(MyData.serializer.descriptor, 0, MyInt.serializer())
507 * ```
508 *
509 * Current decoder may return any other instance of [Decoder] class, depending on the provided descriptor.
510 * For example, when this function is called on `Json` decoder with descriptor that has
511 * `UInt.serializer().descriptor` at the given [index], the returned decoder is able
512 * to decode unsigned integers.
513 *
514 * Note that this function returns [Decoder] instead of the [CompositeDecoder]
515 * because value classes always have the single property.
516 * Calling [Decoder.beginStructure] on returned instance leads to an unspecified behavior and, in general, is prohibited.
517 *
518 * @see Decoder.decodeInline
519 * @see SerialDescriptor.getElementDescriptor
520 */
521 public fun decodeInlineElement(
522 descriptor: SerialDescriptor,
523 index: Int
524 ): Decoder
525
526 /**
527 * Decodes value of the type [T] with the given [deserializer].
528 *
529 * Implementations of [CompositeDecoder] may use their format-specific deserializers
530 * for particular data types, e.g. handle [ByteArray] specifically if format is binary.
531 *
532 * If value at given [index] was already decoded with previous [decodeSerializableElement] call with the same index,
533 * [previousValue] would contain a previously decoded value.
534 * This parameter can be used to aggregate multiple values of the given property to the only one.
535 * Implementation can safely ignore it and return a new value, effectively using 'the last one wins' strategy,
536 * or apply format-specific aggregating strategies, e.g. appending scattered Protobuf lists to a single one.
537 */
538 public fun <T : Any?> decodeSerializableElement(
539 descriptor: SerialDescriptor,
540 index: Int,
541 deserializer: DeserializationStrategy<T>,
542 previousValue: T? = null
543 ): T
544
545 /**
546 * Decodes nullable value of the type [T] with the given [deserializer].
547 *
548 * If value at given [index] was already decoded with previous [decodeSerializableElement] call with the same index,
549 * [previousValue] would contain a previously decoded value.
550 * This parameter can be used to aggregate multiple values of the given property to the only one.
551 * Implementation can safely ignore it and return a new value, efficiently using 'the last one wins' strategy,
552 * or apply format-specific aggregating strategies, e.g. appending scattered Protobuf lists to a single one.
553 */
554 @ExperimentalSerializationApi
555 public fun <T : Any> decodeNullableSerializableElement(
556 descriptor: SerialDescriptor,
557 index: Int,
558 deserializer: DeserializationStrategy<T?>,
559 previousValue: T? = null
560 ): T?
561 }
562
563 /**
564 * Begins a structure, decodes it using the given [block], ends it and returns decoded element.
565 */
566 public inline fun <T> Decoder.decodeStructure(
567 descriptor: SerialDescriptor,
568 crossinline block: CompositeDecoder.() -> T
569 ): T {
570 val composite = beginStructure(descriptor)
571 val result = composite.block()
572 composite.endStructure(descriptor)
573 return result
574 }
575