1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-25 13:03:35 +08:00

Make mirai-core-utils multiplatform

This commit is contained in:
Him188 2022-05-17 10:52:12 +01:00
parent da06a19881
commit 924b65ba00
No known key found for this signature in database
GPG Key ID: BA439CDDCF652375
53 changed files with 753 additions and 305 deletions

View File

@ -12,6 +12,9 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
public inline fun <A, reified B> Array<A>.mapToArray(block: (element: A) -> B): Array<B> {
val result = arrayOfNulls<B>(size)
this.forEachIndexed { index, element ->

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -7,9 +7,6 @@
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
import kotlinx.io.pool.DefaultPool

View File

@ -16,6 +16,10 @@ package net.mamoe.mirai.utils
import kotlinx.io.core.ByteReadPacket
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
@JvmOverloads

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -11,6 +11,7 @@ package net.mamoe.mirai.utils
import kotlinx.serialization.Serializable
import net.mamoe.mirai.utils.Either.Companion.fold
import kotlin.jvm.JvmName
import kotlin.reflect.KType
@Suppress("PropertyName")

View File

@ -0,0 +1,17 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import kotlinx.io.errors.IOException
public expect interface Closeable {
@Throws(IOException::class)
public fun close()
}

View File

@ -0,0 +1,13 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
@Suppress("FunctionName")
public expect fun <K : Any, V> ConcurrentHashMap(): MutableMap<K, V>

View File

@ -1,15 +1,17 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.utils
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.locks.SynchronizedObject
import kotlinx.atomicfu.locks.synchronized
import kotlin.reflect.KProperty
public fun <T : Any> computeOnNullMutableProperty(initializer: () -> T): ComputeOnNullMutableProperty<T> =
@ -28,10 +30,11 @@ private class ComputeOnNullMutablePropertyImpl<T : Any>(
private val initializer: () -> T
) : ComputeOnNullMutableProperty<T> {
private val value = atomic<T?>(null)
private val lock = SynchronizedObject()
override tailrec fun get(): T {
return when (val v = this.value.value) {
null -> synchronized(this) {
null -> synchronized(lock) {
if (this.value.value === null) {
val value = this.initializer()
// compiler inserts

View File

@ -14,6 +14,9 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/*
* 类型转换 Utils.
* 这些函数为内部函数, 可能会改变

View File

@ -7,8 +7,8 @@
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MiraiUtils")
@file:JvmName("CoroutineUtils_common")
package net.mamoe.mirai.utils
@ -17,25 +17,15 @@ import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.jvm.JvmName
@Suppress("unused", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "DeprecatedCallableAddReplaceWith")
@Deprecated(
message = "Use runBIO which delegates to `runInterruptible`. " +
"Technically remove suspend call in `block` and remove CoroutineScope parameter usages.",
level = DeprecationLevel.HIDDEN
)
@kotlin.internal.LowPriorityInOverloadResolution
public suspend inline fun <R> runBIO(
noinline block: suspend CoroutineScope.() -> R,
): R = withContext(Dispatchers.IO, block)
public suspend inline fun <R> runBIO(
public expect suspend inline fun <R> runBIO(
noinline block: () -> R,
): R = runInterruptible(context = Dispatchers.IO, block = block)
): R
public suspend inline fun <T, R> T.runBIO(
public expect suspend inline fun <T, R> T.runBIO(
crossinline block: T.() -> R,
): R = runInterruptible(context = Dispatchers.IO, block = { block() })
): R
public inline fun CoroutineScope.launchWithPermit(
semaphore: Semaphore,

View File

@ -11,6 +11,10 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmField
import kotlin.jvm.JvmInline
import kotlin.jvm.JvmName
/**
* Safe union of two types.
*/

View File

@ -11,6 +11,8 @@ package net.mamoe.mirai.utils
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.Synchronized
import kotlin.jvm.Volatile
public open class ExceptionCollector {
@ -50,16 +52,6 @@ public open class ExceptionCollector {
receiver.addSuppressed(e)
}
private fun hash(e: Throwable): Long {
return e.stackTrace.fold(0L) { acc, stackTraceElement ->
acc * 31 + hash(stackTraceElement).toLongUnsigned()
}
}
private fun hash(element: StackTraceElement): Int {
return element.lineNumber.hashCode() xor element.className.hashCode() xor element.methodName.hashCode()
}
public fun collectGet(e: Throwable?): Throwable {
this.collect(e)
return getLast()!!
@ -90,7 +82,8 @@ public open class ExceptionCollector {
@TestOnly // very slow
public fun asSequence(): Sequence<Throwable> {
fun Throwable.itr(): Iterator<Throwable> {
return (sequenceOf(this) + this.suppressed.asSequence().flatMap { it.itr().asSequence() }).iterator()
return (sequenceOf(this) + this.suppressedExceptions.asSequence()
.flatMap { it.itr().asSequence() }).iterator()
}
val last = getLast() ?: return emptySequence()
@ -136,4 +129,6 @@ public inline fun <R> ExceptionCollector.withExceptionCollector(action: Exceptio
collectThrow(e)
}
}
}
}
internal expect fun hash(e: Throwable): Long

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -12,6 +12,9 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
/**
* 文件头和文件类型列表
*/

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -15,9 +15,11 @@
package net.mamoe.mirai.utils
import kotlinx.io.charsets.Charset
import kotlinx.io.charsets.Charsets
import kotlinx.io.core.*
import java.io.File
import kotlin.text.String
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
public val EMPTY_BYTE_ARRAY: ByteArray = ByteArray(0)
@ -132,21 +134,3 @@ public inline fun Input.readString(length: Byte, charset: Charset = Charsets.UTF
public fun Input.readUShortLVString(): String = String(this.readUShortLVByteArray())
public fun Input.readUShortLVByteArray(): ByteArray = this.readBytes(this.readUShort().toInt())
public fun File.createFileIfNotExists() {
if (!this.exists()) {
this.parentFile.mkdirs()
this.createNewFile()
}
}
public fun File.resolveCreateFile(relative: String): File = this.resolve(relative).apply { createFileIfNotExists() }
public fun File.resolveCreateFile(relative: File): File = this.resolve(relative).apply { createFileIfNotExists() }
public fun File.resolveMkdir(relative: String): File = this.resolve(relative).apply { mkdirs() }
public fun File.resolveMkdir(relative: File): File = this.resolve(relative).apply { mkdirs() }
public fun File.touch(): File = apply {
parentFile?.mkdirs()
createNewFile()
}

View File

@ -1,15 +1,17 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.utils
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.locks.SynchronizedObject
import kotlinx.atomicfu.locks.synchronized
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@ -24,7 +26,7 @@ public fun <T> lateinitMutableProperty(initializer: () -> T): ReadWriteProperty<
private class LateinitMutableProperty<T>(
initializer: () -> T
) : ReadWriteProperty<Any?, T> {
) : ReadWriteProperty<Any?, T>, SynchronizedObject() {
private val value = atomic(UNINITIALIZED)
private var initializer: (() -> T)? = initializer
@ -39,7 +41,7 @@ private class LateinitMutableProperty<T>(
this.initializer = null
this.value.compareAndSet(UNINITIALIZED, value) // setValue prevails
this.value.value.let {
assert(it !== UNINITIALIZED)
check(it !== UNINITIALIZED)
return it as T
}
} else this.value.value as T

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -12,117 +12,38 @@
package net.mamoe.mirai.utils
import kotlinx.io.core.Input
import kotlinx.io.core.readAvailable
import java.io.*
import java.net.Inet4Address
import java.security.MessageDigest
import java.util.zip.Deflater
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import java.util.zip.Inflater
import kotlinx.io.core.Closeable
import kotlinx.io.core.toByteArray
import kotlinx.io.core.use
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
@JvmOverloads
public fun ByteArray.unzip(offset: Int = 0, length: Int = size - offset): ByteArray {
checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
public expect val DEFAULT_BUFFER_SIZE: Int
val inflater = Inflater()
inflater.reset()
ByteArrayOutputStream().use { output ->
inflater.setInput(this, offset, length)
ByteArray(DEFAULT_BUFFER_SIZE).let {
while (!inflater.finished()) {
output.write(it, 0, inflater.inflate(it))
}
}
public expect fun ByteArray.unzip(offset: Int = 0, length: Int = size - offset): ByteArray
inflater.end()
return output.toByteArray()
}
}
public fun InputStream.md5(): ByteArray {
return digest("md5")
}
public fun InputStream.digest(algorithm: String): ByteArray {
val digest = MessageDigest.getInstance(algorithm)
digest.reset()
use { input ->
object : OutputStream() {
override fun write(b: Int) {
digest.update(b.toByte())
}
override fun write(b: ByteArray, off: Int, len: Int) {
digest.update(b, off, len)
}
}.use { output ->
input.copyTo(output)
}
}
return digest.digest()
}
public fun InputStream.sha1(): ByteArray {
return digest("SHA-1")
}
/**
* Localhost 解析
*/
public fun localIpAddress(): String = runCatching {
Inet4Address.getLocalHost().hostAddress
}.getOrElse { "192.168.1.123" }
public expect fun localIpAddress(): String
public fun String.md5(): ByteArray = toByteArray().md5()
@JvmOverloads
public fun ByteArray.md5(offset: Int = 0, length: Int = size - offset): ByteArray {
checkOffsetAndLength(offset, length)
return MessageDigest.getInstance("MD5").apply { update(this@md5, offset, length) }.digest()
}
public expect fun ByteArray.md5(offset: Int = 0, length: Int = size - offset): ByteArray
public fun String.sha1(): ByteArray = toByteArray().sha1()
@JvmOverloads
public fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray {
checkOffsetAndLength(offset, length)
return MessageDigest.getInstance("SHA-1").apply { update(this@sha1, offset, length) }.digest()
}
public expect fun ByteArray.sha1(offset: Int = 0, length: Int = size - offset): ByteArray
@JvmOverloads
public fun ByteArray.ungzip(offset: Int = 0, length: Int = size - offset): ByteArray {
return GZIPInputStream(inputStream(offset, length)).use { it.readBytes() }
}
public expect fun ByteArray.ungzip(offset: Int = 0, length: Int = size - offset): ByteArray
@JvmOverloads
public fun ByteArray.gzip(offset: Int = 0, length: Int = size - offset): ByteArray {
ByteArrayOutputStream().use { buf ->
GZIPOutputStream(buf).use { gzip ->
inputStream(offset, length).use { t -> t.copyTo(gzip) }
}
buf.flush()
return buf.toByteArray()
}
}
public expect fun ByteArray.gzip(offset: Int = 0, length: Int = size - offset): ByteArray
@JvmOverloads
public fun ByteArray.zip(offset: Int = 0, length: Int = size - offset): ByteArray {
checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
public expect fun ByteArray.zip(offset: Int = 0, length: Int = size - offset): ByteArray
val deflater = Deflater()
deflater.setInput(this, offset, length)
deflater.finish()
ByteArray(DEFAULT_BUFFER_SIZE).let {
return it.take(deflater.deflate(it)).toByteArray().also { deflater.end() }
}
}
public inline fun <C : Closeable, R> C.withUse(block: C.() -> R): R {
contract {
@ -131,20 +52,6 @@ public inline fun <C : Closeable, R> C.withUse(block: C.() -> R): R {
return use(block)
}
@Throws(IOException::class)
@JvmOverloads
public fun Input.copyTo(out: OutputStream, bufferSize: Int = DEFAULT_BUFFER_SIZE): Long {
var bytesCopied: Long = 0
val buffer = ByteArray(bufferSize)
var bytes = readAvailable(buffer)
while (bytes >= 0) {
out.write(buffer, 0, bytes)
bytesCopied += bytes
bytes = readAvailable(buffer)
}
return bytesCopied
}
public inline fun <I : Closeable, O : Closeable, R> I.withOut(output: O, block: I.(output: O) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)

View File

@ -12,6 +12,9 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
public fun Int.toLongUnsigned(): Long = this.toLong().and(0xFFFF_FFFF)
public fun Short.toIntUnsigned(): Int = this.toUShort().toInt()
public fun Byte.toIntUnsigned(): Int = toInt() and 0xFF

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -14,6 +14,8 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.math.absoluteValue
import kotlin.random.Random
import kotlin.random.nextInt

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -9,13 +9,7 @@
package net.mamoe.mirai.utils
import java.util.concurrent.atomic.AtomicInteger
@TestOnly
public fun readResource(url: String): String =
Thread.currentThread().contextClassLoader.getResourceAsStream(url)?.readBytes()?.decodeToString()
?: error("Could not find resource '$url'")
import kotlinx.atomicfu.atomic
public class ResourceAccessLock {
public companion object {
@ -27,7 +21,7 @@ public class ResourceAccessLock {
/*
* status > 0 -> Number of holders using resource
*/
private val status = AtomicInteger(-1)
private val status = atomic(-1)
/**
* ```
@ -54,7 +48,7 @@ public class ResourceAccessLock {
public fun tryUse(): Boolean {
val c = status
while (true) {
val v = c.get()
val v = c.value
if (v < 0) return false
if (c.compareAndSet(v, v + 1)) return true
}
@ -63,7 +57,7 @@ public class ResourceAccessLock {
public fun lockIfNotUsing(): Boolean {
val count = this.status
while (true) {
val value = count.get()
val value = count.value
if (value != 0) return false
if (count.compareAndSet(0, -2)) return true
}
@ -72,7 +66,7 @@ public class ResourceAccessLock {
public fun release() {
val count = this.status
while (true) {
val value = count.get()
val value = count.value
if (value < 1) throw IllegalStateException("Current resource not in using")
if (count.compareAndSet(value, value - 1)) return
@ -84,11 +78,11 @@ public class ResourceAccessLock {
}
public fun setInitialized() {
status.set(INITIALIZED)
status.value = INITIALIZED
}
public fun setLocked() {
status.set(LOCKED)
status.value = LOCKED
}
public fun setDisposed() {
@ -96,13 +90,13 @@ public class ResourceAccessLock {
}
public fun setUninitialized() {
status.set(UNINITIALIZED)
status.value = UNINITIALIZED
}
public fun currentStatus(): Int = status.get()
public fun currentStatus(): Int = status.value
override fun toString(): String {
return when (val status = status.get()) {
return when (val status = status.value) {
0 -> "ResourceAccessLock(INITIALIZED)"
-1 -> "ResourceAccessLock(UNINITIALIZED)"
-2 -> "ResourceAccessLock(LOCKED)"

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@ -13,6 +13,8 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.reflect.KClass

View File

@ -7,41 +7,12 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.StringFormat
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.io.File
public fun <T> File.loadNotBlankAs(
serializer: DeserializationStrategy<T>,
stringFormat: StringFormat,
): T? {
if (!this.exists() || this.length() == 0L) {
return null
}
return stringFormat.decodeFromString(serializer, this.readText())
}
public fun <T> File.loadNotBlankAs(
serializer: DeserializationStrategy<T>,
binaryFormat: BinaryFormat,
): T? {
if (!this.exists() || this.length() == 0L) {
return null
}
return binaryFormat.decodeFromByteArray(serializer, this.readBytes())
}
public fun SerialDescriptor.copy(newName: String): SerialDescriptor =
buildClassSerialDescriptor(newName) { takeElementsFrom(this@copy) }

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -9,12 +9,13 @@
package net.mamoe.mirai.utils
import kotlinx.atomicfu.locks.ReentrantLock
import kotlinx.atomicfu.locks.reentrantLock
import kotlinx.atomicfu.locks.withLock
import java.util.concurrent.locks.ReentrantLock
@Suppress("unused", "UNCHECKED_CAST")
public class SizedCache<T>(size: Int) : Iterable<T> {
public val lock: ReentrantLock = ReentrantLock()
public val lock: ReentrantLock = reentrantLock()
public val data: Array<Any?> = arrayOfNulls(size)
public var filled: Boolean = false

View File

@ -12,9 +12,10 @@
package net.mamoe.mirai.utils
import java.util.*
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
public inline fun <reified T> Any?.cast(): T {
contract { returns() implies (this@cast is T) }
@ -58,34 +59,6 @@ public inline fun <E> MutableList<E>.replaceAllKotlin(operator: (E) -> E) {
}
}
public fun <T> Collection<T>.asImmutable(): Collection<T> {
return when (this) {
is List<T> -> asImmutable()
is Set<T> -> asImmutable()
else -> Collections.unmodifiableCollection(this)
}
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> Collection<T>.asImmutableStrict(): Collection<T> {
return Collections.unmodifiableCollection(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> List<T>.asImmutable(): List<T> {
return Collections.unmodifiableList(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> Set<T>.asImmutable(): Set<T> {
return Collections.unmodifiableSet(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <K, V> Map<K, V>.asImmutable(): Map<K, V> {
return Collections.unmodifiableMap(this)
}
public fun Throwable.getRootCause(maxDepth: Int = 20): Throwable {
var depth = 0
var rootCause: Throwable? = this
@ -156,7 +129,7 @@ public inline fun Throwable.findCauseOrSelf(maxDepth: Int = 20, filter: (Throwab
findCause(maxDepth, filter) ?: this
public fun String.capitalize(): String {
return replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
return replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
}
public fun String.truncated(length: Int, truncated: String = "..."): String {

File diff suppressed because one or more lines are too long

View File

@ -1,14 +1,16 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.utils
import kotlin.jvm.JvmName
public class Symbol private constructor(name: String) {
private val str = "Symbol($name)"
override fun toString(): String = str

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass
@ -12,17 +12,15 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.math.floor
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.ExperimentalTime
/**
* 时间戳
*
* @see System.currentTimeMillis
*/
public fun currentTimeMillis(): Long = System.currentTimeMillis()
public expect fun currentTimeMillis(): Long
/**
* 时间戳到秒

View File

@ -12,12 +12,12 @@
package net.mamoe.mirai.utils
import kotlinx.serialization.Serializable
import java.util.concurrent.ConcurrentHashMap
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlin.jvm.JvmInline
@Serializable
@JvmInline

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -9,6 +9,8 @@
package net.mamoe.mirai.utils
import kotlin.jvm.JvmField
public fun <T : Any> unsafeMutableNonNullPropertyOf(
name: String = "<unknown>"
): UnsafeMutableNonNullProperty<T> {
@ -24,7 +26,7 @@ public class UnsafeMutableNonNullProperty<T : Any>(
public val isInitialized: Boolean get() = value0 !== null
public var value: T
get() = value0 ?: throw UninitializedPropertyAccessException("Property `$propertyName` not initialized")
get() = value0 ?: throw IllegalStateException("Property `$propertyName` not initialized")
set(value) {
value0 = value
}

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@ -13,18 +13,20 @@
package net.mamoe.mirai.utils
import java.util.concurrent.ConcurrentHashMap
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
internal expect fun getProperty(name: String, default: String): String?
public fun systemProp(name: String, default: String): String =
System.getProperty(name, default) ?: default
getProperty(name, default) ?: default
public fun systemProp(name: String, default: Boolean): Boolean =
System.getProperty(name, default.toString())?.toBoolean() ?: default
getProperty(name, default.toString())?.toBoolean() ?: default
public fun systemProp(name: String, default: Long): Long =
System.getProperty(name, default.toString())?.toLongOrNull() ?: default
getProperty(name, default.toString())?.toLongOrNull() ?: default
private val debugProps = ConcurrentHashMap<String, Boolean>()

View File

@ -0,0 +1,46 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import java.util.*
public fun <T> Collection<T>.asImmutable(): Collection<T> {
return when (this) {
is List<T> -> asImmutable()
is Set<T> -> asImmutable()
else -> Collections.unmodifiableCollection(this)
}
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> Collection<T>.asImmutableStrict(): Collection<T> {
return Collections.unmodifiableCollection(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> List<T>.asImmutable(): List<T> {
return Collections.unmodifiableList(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <T> Set<T>.asImmutable(): Set<T> {
return Collections.unmodifiableSet(this)
}
@Suppress("NOTHING_TO_INLINE")
public inline fun <K, V> Map<K, V>.asImmutable(): Map<K, V> {
return Collections.unmodifiableMap(this)
}
@Suppress("FunctionName")
public actual fun <K : Any, V> ConcurrentHashMap(): MutableMap<K, V> {
return java.util.concurrent.ConcurrentHashMap()
}

View File

@ -0,0 +1,21 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
public actual suspend inline fun <R> runBIO(
noinline block: () -> R,
): R = runInterruptible(context = Dispatchers.IO, block = block)
public actual suspend inline fun <T, R> T.runBIO(
crossinline block: T.() -> R,
): R = runInterruptible(context = Dispatchers.IO, block = { block() })

View File

@ -0,0 +1,118 @@
/*
* Copyright 2019-2022 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:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
import kotlinx.io.core.use
import java.io.ByteArrayOutputStream
import java.io.InputStream
import java.io.OutputStream
import java.net.Inet4Address
import java.security.MessageDigest
import java.util.zip.Deflater
import java.util.zip.GZIPInputStream
import java.util.zip.GZIPOutputStream
import java.util.zip.Inflater
public actual val DEFAULT_BUFFER_SIZE: Int get() = kotlin.io.DEFAULT_BUFFER_SIZE
public actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
val inflater = Inflater()
inflater.reset()
ByteArrayOutputStream().use { output ->
inflater.setInput(this, offset, length)
ByteArray(DEFAULT_BUFFER_SIZE).let {
while (!inflater.finished()) {
output.write(it, 0, inflater.inflate(it))
}
}
inflater.end()
return output.toByteArray()
}
}
public actual fun localIpAddress(): String = runCatching {
Inet4Address.getLocalHost().hostAddress
}.getOrElse { "192.168.1.123" }
public fun InputStream.md5(): ByteArray {
return digest("md5")
}
public fun InputStream.digest(algorithm: String): ByteArray {
val digest = MessageDigest.getInstance(algorithm)
digest.reset()
use { input ->
object : OutputStream() {
override fun write(b: Int) {
digest.update(b.toByte())
}
override fun write(b: ByteArray, off: Int, len: Int) {
digest.update(b, off, len)
}
}.use { output ->
input.copyTo(output)
}
}
return digest.digest()
}
public fun InputStream.sha1(): ByteArray {
return digest("SHA-1")
}
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
checkOffsetAndLength(offset, length)
return MessageDigest.getInstance("MD5").apply { update(this@md5, offset, length) }.digest()
}
@JvmOverloads
public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray {
checkOffsetAndLength(offset, length)
return MessageDigest.getInstance("SHA-1").apply { update(this@sha1, offset, length) }.digest()
}
@JvmOverloads
public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray {
return GZIPInputStream(inputStream(offset, length)).use { it.readBytes() }
}
@JvmOverloads
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
ByteArrayOutputStream().use { buf ->
GZIPOutputStream(buf).use { gzip ->
inputStream(offset, length).use { t -> t.copyTo(gzip) }
}
buf.flush()
return buf.toByteArray()
}
}
@JvmOverloads
public actual fun ByteArray.zip(offset: Int, length: Int): ByteArray {
checkOffsetAndLength(offset, length)
if (length == 0) return ByteArray(0)
val deflater = Deflater()
deflater.setInput(this, offset, length)
deflater.finish()
ByteArray(DEFAULT_BUFFER_SIZE).let {
return it.take(deflater.deflate(it)).toByteArray().also { deflater.end() }
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
internal actual fun hash(e: Throwable): Long {
return e.stackTrace.fold(0L) { acc, stackTraceElement ->
acc * 31 + hash(stackTraceElement).toLongUnsigned()
}
}
private fun hash(element: StackTraceElement): Int {
return element.lineNumber.hashCode() xor element.className.hashCode() xor element.methodName.hashCode()
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2019-2022 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:JvmMultifileClass
@file:JvmName("MiraiUtils")
package net.mamoe.mirai.utils
import java.io.File
public fun File.createFileIfNotExists() {
if (!this.exists()) {
this.parentFile.mkdirs()
this.createNewFile()
}
}
public fun File.resolveCreateFile(relative: String): File = this.resolve(relative).apply { createFileIfNotExists() }
public fun File.resolveCreateFile(relative: File): File = this.resolve(relative).apply { createFileIfNotExists() }
public fun File.resolveMkdir(relative: String): File = this.resolve(relative).apply { mkdirs() }
public fun File.resolveMkdir(relative: File): File = this.resolve(relative).apply { mkdirs() }
public fun File.touch(): File = apply {
parentFile?.mkdirs()
createNewFile()
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.

View File

@ -0,0 +1,16 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
@TestOnly
public fun readResource(url: String): String =
Thread.currentThread().contextClassLoader.getResourceAsStream(url)?.readBytes()?.decodeToString()
?: error("Could not find resource '$url'")

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
@ -13,7 +13,6 @@ import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ByteArraySerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.serializer
import java.nio.ByteBuffer
import java.util.concurrent.ConcurrentLinkedDeque
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater

View File

@ -0,0 +1,37 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import kotlinx.serialization.BinaryFormat
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.StringFormat
import java.io.File
public fun <T> File.loadNotBlankAs(
serializer: DeserializationStrategy<T>,
stringFormat: StringFormat,
): T? {
if (!this.exists() || this.length() == 0L) {
return null
}
return stringFormat.decodeFromString(serializer, this.readText())
}
public fun <T> File.loadNotBlankAs(
serializer: DeserializationStrategy<T>,
binaryFormat: BinaryFormat,
): T? {
if (!this.exists() || this.length() == 0L) {
return null
}
return binaryFormat.decodeFromByteArray(serializer, this.readBytes())
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.

View File

@ -0,0 +1,12 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
public actual fun currentTimeMillis(): Long = System.currentTimeMillis()

View File

@ -1,10 +1,10 @@
/*
* Copyright 2019-2021 Mamoe Technologies and contributors.
* Copyright 2019-2022 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.
* 此源代码的使用受 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/master/LICENSE
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:JvmMultifileClass

View File

@ -0,0 +1,9 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils

View File

@ -0,0 +1,12 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
internal actual fun getProperty(name: String, default: String): String? = System.getProperty(name, default)

View File

@ -0,0 +1,10 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils

View File

@ -0,0 +1,17 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import kotlinx.io.errors.IOException
public actual interface Closeable {
@Throws(IOException::class)
public actual fun close()
}

View File

@ -0,0 +1,15 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
@Suppress("FunctionName")
public actual fun <K : Any, V> ConcurrentHashMap(): MutableMap<K, V> {
TODO("Not yet implemented")
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
public actual suspend inline fun <R> runBIO(noinline block: () -> R): R {
return block()
}
public actual suspend inline fun <T, R> T.runBIO(crossinline block: T.() -> R): R {
TODO("Not yet implemented")
}
/**
* For code
* ```
* try {
* job(new)
* } catch (e: Throwable) {
* throw IllegalStateException("Exception in attached Job '$name'", e.unwrapCancellationException())
* }
* ```
*
* Original stacktrace, you mainly see `StateSwitchingException` which is useless to locate the code where real cause `ForceOfflineException` is thrown.
* ```
* Exception in thread "DefaultDispatcher-worker-1 @BotInitProcessor.init#7" java.lang.IllegalStateException: Exception in attached Job 'BotInitProcessor.init'
* at net.mamoe.mirai.internal.network.handler.state.JobAttachStateObserver$stateChanged0$1.invokeSuspend(JobAttachStateObserver.kt:40)
* at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
* at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
* at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
* Caused by: StateSwitchingException(old=StateLoading, new=StateClosed, cause=net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException: Closed by MessageSvc.PushForceOffline: net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushForceOffline@4abf6d30)
* at net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport.setStateImpl$mirai_core(NetworkHandlerSupport.kt:258)
* at net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandler.close(NettyNetworkHandler.kt:404)
* ```
*
* Real stacktrace (with [unwrapCancellationException]), you directly have `ForceOfflineException`, also you wont lose information of `StateSwitchingException`
* ```
* Exception in thread "DefaultDispatcher-worker-2 @BotInitProcessor.init#7" java.lang.IllegalStateException: Exception in attached Job 'BotInitProcessor.init'
* at net.mamoe.mirai.internal.network.handler.state.JobAttachStateObserver$stateChanged0$1.invokeSuspend(JobAttachStateObserver.kt:40)
* at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
* at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
* at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
* at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
* Caused by: net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException: Closed by MessageSvc.PushForceOffline: net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushForceOffline@62f65f94
* at net.mamoe.mirai.utils.MiraiUtils__CoroutineUtilsKt.unwrapCancellationException(CoroutineUtils.kt:141)
* at net.mamoe.mirai.utils.MiraiUtils.unwrapCancellationException(Unknown Source)
* ... 7 more
* Suppressed: StateSwitchingException(old=StateLoading, new=StateClosed, cause=net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException: Closed by MessageSvc.PushForceOffline: net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushForceOffline@62f65f94)
* at net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport.setStateImpl$mirai_core(NetworkHandlerSupport.kt:258)
* at net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandler.close(NettyNetworkHandler.kt:404)
* ```
*/
@Suppress("unused")
public actual inline fun <reified E> Throwable.unwrap(): Throwable {
if (this !is E) return this
return this.findCause { it !is E }
?.also { it.addSuppressed(this) }
?: this
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
public actual fun ByteArray.unzip(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}
public actual fun localIpAddress(): String = "192.168.1.123"
public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}
public actual val DEFAULT_BUFFER_SIZE: Int get() = 8192
public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}
public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}
public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}
public actual fun ByteArray.zip(offset: Int, length: Int): ByteArray {
TODO("Not yet implemented")
}

View File

@ -0,0 +1,15 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
internal actual fun hash(e: Throwable): Long {
// Stacktrace analysis not available
return e.hashCode().toLongUnsigned()
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
/**
* 时间戳
*
* @see System.currentTimeMillis
*/
public actual fun currentTimeMillis(): Long {
TODO("Not yet implemented")
}

View File

@ -0,0 +1,14 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
internal actual fun getProperty(name: String, default: String): String? {
TODO("Not yet implemented")
}

View File

@ -0,0 +1,26 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.utils
import kotlin.reflect.KClass
public actual fun <T : Any> loadServiceOrNull(
clazz: KClass<out T>,
fallbackImplementation: String?
): T? {
TODO("Not yet implemented")
}
public actual fun <T : Any> loadService(
clazz: KClass<out T>,
fallbackImplementation: String?
): T {
TODO("Not yet implemented")
}