• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.protobuf.internal
6 
7 import kotlinx.serialization.*
8 import kotlin.jvm.*
9 
10 /*
11  * In ProtoBuf spec, ids from 19000 to 19999 are reserved for protocol use,
12  * thus we are leveraging it here and use 19_500 as a marker no one us allowed to use.
13  * It does not leak to the resulting output.
14  */
15 internal const val MISSING_TAG = 19_500L
16 
17 /**
18  * Tag indicating that now is handling the first element of polymorphic serializer,
19  * which is the serial name that should match the class name.
20  *
21  * In oneof element, such element should be ignored.
22  */
23 internal const val POLYMORPHIC_NAME_TAG: ProtoDesc = 19501
24 
25 
26 internal abstract class ProtobufTaggedBase {
27     private var tagsStack = LongArray(8)
28     @JvmField
29     protected var stackSize = -1
30 
31     protected val currentTag: ProtoDesc
32         get() = tagsStack[stackSize]
33 
34     protected val currentTagOrDefault: ProtoDesc
35         get() = if (stackSize == -1) MISSING_TAG else tagsStack[stackSize]
36 
popTagOrDefaultnull37     protected fun popTagOrDefault(): ProtoDesc = if (stackSize == -1) MISSING_TAG else tagsStack[stackSize--]
38 
39     protected fun pushTag(tag: ProtoDesc) {
40         if (tag == MISSING_TAG) return // Missing tag is never added
41         val idx = ++stackSize
42         if (stackSize >= tagsStack.size) {
43             expand()
44         }
45         tagsStack[idx] = tag
46     }
47 
expandnull48     private fun expand() {
49         tagsStack = tagsStack.copyOf(tagsStack.size * 2)
50     }
51 
popTagnull52     protected fun popTag(): ProtoDesc {
53         if (stackSize >= 0) return tagsStack[stackSize--]
54         // Unreachable
55         throw SerializationException("No tag in stack for requested element")
56     }
57 
tagBlocknull58     protected inline fun <E> tagBlock(tag: ProtoDesc, block: () -> E): E {
59         pushTag(tag)
60         return block()
61     }
62 }
63