Fix unresolved KDoc reference

This commit is contained in:
Him188 2019-11-15 10:41:26 +08:00
parent ee7d3a7e1a
commit 20ea49b090
8 changed files with 111 additions and 136 deletions

View File

@ -174,7 +174,7 @@ inline class Image(inline val id: ImageId) : Message {
* 对于好友, [value] 类似于 `/01ee6426-5ff1-4cf0-8278-e8634d2909ef`, 由服务器返回.
*
* @see ExternalImage.groupImageId 群图片的 [ImageId] 获取
* @see FriendImageIdRequestPacket.Response.imageId 好友图片的 [ImageId] 获取
* @see FriendImageIdRequestPacket.Response.RequireUpload.imageId 好友图片的 [ImageId] 获取
*/
inline class ImageId(inline val value: String)

View File

@ -5,7 +5,9 @@ import kotlinx.io.core.IoBuffer
import kotlinx.io.pool.useInstance
import net.mamoe.mirai.network.protocol.tim.packet.Decrypter
import net.mamoe.mirai.network.protocol.tim.packet.DecrypterByteArray
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.toByteArray
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.experimental.and
import kotlin.experimental.xor
import kotlin.jvm.JvmStatic
@ -30,15 +32,6 @@ fun ByteArray.encryptBy(key: ByteArray, length: Int = this.size): ByteArray = TE
fun ByteArray.encryptBy(key: DecrypterByteArray, length: Int = this.size): ByteArray = TEA.encrypt(this, key.value, sourceLength = length)
/**
* 通过 [String.hexToBytes] [keyHex] 转为 [ByteArray] 后用它解密 [this].
* 将会使用 [HexCache]
*
* @param keyHex 长度至少为 16 bytes
* @throws DecryptionFailedException 解密错误时
*/
fun ByteArray.encryptBy(keyHex: String, length: Int = this.size): ByteArray = encryptBy(keyHex.hexToBytes(withCache = true), length = length)
/**
* [ByteArrayPool] 缓存 [this], 然后使用 [key] 加密.
*
@ -83,15 +76,6 @@ fun ByteArray.decryptBy(key: IoBuffer, length: Int = this.size): ByteArray {
}
}
/**
* 通过 [String.hexToBytes] [keyHex] 转为 [ByteArray] 后用它解密 [this]
* 将会使用 [HexCache]
*
* @param keyHex 长度至少为 16 bytes
* @throws DecryptionFailedException 解密错误时
*/
fun ByteArray.decryptBy(keyHex: String, length: Int = this.size): ByteArray = decryptBy(keyHex.hexToBytes(withCache = true), length = length)
/**
* [ByteArrayPool] 缓存 [this], 然后使用 [key] 解密.
*
@ -106,16 +90,6 @@ fun IoBuffer.decryptBy(key: ByteArray, offset: Int = 0, length: Int = readRemain
}
}
/**
* [ByteArrayPool] 缓存 [this], 然后使用 [keyHex] 解密.
*
* @param keyHex 长度至少为 16
* @throws DecryptionFailedException 解密错误时
*/
fun IoBuffer.decryptBy(keyHex: String, offset: Int = 0, length: Int = readRemaining - offset): ByteArray =
decryptBy(keyHex.hexToBytes(withCache = true), offset = offset, length = length)
// endregion
// region ByteReadPacket extension
@ -126,8 +100,6 @@ fun ByteReadPacket.decryptBy(key: IoBuffer): ByteReadPacket = decryptAsByteArray
fun ByteReadPacket.decryptBy(key: Decrypter): ByteReadPacket = key.decrypt(this)
fun ByteReadPacket.decryptBy(keyHex: String): ByteReadPacket = decryptBy(keyHex.hexToBytes())
inline fun <R> ByteReadPacket.decryptAsByteArray(key: ByteArray, consumer: (ByteArray) -> R): R =
ByteArrayPool.useInstance {
val length = remaining.toInt()
@ -135,9 +107,6 @@ inline fun <R> ByteReadPacket.decryptAsByteArray(key: ByteArray, consumer: (Byte
consumer(it.decryptBy(key, length))
}.also { close() }
inline fun <R> ByteReadPacket.decryptAsByteArray(keyHex: String, consumer: (ByteArray) -> R): R =
this.decryptAsByteArray(keyHex.hexToBytes(), consumer)
inline fun <R> ByteReadPacket.decryptAsByteArray(key: IoBuffer, consumer: (ByteArray) -> R): R =
ByteArrayPool.useInstance {
val length = remaining.toInt()

View File

@ -1,11 +1,12 @@
@file:Suppress("ObjectPropertyName", "MayBeConstant", "NonAsciiCharacters", "SpellCheckingInspection", "unused")
package net.mamoe.mirai.utils.io
package net.mamoe.mirai.utils.internal
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.math.max
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
/**
* 匹配已知 hex 常量并格式化后打印到控制台.
@ -19,7 +20,7 @@ internal fun String.printColorize(ignoreUntilFirstConst: Boolean): String = with
*
* 低效率, 仅调试使用.
*/
internal fun printCompareHex(hex1s: String, hex2s: String): String = with(HexComparator) { compare(hex1s, hex2s) }
fun printCompareHex(hex1s: String, hex2s: String): String = with(HexComparator) { compare(hex1s.toUpperCase(), hex2s.toUpperCase()) }
data class NamedHexElement(
val name: String,
@ -35,8 +36,8 @@ private fun LinkedHashSet<NamedHexElement>.initConstFileds() {
TIMProtocol,
PacketIds
).forEach { obj ->
obj::class.members.filterIsInstance<KProperty<*>>().forEach { property ->
add(NamedHexElement(property.name, property.getter.call().toString()))
obj::class.members.filterIsInstance<KProperty0<*>>().forEach { property ->
property.get()?.let { add(NamedHexElement(property.name, it.toString())) }
}
}
}
@ -107,9 +108,14 @@ private object HexComparator {
private class Match internal constructor(val range: IntRange, val constName: String)
init {
TIMProtocol::class.members.filterIsInstance<KProperty<*>>().forEach {
for (match in match(hex, it.getter.call().toString())) {
matches.add(Match(match, it.getter.call().toString()))
CONST_FIELDS.forEach { (name, value) ->
for (match in match(hex, value)) {
matches.add(Match(match, name))
}
}
TIMProtocol::class.members.filterIsInstance<KProperty0<*>>().mapNotNull { it()?.toString() }.forEach {
for (match in match(hex, it)) {
matches.add(Match(match, it))
}
}
}
@ -118,10 +124,10 @@ private object HexComparator {
val CONST_FIELDS: Set<NamedHexElement> = linkedSetOf<NamedHexElement>().apply { initConstFileds() }
}
private fun match(hex: String, field: String): Set<IntRange> {
private fun match(hex: String, value: String): Set<IntRange> {
val constValue: String
try {
constValue = field.trim { it <= ' ' }
constValue = value.trim { it <= ' ' }
if (constValue.length / 3 <= 3) {//Minimum numbers of const hex bytes
return linkedSetOf()
}

View File

@ -3,6 +3,8 @@ package net.mamoe.mirai.utils.io
import kotlinx.io.core.*
import net.mamoe.mirai.utils.DefaultLogger
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.internal.printColorize
import net.mamoe.mirai.utils.internal.printCompareHex
internal object DebugLogger : MiraiLogger by DefaultLogger("Packet Debug")
@ -62,7 +64,7 @@ internal fun BytePacketBuilder.debugPrintThis(name: String = "") {
}
internal fun String.printStringFromHex() {
println(this.hexToBytes().stringOfWitch())
println(this.hexToBytes().encodeToString())
}
internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstConst: Boolean = false, compareTo: String? = null) {

View File

@ -3,6 +3,8 @@
package net.mamoe.mirai.utils.io
import kotlinx.io.core.*
import kotlinx.io.pool.useInstance
import kotlin.jvm.JvmName
fun ByteReadPacket.readRemainingBytes(
@ -23,8 +25,12 @@ fun Input.readIP(): String = buildString(4 + 3) {
}
}
fun Input.readUVarIntLVString(): String = String(this.readUVarIntByteArray())
fun Input.readUShortLVString(): String = String(this.readUShortLVByteArray())
fun Input.readUVarIntByteArray(): ByteArray = this.readBytes(this.readUVarInt().toInt())
fun Input.readUShortLVByteArray(): ByteArray = this.readBytes(this.readUShort().toInt())
private inline fun <R> inline(block: () -> R): R = block()
@ -63,7 +69,33 @@ fun Input.readTLVMap(expectingEOF: Boolean = false, tagSize: Int = 1): MutableMa
fun Map<*, ByteArray>.printTLVMap(name: String) =
debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() })
fun Input.readString(length: Number): String = String(this.readBytes(length.toInt()))
fun Input.readString(length: Int): String = String(this.readBytes(length))
fun Input.readString(length: Long): String = String(this.readBytes(length.toInt()))
fun Input.readString(length: Short): String = String(this.readBytes(length.toInt()))
fun Input.readString(length: UShort): String = String(this.readBytes(length.toInt()))
fun Input.readString(length: Byte): String = String(this.readBytes(length.toInt()))
fun Input.readStringUntil(stopSignalExclude: UByte, expectingEOF: Boolean = false): String = readStringUntil(stopSignalExclude.toByte(), expectingEOF)
// TODO 应标记 JvmSynthetic 但 kotlin 有bug
@JvmName("readStringUntil0")
fun Input.readStringUntil(stopSignalExclude: Byte, expectingEOF: Boolean = false): String {
ByteArrayPool.useInstance {
var count = 0
val buffer = byteArrayOf(1)
while (readAvailable(buffer, 1) == 1) {
if (buffer[0] == stopSignalExclude) {
return buffer.encodeToString()
}
it[count++] = buffer[0]
}
if (!expectingEOF) {
throw EOFException("Early EOF")
}
return buffer.encodeToString()
}
}
private const val TRUE_BYTE_VALUE: Byte = 1
fun Input.readBoolean(): Boolean = this.readByte() == TRUE_BYTE_VALUE

View File

@ -29,38 +29,33 @@ fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray) {
this.writeFully(byteArray)
}
fun BytePacketBuilder.writeShortLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long)? = null, builder: BytePacketBuilder.() -> Unit) =
with(BytePacketBuilder().apply(builder).build()) {
if (tag != null) {
writeUByte(tag)
}
writeUShort((lengthOffset?.invoke(remaining) ?: remaining).coerceAtMostOrFail(0xFFFFL).toUShort())
writePacket(this)
this.release()
BytePacketBuilder().apply(builder).build().use {
if (tag != null) writeUByte(tag)
writeUShort((lengthOffset?.invoke(it.remaining) ?: it.remaining).coerceAtMostOrFail(0xFFFFL).toUShort())
writePacket(it)
}
fun BytePacketBuilder.writeUVarintLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long)? = null, builder: BytePacketBuilder.() -> Unit) =
with(BytePacketBuilder().apply(builder).build()) {
if (tag != null) {
writeUByte(tag)
}
writeUVarInt((lengthOffset?.invoke(remaining) ?: remaining).coerceAtMostOrFail(0xFFFFL))
writePacket(this)
this.release()
fun BytePacketBuilder.writeUVarIntLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long)? = null, builder: BytePacketBuilder.() -> Unit) =
BytePacketBuilder().apply(builder).build().use {
if (tag != null) writeUByte(tag)
writeUVarInt((lengthOffset?.invoke(it.remaining) ?: it.remaining).coerceAtMostOrFail(0xFFFFL))
writePacket(it)
}
@Suppress("DEPRECATION")
fun BytePacketBuilder.writeShortLVString(str: String) = this.writeShortLVByteArray(str.toByteArray())
@Suppress("DEPRECATION")
fun BytePacketBuilder.writeLVHex(hex: String) = this.writeShortLVByteArray(hex.hexToBytes())
fun BytePacketBuilder.writeShortLVString(str: String) = writeShortLVByteArray(str.toByteArray())
fun BytePacketBuilder.writeIP(ip: String) = writeFully(ip.trim().split(".").map { it.toUByte() }.toUByteArray())
fun BytePacketBuilder.writeTime() = this.writeInt(currentTime.toInt())
fun BytePacketBuilder.writeHex(uHex: String) = this.writeFully(uHex.hexToUBytes())
fun BytePacketBuilder.writeHex(uHex: String) {
uHex.split(" ").forEach {
if (it.isNotBlank()) {
writeUByte(it.toUByte(16))
}
}
}
fun BytePacketBuilder.writeTLV(tag: UByte, values: UByteArray) {
writeUByte(tag)
@ -81,6 +76,11 @@ fun BytePacketBuilder.writeTHex(tag: UByte, uHex: String) {
fun BytePacketBuilder.writeTV(tagValue: UShort) = writeUShort(tagValue)
fun BytePacketBuilder.writeTV(tag: UByte, value: UByte) {
writeUByte(tag)
writeUByte(value)
}
fun BytePacketBuilder.writeTUbyte(tag: UByte, value: UByte) {
this.writeUByte(tag)
this.writeUByte(value)
@ -124,7 +124,7 @@ fun BytePacketBuilder.writeTLV0006(qq: UInt, password: String, loginTime: Int, l
writeRandom(4)
writeHex("00 02")
writeQQ(qq)
writeHex(TIMProtocol.constantData2)
writeFully(TIMProtocol.constantData2)
writeHex("00 00 01")
writeFully(firstMD5)
@ -151,5 +151,5 @@ fun BytePacketBuilder.writeDeviceName(random: Boolean) {
}
this.writeShort((deviceName.length + 2).toShort())
this.writeShort(deviceName.length.toShort())
this.writeStringUtf8(deviceName)//TODO TEST?
this.writeStringUtf8(deviceName)
}

View File

@ -5,7 +5,6 @@ package net.mamoe.mirai.utils.io
import kotlinx.io.core.IoBuffer
import kotlinx.io.core.writeFully
import kotlinx.io.pool.ObjectPool
import kotlin.jvm.Synchronized
import kotlin.random.Random
import kotlin.random.nextInt
@ -75,9 +74,8 @@ fun Byte.toUHexString(): String = this.toUByte().toString(16).toUpperCase().let
/**
* 将无符号 Hex 转为 [ByteArray], 有根据 hex [hashCode] 建立的缓存.
*/
fun String.hexToBytes(withCache: Boolean = true): ByteArray =
if (withCache) HexCache.getCacheOrConvert(this)
else this.split(" ")
fun String.hexToBytes(): ByteArray =
this.split(" ")
.filterNot { it.isEmpty() }
.map { s -> s.toUByte(16).toByte() }
.toByteArray()
@ -85,9 +83,8 @@ fun String.hexToBytes(withCache: Boolean = true): ByteArray =
/**
* 将无符号 Hex 转为 [UByteArray], 有根据 hex [hashCode] 建立的缓存.
*/
fun String.hexToUBytes(withCache: Boolean = true): UByteArray =
if (withCache) HexCache.getUCacheOrConvert(this)
else this.split(" ")
fun String.hexToUBytes(): UByteArray =
this.split(" ")
.filterNot { it.isEmpty() }
.map { s -> s.toUByte(16) }
.toUByteArray()
@ -129,38 +126,4 @@ fun ByteArray.toUInt(): UInt =
* [IoBuffer.Pool] [borrow][ObjectPool.borrow] 一个 [IoBuffer] 然后将 [this] 写入.
* 注意回收 ([ObjectPool.recycle])
*/
fun ByteArray.toIoBuffer(): IoBuffer = IoBuffer.Pool.borrow().let { it.writeFully(this); it }
/**
* Hex 转换 [ByteArray] [UByteArray] 缓存.
* [net.mamoe.mirai.network.protocol.tim.TIMProtocol] hex 常量使用
*/
internal object HexCache {
private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf()
@Synchronized
internal fun getCacheOrConvert(hex: String): ByteArray = hex.hashCode().let { id ->
if (hexToByteArrayCacheMap.containsKey(id)) {
return hexToByteArrayCacheMap[id]!!
} else {
hex.hexToBytes(withCache = false).let {
hexToByteArrayCacheMap[id] = it
return it
}
}
}
private val hexToUByteArrayCacheMap: MutableMap<Int, UByteArray> = mutableMapOf()
@Synchronized
internal fun getUCacheOrConvert(hex: String): UByteArray = hex.hashCode().let { id ->
if (hexToUByteArrayCacheMap.containsKey(id)) {
return hexToUByteArrayCacheMap[id]!!
} else {
hex.hexToUBytes(withCache = false).let {
hexToUByteArrayCacheMap[id] = it
return it
}
}
}
}
fun ByteArray.toIoBuffer(): IoBuffer = IoBuffer.Pool.borrow().let { it.writeFully(this); it }

View File

@ -1,12 +1,13 @@
@file:JvmName("Varint")
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.utils
package net.mamoe.mirai.utils.io
import kotlinx.io.core.BytePacketBuilder
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input
import kotlinx.io.core.Output
import kotlin.experimental.or
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
/**
* Tool class for VarInt or VarLong operations.
@ -17,70 +18,72 @@ import kotlin.jvm.JvmName
* @author lmlstarqaq of Nukkit Project
*/
fun encodeZigZag32(signedInt: Int): Long {
internal fun encodeZigZag32(signedInt: Int): Long {
return (signedInt shl 1 xor (signedInt shr 31)).toLong()
}
//@JvmSynthetic
fun decodeZigZag32(uint: UInt): Int {
@JvmSynthetic
internal fun decodeZigZag32(uint: UInt): Int {
return decodeZigZag32(uint.toLong())
}
fun decodeZigZag32(uint: Long): Int {
internal fun decodeZigZag32(uint: Long): Int {
return (uint shr 1).toInt() xor -(uint and 1).toInt()
}
fun encodeZigZag64(signedLong: Long): Long {
internal fun encodeZigZag64(signedLong: Long): Long {
return signedLong shl 1 xor (signedLong shr 63)
}
fun decodeZigZag64(signedLong: Long): Long {
internal fun decodeZigZag64(signedLong: Long): Long {
return signedLong.ushr(1) xor -(signedLong and 1)
}
fun ByteReadPacket.readVarInt(): Int {
return decodeZigZag32(this.readUnsignedVarInt())
fun Input.readVarInt(): Int {
return decodeZigZag32(this.readUVarInt())
}
fun ByteReadPacket.readUnsignedVarInt(): UInt {
@JvmSynthetic
fun Input.readUVarInt(): UInt {
return read(this, 5).toUInt()
}
fun ByteReadPacket.readVarLong(): Long {
return decodeZigZag64(readUnsignedVarLong().toLong())
fun Input.readVarLong(): Long {
return decodeZigZag64(readUVarLong().toLong())
}
fun ByteReadPacket.readUnsignedVarLong(): ULong {
@JvmSynthetic
fun Input.readUVarLong(): ULong {
return read(this, 10).toULong()
}
fun BytePacketBuilder.writeVarInt(signedInt: Int) {
fun Output.writeVarInt(signedInt: Int) {
this.writeUVarInt(encodeZigZag32(signedInt))
}
fun BytePacketBuilder.writeUVarInt(uint: UInt) {
@JvmSynthetic
fun Output.writeUVarInt(uint: UInt) {
return writeUVarInt(uint.toLong())
}
fun BytePacketBuilder.writeUVarInt(uint: Long) {
fun Output.writeUVarInt(uint: Long) {
this.write0(uint)
}
fun BytePacketBuilder.writeVarLong(signedLong: Long) {
fun Output.writeVarLong(signedLong: Long) {
this.writeUVarLong(encodeZigZag64(signedLong))
}
fun BytePacketBuilder.writeUVarLong(ulong: Long) {
fun Output.writeUVarLong(ulong: Long) {
this.write0(ulong)
}
private fun BytePacketBuilder.write0(long: Long) {
private fun Output.write0(long: Long) {
var value = long
do {
var temp = (value and 127).toByte()
@ -92,7 +95,7 @@ private fun BytePacketBuilder.write0(long: Long) {
} while (value != 0L)
}
private fun read(stream: ByteReadPacket, maxSize: Int): Long {
private fun read(stream: Input, maxSize: Int): Long {
var value: Long = 0
var size = 0
var b = stream.readByte().toInt()