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

commonMain.utils.io.output.kt Maven / Gradle / Ivy

There is a newer version: 2.16.0
Show newest version
/*
 * Copyright 2019-2021 Mamoe Technologies and contributors.
 *
 * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
 * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
 *
 * https://github.com/mamoe/mirai/blob/dev/LICENSE
 */

@file:Suppress("EXPERIMENTAL_API_USAGE", "NOTHING_TO_INLINE")
@file:JvmMultifileClass
@file:JvmName("Utils")

package net.mamoe.mirai.internal.utils.io

import io.ktor.utils.io.streams.*
import kotlinx.io.core.*
import kotlinx.io.streams.outputStream
import net.mamoe.mirai.internal.utils.coerceAtMostOrFail
import net.mamoe.mirai.internal.utils.crypto.TEA
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.withUse

internal fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) {
    if (array.size <= maxLength) {
        writeShort(array.size.toShort())
        writeFully(array)
    } else {
        writeShort(maxLength.toShort())
        repeat(maxLength) {
            writeByte(array[it])
        }
    }
}

internal fun BytePacketBuilder.writeResource(
    resource: ExternalResource,
    close: Boolean = false,
): Long = resource.inputStream().withUse { copyTo(outputStream()) }.also {
    if (close) resource.close()
}

internal fun io.ktor.utils.io.core.BytePacketBuilder.writeResource(
    resource: ExternalResource,
): Long = resource.inputStream().withUse { copyTo(outputStream()) }

internal inline fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray): Int {
    this.writeShort(byteArray.size.toShort())
    this.writeFully(byteArray)
    return byteArray.size
}

internal inline fun BytePacketBuilder.writeIntLVPacket(
    tag: UByte? = null,
    lengthOffset: ((Long) -> Long) = { it },
    builder: BytePacketBuilder.() -> Unit,
): Int =
    BytePacketBuilder().apply(builder).build().use {
        if (tag != null) writeUByte(tag)
        val length = lengthOffset.invoke(it.remaining).coerceAtMostOrFail(0xFFFFFFFFL)
        writeInt(length.toInt())
        writePacket(it)
        return length.toInt()
    }

internal inline fun BytePacketBuilder.writeShortLVPacket(
    tag: UByte? = null,
    lengthOffset: ((Long) -> Long) = { it },
    builder: BytePacketBuilder.() -> Unit,
): Int =
    BytePacketBuilder().apply(builder).build().use {
        if (tag != null) writeUByte(tag)
        val length = lengthOffset.invoke(it.remaining).coerceAtMostOrFail(0xFFFFFFFFL)
        writeUShort(length.toUShort())
        writePacket(it)
        return length.toInt()
    }

internal inline fun BytePacketBuilder.writeShortLVString(str: String) = writeShortLVByteArray(str.toByteArray())

internal fun BytePacketBuilder.writeHex(uHex: String) {
    uHex.split(" ").forEach {
        if (it.isNotBlank()) {
            writeUByte(it.toUByte(16))
        }
    }
}


internal inline fun BytePacketBuilder.encryptAndWrite(key: ByteArray, encoder: BytePacketBuilder.() -> Unit) =
    TEA.encrypt(BytePacketBuilder().apply(encoder).build(), key) { decrypted -> writeFully(decrypted) }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy