From 350b900aaa0803d6f2329f204c3d74891d67f1be Mon Sep 17 00:00:00 2001 From: RTAkland Date: Fri, 4 Sep 2026 00:19:17 +0800 Subject: [PATCH] Split rconlib and mcping --- build.gradle.kts | 69 ++++++------------- common/build.gradle.kts | 31 +++++++++ .../kotlin/cn/rtast/mcping/platform/buffer.kt | 28 ++++++++ .../cn/rtast/mcping/platform/channels.kt | 22 ++++++ .../cn/rtast/mcping/platform/context.kt | 0 .../kotlin/cn/rtast/mcping/platform/socket.kt | 21 ++++++ .../cn/rtast/mcping/platform/buffer.jvm.kt | 28 ++++---- .../cn/rtast/mcping/platform/channels.jvm.kt | 22 +++--- .../cn/rtast/mcping/platform/context.jvm.kt | 0 .../cn/rtast/mcping/platform/socket.jvm.kt | 16 +++-- .../cn/rtast/mcping/platform/buffer.native.kt | 38 ++++++++++ .../rtast/mcping/platform/channels.native.kt | 40 +++++++++++ .../rtast/mcping/platform/context.native.kt | 0 .../cn/rtast/mcping/platform/socket.native.kt | 18 ++--- mcping/build.gradle.kts | 24 +++++++ .../kotlin/cn/rtast/mcping/bedrock/packet.kt | 9 ++- .../cn/rtast/mcping/bedrock/packet_writer.kt | 17 +++++ .../cn/rtast/mcping/bedrock/ping_bedrock.kt | 4 +- .../mcping/bedrock/ping_response_parser.kt | 0 .../cn/rtast/mcping/java/mc_primitives.kt | 12 ++-- .../kotlin/cn/rtast/mcping/java/packet.kt | 10 +-- .../cn/rtast/mcping/java/packet_writer.kt | 10 +-- .../kotlin/cn/rtast/mcping/java/ping_java.kt | 4 +- .../kotlin/cn/rtast/mcping/mcping.kt | 0 .../kotlin/cn/rtast/mcping/ping_response.kt | 0 .../kotlin/cn/rtast/mcping/server_type.kt | 0 .../src}/commonTest/kotlin/test/TestPing.kt | 0 .../jvmTest/java/test/TestPingInJava.java | 0 .../mingwTest/kotlin/test/TestMingwPing.kt | 0 rconlib/build.gradle.kts | 24 +++++++ .../kotlin/cn/rtast/mcping/rconlib/rconlib.kt | 9 +++ settings.gradle.kts | 6 +- .../cn/rtast/mcping/bedrock/packet_writer.kt | 17 ----- .../kotlin/cn/rtast/mcping/platform/buffer.kt | 27 -------- .../cn/rtast/mcping/platform/channels.kt | 20 ------ .../kotlin/cn/rtast/mcping/platform/socket.kt | 19 ----- .../cn/rtast/mcping/platform/buffer.native.kt | 37 ---------- .../rtast/mcping/platform/channels.native.kt | 36 ---------- 38 files changed, 350 insertions(+), 268 deletions(-) create mode 100644 common/build.gradle.kts create mode 100644 common/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt create mode 100644 common/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt rename {src => common/src}/commonMain/kotlin/cn/rtast/mcping/platform/context.kt (100%) create mode 100644 common/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt rename {src => common/src}/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt (77%) rename {src => common/src}/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt (72%) rename {src => common/src}/jvmMain/kotlin/cn/rtast/mcping/platform/context.jvm.kt (100%) rename {src => common/src}/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt (54%) create mode 100644 common/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt create mode 100644 common/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt rename {src => common/src}/nativeMain/kotlin/cn/rtast/mcping/platform/context.native.kt (100%) rename {src => common/src}/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt (63%) create mode 100644 mcping/build.gradle.kts rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt (92%) create mode 100644 mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt (91%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_response_parser.kt (100%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt (75%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/java/packet.kt (78%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt (62%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt (94%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/mcping.kt (100%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/ping_response.kt (100%) rename {src => mcping/src}/commonMain/kotlin/cn/rtast/mcping/server_type.kt (100%) rename {src => mcping/src}/commonTest/kotlin/test/TestPing.kt (100%) rename {src => mcping/src}/jvmTest/java/test/TestPingInJava.java (100%) rename {src => mcping/src}/mingwTest/kotlin/test/TestMingwPing.kt (100%) create mode 100644 rconlib/build.gradle.kts create mode 100644 rconlib/src/commonMain/kotlin/cn/rtast/mcping/rconlib/rconlib.kt delete mode 100644 src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt delete mode 100644 src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt delete mode 100644 src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt delete mode 100644 src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt delete mode 100644 src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt delete mode 100644 src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt diff --git a/build.gradle.kts b/build.gradle.kts index 0c299ca..d6c3080 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,56 +1,31 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - plugins { - kotlin("multiplatform") version "2.4.10" + kotlin("multiplatform") version "2.4.10" apply false id("maven-publish") } -group = "cn.rtast.mcping" -version = providers.gradleProperty("libVersion").get() +allprojects { + group = "cn.rtast.mcping" + version = providers.gradleProperty("libVersion").get() -repositories { - mavenCentral() -} - -kotlin { - explicitApi() - - linuxX64() - linuxArm64() - macosArm64() - mingwX64() - iosArm64() - iosSimulatorArm64() - jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } - - sourceSets { - jvmMain.dependencies { - // no dependencies needed - } - - nativeMain.dependencies { - implementation("io.ktor:ktor-network:3.5.2") - implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.9.1") - } - - commonTest.dependencies { - implementation(kotlin("test")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0") - } - } - - compilerOptions.freeCompilerArgs.addAll("-Xexpect-actual-classes") -} - -publishing { repositories { - maven("https://repo.rtast.cn/packages") { - credentials(HttpHeaderCredentials::class) { - name = "Authorization" - value = "Bearer ${System.getenv("PUBLISH_TOKEN")}" - } - authentication { - create("header") + mavenCentral() + } +} + +subprojects { + pluginManager.apply("org.jetbrains.kotlin.multiplatform") + pluginManager.apply("maven-publish") + + publishing { + repositories { + maven("https://repo.rtast.cn/packages") { + credentials(HttpHeaderCredentials::class) { + name = "Authorization" + value = "Bearer ${System.getenv("PUBLISH_TOKEN")}" + } + authentication { + create("header") + } } } } diff --git a/common/build.gradle.kts b/common/build.gradle.kts new file mode 100644 index 0000000..b9a9960 --- /dev/null +++ b/common/build.gradle.kts @@ -0,0 +1,31 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +kotlin { + explicitApi() + + linuxX64() + linuxArm64() + macosArm64() + mingwX64() + iosArm64() + iosSimulatorArm64() + jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } + + sourceSets { + jvmMain.dependencies { + // no dependencies needed + } + + nativeMain.dependencies { + implementation("io.ktor:ktor-network:3.5.2") + implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.9.1") + } + + commonTest.dependencies { + implementation(kotlin("test")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0") + } + } + + compilerOptions.freeCompilerArgs.addAll("-Xexpect-actual-classes") +} \ No newline at end of file diff --git a/common/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt new file mode 100644 index 0000000..c63aa4a --- /dev/null +++ b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + + +package cn.rtast.mcping.platform + +@Suppress("CLASSNAME") +public expect class _Buffer { + public constructor() + public constructor(bytes: ByteArray) + + public fun writeByte(value: Byte) + public fun writeShort(value: Short) + public fun writeLong(value: Long) + public fun writeBytes(bytes: ByteArray) + + public fun readByte(): Byte + public fun readShort(): Short + public fun readLong(): Long + public fun readBytes(length: Int): ByteArray + public fun toByteArray(): ByteArray + public val size: Int +} + +public fun ByteArray.wrap(): _Buffer = _Buffer(this) \ No newline at end of file diff --git a/common/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt new file mode 100644 index 0000000..0bcc120 --- /dev/null +++ b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt @@ -0,0 +1,22 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + + +package cn.rtast.mcping.platform + +@Suppress("CLASSNAME") +public expect class _ReadChannel { + public fun readByte(): Byte + public fun readBytes(length: Int): ByteArray + public fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size) + public fun readLong(): Long +} + +@Suppress("CLASSNAME") +public expect class _WriteChannel { + public fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size) + public fun flush() +} \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/platform/context.kt b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/context.kt similarity index 100% rename from src/commonMain/kotlin/cn/rtast/mcping/platform/context.kt rename to common/src/commonMain/kotlin/cn/rtast/mcping/platform/context.kt diff --git a/common/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt new file mode 100644 index 0000000..c65cdd6 --- /dev/null +++ b/common/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt @@ -0,0 +1,21 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + + +package cn.rtast.mcping.platform + +@Suppress("CLASSNAME") +public expect class _Socket public constructor(host: String, port: Int, context: PingContext) { + public fun openReadChannel(): _ReadChannel + public fun openWriteChannel(): _WriteChannel + public fun close() +} + +@Suppress("CLASSNAME") +public expect class _UdpSocket public constructor(host: String, port: Int, context: PingContext) { + public fun sendAndReceive(data: ByteArray): ByteArray + public fun close() +} \ No newline at end of file diff --git a/src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt similarity index 77% rename from src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt rename to common/src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt index 9e3bf51..205a5eb 100644 --- a/src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt +++ b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/buffer.jvm.kt @@ -8,29 +8,29 @@ package cn.rtast.mcping.platform import java.io.ByteArrayOutputStream -internal actual class PlatformBuffer { +@Suppress("CLASSNAME") +public actual class _Buffer { private val outStream = ByteArrayOutputStream() private var readBuffer: ByteArray? = null private var readOffset = 0 - actual constructor() - - actual constructor(bytes: ByteArray) { + public actual constructor() + public actual constructor(bytes: ByteArray) { this.readBuffer = bytes outStream.write(bytes) } - actual fun writeByte(value: Byte) { + public actual fun writeByte(value: Byte) { outStream.write(value.toInt()) } - actual fun writeShort(value: Short) { + public actual fun writeShort(value: Short) { val v = value.toInt() outStream.write(v shr 8) outStream.write(v) } - actual fun writeLong(value: Long) { + public actual fun writeLong(value: Long) { outStream.write((value shr 56).toInt()) outStream.write((value shr 48).toInt()) outStream.write((value shr 40).toInt()) @@ -41,7 +41,7 @@ internal actual class PlatformBuffer { outStream.write(value.toInt()) } - actual fun writeBytes(bytes: ByteArray) { + public actual fun writeBytes(bytes: ByteArray) { outStream.write(bytes) } @@ -54,19 +54,19 @@ internal actual class PlatformBuffer { return buf } - actual fun readByte(): Byte { + public actual fun readByte(): Byte { val array = ensureReadArray() if (readOffset >= array.size) throw IndexOutOfBoundsException("Buffer underflow") return array[readOffset++] } - actual fun readShort(): Short { + public actual fun readShort(): Short { val b1 = readByte().toInt() and 0xFF val b2 = readByte().toInt() and 0xFF return ((b1 shl 8) or b2).toShort() } - actual fun readLong(): Long { + public actual fun readLong(): Long { return (readByte().toLong() and 0xFF shl 56) or (readByte().toLong() and 0xFF shl 48) or (readByte().toLong() and 0xFF shl 40) or @@ -77,7 +77,7 @@ internal actual class PlatformBuffer { (readByte().toLong() and 0xFF) } - actual fun readBytes(length: Int): ByteArray { + public actual fun readBytes(length: Int): ByteArray { val array = ensureReadArray() if (readOffset + length > array.size) throw IndexOutOfBoundsException("Buffer underflow") val result = array.copyOfRange(readOffset, readOffset + length) @@ -85,8 +85,8 @@ internal actual class PlatformBuffer { return result } - actual fun toByteArray(): ByteArray = outStream.toByteArray() + public actual fun toByteArray(): ByteArray = outStream.toByteArray() - actual val size: Int + public actual val size: Int get() = outStream.size() } \ No newline at end of file diff --git a/src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt similarity index 72% rename from src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt rename to common/src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt index 3388c00..d4fd7a0 100644 --- a/src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt +++ b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/channels.jvm.kt @@ -11,16 +11,17 @@ import java.io.EOFException import java.io.InputStream import java.io.OutputStream -internal actual class ReadChannel { +@Suppress("CLASSNAME") +public actual class _ReadChannel { private val _inputStream: InputStream - constructor(inputStream: InputStream) { + public constructor(inputStream: InputStream) { _inputStream = inputStream } - actual fun readByte(): Byte = _inputStream.read().toByte() - actual fun readBytes(length: Int): ByteArray = _inputStream.readNBytes(length) - actual fun readFully(out: ByteArray, start: Int, end: Int) { + public actual fun readByte(): Byte = _inputStream.read().toByte() + public actual fun readBytes(length: Int): ByteArray = _inputStream.readNBytes(length) + public actual fun readFully(out: ByteArray, start: Int, end: Int) { var bytesRead = 0 val length = end - start while (bytesRead < length) { @@ -30,7 +31,7 @@ internal actual class ReadChannel { } } - actual fun readLong(): Long { + public actual fun readLong(): Long { val bytes = ByteArray(8) var read = 0 while (read < 8) { @@ -49,17 +50,18 @@ internal actual class ReadChannel { } } -internal actual class WriteChannel { +@Suppress("CLASSNAME") +public actual class _WriteChannel { private val _outputStream: OutputStream - constructor(outputStream: OutputStream) { + public constructor(outputStream: OutputStream) { _outputStream = outputStream } - actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) = + public actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit = _outputStream.write(value, startIndex, endIndex - startIndex) - actual fun flush() = _outputStream.flush() + public actual fun flush(): Unit = _outputStream.flush() } private fun InputStream.readNBytes(length: Int): ByteArray { diff --git a/src/jvmMain/kotlin/cn/rtast/mcping/platform/context.jvm.kt b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/context.jvm.kt similarity index 100% rename from src/jvmMain/kotlin/cn/rtast/mcping/platform/context.jvm.kt rename to common/src/jvmMain/kotlin/cn/rtast/mcping/platform/context.jvm.kt diff --git a/src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt similarity index 54% rename from src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt rename to common/src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt index 8680375..1cdbecb 100644 --- a/src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt +++ b/common/src/jvmMain/kotlin/cn/rtast/mcping/platform/socket.jvm.kt @@ -11,21 +11,23 @@ import java.net.DatagramSocket import java.net.InetSocketAddress import java.net.Socket as JvmSocket -internal actual class Socket internal actual constructor(host: String, port: Int, context: PingContext) { +@Suppress("CLASSNAME") +public actual class _Socket public actual constructor(host: String, port: Int, context: PingContext) { private val socket = JvmSocket(host, port) - actual fun openReadChannel(): ReadChannel = ReadChannel(socket.getInputStream()) - actual fun openWriteChannel(): WriteChannel = WriteChannel(socket.getOutputStream()) - actual fun close() = socket.close() + public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.getInputStream()) + public actual fun openWriteChannel(): _WriteChannel = _WriteChannel(socket.getOutputStream()) + public actual fun close(): Unit = socket.close() } -internal actual class UdpSocket internal actual constructor(host: String, port: Int, context: PingContext) { +@Suppress("CLASSNAME") +public actual class _UdpSocket public actual constructor(host: String, port: Int, context: PingContext) { private val socket = DatagramSocket().apply { soTimeout = 3000 connect(InetSocketAddress(host, port)) } - actual fun sendAndReceive(data: ByteArray): ByteArray { + public actual fun sendAndReceive(data: ByteArray): ByteArray { socket.send(DatagramPacket(data, data.size)) val buf = ByteArray(2048) @@ -34,5 +36,5 @@ internal actual class UdpSocket internal actual constructor(host: String, port: return buf.copyOf(receivePacket.length) } - actual fun close() = socket.close() + public actual fun close(): Unit = socket.close() } \ No newline at end of file diff --git a/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt new file mode 100644 index 0000000..8ac2e2d --- /dev/null +++ b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt @@ -0,0 +1,38 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + +package cn.rtast.mcping.platform + +import kotlinx.io.Buffer +import kotlinx.io.readByteArray + +@Suppress("CLASSNAME") +public actual class _Buffer { + private val _delegateBuf: Buffer + + public actual constructor() { + _delegateBuf = Buffer() + } + + public actual constructor(bytes: ByteArray) { + _delegateBuf = Buffer().apply { write(bytes) } + } + + public actual fun writeByte(value: Byte): Unit = _delegateBuf.writeByte(value) + public actual fun writeShort(value: Short): Unit = _delegateBuf.writeShort(value) + public actual fun writeLong(value: Long): Unit = _delegateBuf.writeLong(value) + public actual fun writeBytes(bytes: ByteArray): Unit = _delegateBuf.write(bytes) + + public actual fun readByte(): Byte = _delegateBuf.readByte() + public actual fun readShort(): Short = _delegateBuf.readShort() + public actual fun readLong(): Long = _delegateBuf.readLong() + public actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length) + + public actual fun toByteArray(): ByteArray = _delegateBuf.peek().readByteArray() + + public actual val size: Int + get() = _delegateBuf.size.toInt() +} \ No newline at end of file diff --git a/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt new file mode 100644 index 0000000..23c4391 --- /dev/null +++ b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt @@ -0,0 +1,40 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + +package cn.rtast.mcping.platform + +import io.ktor.utils.io.* +import kotlinx.coroutines.runBlocking + +@Suppress("CLASSNAME") +public actual class _ReadChannel { + private val _readChannel: ByteReadChannel + + public constructor(readChannel: ByteReadChannel) { + _readChannel = readChannel + } + + public actual fun readByte(): Byte = runBlocking { _readChannel.readByte() } + public actual fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) } + public actual fun readFully(out: ByteArray, start: Int, end: Int): Unit = + runBlocking { _readChannel.readFully(out, start, end) } + + public actual fun readLong(): Long = runBlocking { _readChannel.readLong() } +} + +@Suppress("CLASSNAME") +public actual class _WriteChannel { + private val _writeChannel: ByteWriteChannel + + public constructor(writeChannel: ByteWriteChannel) { + _writeChannel = writeChannel + } + + public actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit = + runBlocking { _writeChannel.writeFully(value, startIndex, endIndex) } + + public actual fun flush(): Unit = runBlocking { _writeChannel.flush() } +} \ No newline at end of file diff --git a/src/nativeMain/kotlin/cn/rtast/mcping/platform/context.native.kt b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/context.native.kt similarity index 100% rename from src/nativeMain/kotlin/cn/rtast/mcping/platform/context.native.kt rename to common/src/nativeMain/kotlin/cn/rtast/mcping/platform/context.native.kt diff --git a/src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt similarity index 63% rename from src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt rename to common/src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt index 4075f9f..aa0035e 100644 --- a/src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt +++ b/common/src/nativeMain/kotlin/cn/rtast/mcping/platform/socket.native.kt @@ -11,34 +11,36 @@ import io.ktor.utils.io.core.* import kotlinx.coroutines.runBlocking import kotlinx.io.readByteArray -internal actual class Socket internal actual constructor(host: String, port: Int, context: PingContext) { +@Suppress("CLASSNAME") +public actual class _Socket public actual constructor(host: String, port: Int, context: PingContext) { private val ctx = context private val socket = runBlocking { aSocket(ctx._selectorManager).tcp().connect(host, port) } - actual fun openReadChannel(): ReadChannel = ReadChannel(socket.openReadChannel()) - actual fun openWriteChannel(): WriteChannel = - WriteChannel(socket.openWriteChannel(autoFlush = true)) + public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.openReadChannel()) + public actual fun openWriteChannel(): _WriteChannel = + _WriteChannel(socket.openWriteChannel(autoFlush = true)) - actual fun close() { + public actual fun close() { socket.close() if (ctx._autoCloseSelectorManager) ctx._selectorManager.close() } } -internal actual class UdpSocket internal actual constructor(host: String, port: Int, context: PingContext) { +@Suppress("CLASSNAME") +public actual class _UdpSocket public actual constructor(host: String, port: Int, context: PingContext) { private val ctx = context // use bind to create an unconnected socket private val socket = runBlocking { aSocket(ctx._selectorManager).udp().bind() } private val remoteAddress = InetSocketAddress(host, port) - actual fun sendAndReceive(data: ByteArray): ByteArray = runBlocking { + public actual fun sendAndReceive(data: ByteArray): ByteArray = runBlocking { val packet = buildPacket { writeFully(data) } socket.send(Datagram(packet, remoteAddress)) socket.receive().packet.readByteArray() } - actual fun close() { + public actual fun close() { socket.close() if (ctx._autoCloseSelectorManager) ctx._selectorManager.close() } diff --git a/mcping/build.gradle.kts b/mcping/build.gradle.kts new file mode 100644 index 0000000..d88aef9 --- /dev/null +++ b/mcping/build.gradle.kts @@ -0,0 +1,24 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +kotlin { + explicitApi() + + linuxX64() + linuxArm64() + macosArm64() + mingwX64() + iosArm64() + iosSimulatorArm64() + jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } + + sourceSets { + commonMain.dependencies { + implementation(project(":common")) + } + + commonTest.dependencies { + implementation(kotlin("test")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0") + } + } +} \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt similarity index 92% rename from src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt index e875ed8..6024522 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet.kt @@ -7,9 +7,8 @@ package cn.rtast.mcping.bedrock -import cn.rtast.mcping.platform.PlatformBuffer +import cn.rtast.mcping.platform._Buffer import kotlin.random.Random -import kotlin.time.Clock private val rakNetMagic = byteArrayOf( 0x00, 0xFF.toByte(), @@ -26,7 +25,7 @@ internal interface MinecraftBedrockPacket { val time: Long val magic: ByteArray - fun writePayload(buffer: PlatformBuffer) + fun writePayload(buffer: _Buffer) } internal data class BedrockRequestPacket( @@ -36,7 +35,7 @@ internal data class BedrockRequestPacket( ) : MinecraftBedrockPacket { override val packetId: Byte = 0x01 - override fun writePayload(buffer: PlatformBuffer) { + override fun writePayload(buffer: _Buffer) { buffer.writeByte(packetId) buffer.writeLong(time) buffer.writeBytes(magic) @@ -71,7 +70,7 @@ internal data class BedrockResponsePacket( val stringLength: Short, val payload: String, ) : MinecraftBedrockPacket { - override fun writePayload(buffer: PlatformBuffer) {} + override fun writePayload(buffer: _Buffer) {} override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt new file mode 100644 index 0000000..9fcf19f --- /dev/null +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt @@ -0,0 +1,17 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/3 + */ + + +package cn.rtast.mcping.bedrock + +import cn.rtast.mcping.platform._Buffer +import cn.rtast.mcping.platform._UdpSocket + +internal fun _UdpSocket.sendPacket(packet: MinecraftBedrockPacket): ByteArray { + val buf = _Buffer() + packet.writePayload(buf) + return sendAndReceive(buf.toByteArray()) +} \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt similarity index 91% rename from src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt index 0ef5723..d5c29b5 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_bedrock.kt @@ -9,12 +9,12 @@ package cn.rtast.mcping.bedrock import cn.rtast.mcping.PingResponse import cn.rtast.mcping.platform.PingContext -import cn.rtast.mcping.platform.UdpSocket +import cn.rtast.mcping.platform._UdpSocket import cn.rtast.mcping.platform.wrap import kotlin.time.Clock internal fun pingBedrockServer(host: String, port: Int, context: PingContext): PingResponse { - val socket = UdpSocket(host, port, context) + val socket = _UdpSocket(host, port, context) return try { val sendTime = Clock.System.now().toEpochMilliseconds() val packet = BedrockRequestPacket(sendTime) diff --git a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_response_parser.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_response_parser.kt similarity index 100% rename from src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_response_parser.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/bedrock/ping_response_parser.kt diff --git a/src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt similarity index 75% rename from src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt index 8856b3c..be8a06c 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/mc_primitives.kt @@ -6,11 +6,11 @@ package cn.rtast.mcping.java -import cn.rtast.mcping.platform.PlatformBuffer -import cn.rtast.mcping.platform.ReadChannel +import cn.rtast.mcping.platform._Buffer +import cn.rtast.mcping.platform._ReadChannel -internal fun PlatformBuffer.writeVarInt(value: Int) { +internal fun _Buffer.writeVarInt(value: Int) { var v = value while (true) { if ((v and 0x7F.inv()) == 0) { @@ -22,7 +22,7 @@ internal fun PlatformBuffer.writeVarInt(value: Int) { } } -internal fun ReadChannel.readVarInt(): Int { +internal fun _ReadChannel.readVarInt(): Int { var value = 0 var position = 0 while (true) { @@ -35,13 +35,13 @@ internal fun ReadChannel.readVarInt(): Int { return value } -internal fun PlatformBuffer.writeMcString(value: String) { +internal fun _Buffer.writeMcString(value: String) { val bytes = value.encodeToByteArray() this.writeVarInt(bytes.size) this.writeBytes(bytes) } -internal fun ReadChannel.readMcString(): String { +internal fun _ReadChannel.readMcString(): String { val length = this.readVarInt() val bytes = this.readBytes(length) return bytes.decodeToString() diff --git a/src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt similarity index 78% rename from src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt index 332bb40..d406bdb 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet.kt @@ -7,12 +7,12 @@ package cn.rtast.mcping.java -import cn.rtast.mcping.platform.PlatformBuffer +import cn.rtast.mcping.platform._Buffer internal interface MinecraftPacket { val packetId: Int - fun writePayload(buffer: PlatformBuffer) + fun writePayload(buffer: _Buffer) } // ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshake @@ -25,7 +25,7 @@ internal data class HandshakePacket( ) : MinecraftPacket { override val packetId: Int = 0x00 - override fun writePayload(buffer: PlatformBuffer) { + override fun writePayload(buffer: _Buffer) { buffer.writeVarInt(protocolVersion) buffer.writeMcString(serverAddress) // write UShort @@ -39,10 +39,10 @@ internal data class HandshakePacket( // ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status internal data object StatusRequestPacket : MinecraftPacket { override val packetId: Int = 0x00 - override fun writePayload(buffer: PlatformBuffer) {} + override fun writePayload(buffer: _Buffer) {} } internal data class PingPacket(val currentTime: Long) : MinecraftPacket { override val packetId: Int = 0x01 - override fun writePayload(buffer: PlatformBuffer) = buffer.writeLong(currentTime) + override fun writePayload(buffer: _Buffer) = buffer.writeLong(currentTime) } \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt similarity index 62% rename from src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt index 0d747a3..02652ed 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/packet_writer.kt @@ -7,14 +7,14 @@ package cn.rtast.mcping.java -import cn.rtast.mcping.platform.PlatformBuffer -import cn.rtast.mcping.platform.WriteChannel +import cn.rtast.mcping.platform._Buffer +import cn.rtast.mcping.platform._WriteChannel -internal fun WriteChannel.sendPacket(packet: MinecraftPacket) { - val bodyBuffer = PlatformBuffer() +internal fun _WriteChannel.sendPacket(packet: MinecraftPacket) { + val bodyBuffer = _Buffer() bodyBuffer.writeVarInt(packet.packetId) packet.writePayload(bodyBuffer) - val frameBuffer = PlatformBuffer() + val frameBuffer = _Buffer() frameBuffer.writeVarInt(bodyBuffer.size) frameBuffer.writeBytes(bodyBuffer.toByteArray()) val bytes = frameBuffer.toByteArray() diff --git a/src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt similarity index 94% rename from src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt index 9273ba8..d4caad5 100644 --- a/src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt +++ b/mcping/src/commonMain/kotlin/cn/rtast/mcping/java/ping_java.kt @@ -9,11 +9,11 @@ package cn.rtast.mcping.java import cn.rtast.mcping.PingResponse import cn.rtast.mcping.platform.PingContext -import cn.rtast.mcping.platform.Socket +import cn.rtast.mcping.platform._Socket import kotlin.time.Clock internal fun pingJavaServer(host: String, port: Int, context: PingContext): PingResponse { - val socket = Socket(host, port, context) + val socket = _Socket(host, port, context) val receiveChannel = socket.openReadChannel() val sendChannel = socket.openWriteChannel() diff --git a/src/commonMain/kotlin/cn/rtast/mcping/mcping.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/mcping.kt similarity index 100% rename from src/commonMain/kotlin/cn/rtast/mcping/mcping.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/mcping.kt diff --git a/src/commonMain/kotlin/cn/rtast/mcping/ping_response.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/ping_response.kt similarity index 100% rename from src/commonMain/kotlin/cn/rtast/mcping/ping_response.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/ping_response.kt diff --git a/src/commonMain/kotlin/cn/rtast/mcping/server_type.kt b/mcping/src/commonMain/kotlin/cn/rtast/mcping/server_type.kt similarity index 100% rename from src/commonMain/kotlin/cn/rtast/mcping/server_type.kt rename to mcping/src/commonMain/kotlin/cn/rtast/mcping/server_type.kt diff --git a/src/commonTest/kotlin/test/TestPing.kt b/mcping/src/commonTest/kotlin/test/TestPing.kt similarity index 100% rename from src/commonTest/kotlin/test/TestPing.kt rename to mcping/src/commonTest/kotlin/test/TestPing.kt diff --git a/src/jvmTest/java/test/TestPingInJava.java b/mcping/src/jvmTest/java/test/TestPingInJava.java similarity index 100% rename from src/jvmTest/java/test/TestPingInJava.java rename to mcping/src/jvmTest/java/test/TestPingInJava.java diff --git a/src/mingwTest/kotlin/test/TestMingwPing.kt b/mcping/src/mingwTest/kotlin/test/TestMingwPing.kt similarity index 100% rename from src/mingwTest/kotlin/test/TestMingwPing.kt rename to mcping/src/mingwTest/kotlin/test/TestMingwPing.kt diff --git a/rconlib/build.gradle.kts b/rconlib/build.gradle.kts new file mode 100644 index 0000000..d88aef9 --- /dev/null +++ b/rconlib/build.gradle.kts @@ -0,0 +1,24 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +kotlin { + explicitApi() + + linuxX64() + linuxArm64() + macosArm64() + mingwX64() + iosArm64() + iosSimulatorArm64() + jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 } + + sourceSets { + commonMain.dependencies { + implementation(project(":common")) + } + + commonTest.dependencies { + implementation(kotlin("test")) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0") + } + } +} \ No newline at end of file diff --git a/rconlib/src/commonMain/kotlin/cn/rtast/mcping/rconlib/rconlib.kt b/rconlib/src/commonMain/kotlin/cn/rtast/mcping/rconlib/rconlib.kt new file mode 100644 index 0000000..ebb68e1 --- /dev/null +++ b/rconlib/src/commonMain/kotlin/cn/rtast/mcping/rconlib/rconlib.kt @@ -0,0 +1,9 @@ +/* + * Copyright © 2026 RTAkland + * Author: RTAkland + * Date: 2026/9/4 + */ + + +package cn.rtast.mcping.rconlib + diff --git a/settings.gradle.kts b/settings.gradle.kts index 2d798d4..aa97f56 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,8 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" } -rootProject.name = "mcping" \ No newline at end of file +rootProject.name = "mcping" + +include(":mcping") +include(":rconlib") +include(":common") \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt b/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt deleted file mode 100644 index 1a0a18b..0000000 --- a/src/commonMain/kotlin/cn/rtast/mcping/bedrock/packet_writer.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - - -package cn.rtast.mcping.bedrock - -import cn.rtast.mcping.platform.PlatformBuffer -import cn.rtast.mcping.platform.UdpSocket - -internal fun UdpSocket.sendPacket(packet: MinecraftBedrockPacket): ByteArray { - val buf = PlatformBuffer() - packet.writePayload(buf) - return sendAndReceive(buf.toByteArray()) -} \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt b/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt deleted file mode 100644 index 9eb042e..0000000 --- a/src/commonMain/kotlin/cn/rtast/mcping/platform/buffer.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - - -package cn.rtast.mcping.platform - -internal expect class PlatformBuffer { - constructor() - constructor(bytes: ByteArray) - - fun writeByte(value: Byte) - fun writeShort(value: Short) - fun writeLong(value: Long) - fun writeBytes(bytes: ByteArray) - - fun readByte(): Byte - fun readShort(): Short - fun readLong(): Long - fun readBytes(length: Int): ByteArray - fun toByteArray(): ByteArray - val size: Int -} - -internal fun ByteArray.wrap(): PlatformBuffer = PlatformBuffer(this) \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt b/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt deleted file mode 100644 index 3dff65c..0000000 --- a/src/commonMain/kotlin/cn/rtast/mcping/platform/channels.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - - -package cn.rtast.mcping.platform - -internal expect class ReadChannel { - fun readByte(): Byte - fun readBytes(length: Int): ByteArray - fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size) - fun readLong(): Long -} - -internal expect class WriteChannel { - fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size) - fun flush() -} \ No newline at end of file diff --git a/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt b/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt deleted file mode 100644 index 7f575c7..0000000 --- a/src/commonMain/kotlin/cn/rtast/mcping/platform/socket.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - - -package cn.rtast.mcping.platform - -internal expect class Socket internal constructor(host: String, port: Int, context: PingContext) { - fun openReadChannel(): ReadChannel - fun openWriteChannel(): WriteChannel - fun close() -} - -internal expect class UdpSocket internal constructor(host: String, port: Int, context: PingContext) { - fun sendAndReceive(data: ByteArray): ByteArray - fun close() -} \ No newline at end of file diff --git a/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt b/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt deleted file mode 100644 index 3e17b89..0000000 --- a/src/nativeMain/kotlin/cn/rtast/mcping/platform/buffer.native.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - -package cn.rtast.mcping.platform - -import kotlinx.io.Buffer -import kotlinx.io.readByteArray - -internal actual class PlatformBuffer { - private val _delegateBuf: Buffer - - actual constructor() { - _delegateBuf = Buffer() - } - - actual constructor(bytes: ByteArray) { - _delegateBuf = Buffer().apply { write(bytes) } - } - - actual fun writeByte(value: Byte) = _delegateBuf.writeByte(value) - actual fun writeShort(value: Short) = _delegateBuf.writeShort(value) - actual fun writeLong(value: Long) = _delegateBuf.writeLong(value) - actual fun writeBytes(bytes: ByteArray) = _delegateBuf.write(bytes) - - actual fun readByte(): Byte = _delegateBuf.readByte() - actual fun readShort(): Short = _delegateBuf.readShort() - actual fun readLong(): Long = _delegateBuf.readLong() - actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length) - - actual fun toByteArray(): ByteArray = _delegateBuf.peek().readByteArray() - - actual val size: Int - get() = _delegateBuf.size.toInt() -} \ No newline at end of file diff --git a/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt b/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt deleted file mode 100644 index 17f65a0..0000000 --- a/src/nativeMain/kotlin/cn/rtast/mcping/platform/channels.native.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2026 RTAkland - * Author: RTAkland - * Date: 2026/9/3 - */ - -package cn.rtast.mcping.platform - -import io.ktor.utils.io.* -import kotlinx.coroutines.runBlocking - -internal actual class ReadChannel { - private val _readChannel: ByteReadChannel - - constructor(readChannel: ByteReadChannel) { - _readChannel = readChannel - } - - actual fun readByte(): Byte = runBlocking { _readChannel.readByte() } - actual fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) } - actual fun readFully(out: ByteArray, start: Int, end: Int) = runBlocking { _readChannel.readFully(out, start, end) } - actual fun readLong(): Long = runBlocking { _readChannel.readLong() } -} - -internal actual class WriteChannel { - private val _writeChannel: ByteWriteChannel - - constructor(writeChannel: ByteWriteChannel) { - _writeChannel = writeChannel - } - - actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) = - runBlocking { _writeChannel.writeFully(value, startIndex, endIndex) } - - actual fun flush() = runBlocking { _writeChannel.flush() } -} \ No newline at end of file