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