All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.maryk.core.protobuf.ProtoBuf.kt Maven / Gradle / Ivy

package maryk.core.protobuf

import maryk.core.extensions.bytes.SIGN_BYTE
import maryk.core.extensions.bytes.ZERO_BYTE
import maryk.core.extensions.bytes.calculateVarIntWithExtraInfoByteSize
import maryk.core.extensions.bytes.initIntByVar
import maryk.core.extensions.bytes.initUIntByVarWithExtraInfo
import maryk.core.extensions.bytes.writeVarIntWithExtraInfo
import maryk.core.protobuf.WireType.BIT_32
import maryk.core.protobuf.WireType.BIT_64
import maryk.core.protobuf.WireType.END_GROUP
import maryk.core.protobuf.WireType.LENGTH_DELIMITED
import maryk.core.protobuf.WireType.START_GROUP
import maryk.core.protobuf.WireType.VAR_INT
import kotlin.experimental.and

internal object ProtoBuf {
    /** Write the key for ProtoBuf field */
    internal fun writeKey(tag: UInt, wireType: WireType, writer: (byte: Byte) -> Unit) {
        tag.writeVarIntWithExtraInfo(wireType.type, writer)
    }

    /** Reads the key of a ProtoBuf based field from [reader] into a ProtoBufKey */
    internal fun readKey(reader: () -> Byte): ProtoBufKey {
        return initUIntByVarWithExtraInfo(reader) { result, wireByte ->
            ProtoBufKey(result, wireTypeOf(wireByte and 0b111))
        }
    }

    /** Skips a field in [reader] by [wireType] */
    internal fun skipField(wireType: Any, reader: () -> Byte) {
        when (wireType) {
            VAR_INT -> {
                var currentByte: Byte
                do {
                    currentByte = reader()
                } while (currentByte and SIGN_BYTE != ZERO_BYTE)
            }
            BIT_64 -> for (it in 0 until 8) {
                reader()
            }
            LENGTH_DELIMITED -> for (it in 0 until initIntByVar(reader)) {
                reader()
            }
            START_GROUP -> {
                while (true) {
                    val key = readKey(reader)
                    if (key.wireType == END_GROUP) {
                        break
                    }
                    skipField(key.wireType, reader)
                }
            }
            END_GROUP -> return
            BIT_32 -> for (it in 0 until 4) {
                reader()
            }
        }
    }

    /**
     * Get length of next value by [wireType] and reading from [reader]
     * It is -1 for varInt or start/end group
     */
    internal fun getLength(wireType: WireType, reader: () -> Byte) = when (wireType) {
        VAR_INT -> -1
        BIT_64 -> 8
        LENGTH_DELIMITED -> initIntByVar(reader)
        START_GROUP -> -1
        END_GROUP -> -1
        BIT_32 -> 4
    }

    /** Calculate the length of the key [tag] */
    internal fun calculateKeyLength(tag: UInt): Int {
        return tag.calculateVarIntWithExtraInfoByteSize()
    }
}

/** Contains the tag and wiretype of the Protobuf key */
internal class ProtoBufKey(val tag: UInt, val wireType: WireType)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy