From 8ff64d4a7fda08b09f26b5b1e4c1ab1da0465e88 Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 16 Jun 2023 13:40:46 +0100 Subject: [PATCH] Remove native (#2700) * Remove native target * Add foojay-resolver-convention * disable windows --- .github/codegen/generate-build-native.ws.kts | 88 --- .github/workflows/build.yml | 270 +-------- .github/workflows/check-publishing.yml | 4 +- .github/workflows/release.yml | 168 ------ .run/Build mirai-core for Host Native.run.xml | 33 -- ...rai-core libraries for host Native.run.xml | 34 -- .run/Run Native Main host.run.xml | 40 -- .run/Run Native Main linuxX64.run.xml | 40 -- .run/Run Native Main macosArm64.run.xml | 40 -- .run/Run Native Main macosX64.run.xml | 40 -- .run/Run Native Main mingwX64.run.xml | 40 -- .run/Test mirai-core for host Native.run.xml | 33 -- ...est mirai-core-api for host Native.run.xml | 33 -- ...t mirai-core-utils for host Native.run.xml | 33 -- buildSrc/src/main/kotlin/HmppConfigure.kt | 452 --------------- docs/ConfiguringMultiplatformProjects.md | 16 +- docs/contributing/README.md | 54 +- docs/contributing/SimpleInstructions.md | 2 - .../building/BuildingCoreNative.md | 194 ------- docs/contributing/building/README.md | 4 - gradle.properties | 2 - .../compiler-annotations/build.gradle.kts | 1 - mirai-core-api/build.gradle.kts | 7 - .../announcement/OfflineAnnouncement.kt | 10 +- .../src/commonMain/kotlin/message/data/At.kt | 7 +- .../commonMain/kotlin/message/data/Audio.kt | 9 +- .../kotlin/message/data/FileMessage.kt | 6 - .../kotlin/message/data/FlashImage.kt | 4 - .../commonMain/kotlin/message/data/Image.kt | 7 - .../kotlin/message/data/UnsupportedMessage.kt | 8 +- .../kotlin/utils/BotConfiguration.kt | 3 - .../src/nativeMain/kotlin/contact/Contact.kt | 107 ---- .../kotlin/contact/FileSupported.kt | 33 -- .../kotlin/contact/file/AbsoluteFolder.kt | 153 ----- .../kotlin/contact/roaming/RoamingMessages.kt | 71 --- .../nativeMain/kotlin/event/EventChannel.kt | 530 ----------------- .../kotlin/event/MessageSelectBuilderUnit.kt | 27 - .../message/overwritePolymorphicWith.kt | 21 - .../utils/ExternalResourceImplByByteArray.kt | 37 -- .../kotlin/internal/utils/Marker.kt | 21 - .../kotlin/internal/utils/MarkerManager.kt | 16 - .../message/action/AsyncRecallResult.kt | 69 --- .../kotlin/message/data/FileMessage.kt | 110 ---- .../src/nativeMain/kotlin/package.kt | 10 - .../kotlin/utils/BotConfiguration.kt | 73 --- .../src/nativeMain/kotlin/utils/DeviceInfo.kt | 144 ----- .../kotlin/utils/ExternalResource.kt | 273 --------- .../kotlin/utils/FileCacheStrategy.kt | 53 -- .../nativeMain/kotlin/utils/LoginSolver.kt | 15 - .../nativeMain/kotlin/utils/MiraiLogger.kt | 188 ------ .../nativeMain/kotlin/utils/PlatformLogger.kt | 70 --- .../src/nativeMain/kotlin/utils/Streamable.kt | 39 -- mirai-core-utils/build.gradle.kts | 16 - .../src/mingwX64Main/kotlin/MiraiFileImpl.kt | 343 ----------- .../src/mingwX64Main/kotlin/StandardUtils.kt | 16 - .../mingwX64Test/kotlin/MiraiFileImplTest.kt | 46 -- .../src/nativeMain/kotlin/Base64.kt | 116 ---- .../src/nativeMain/kotlin/ByteArrayOp.kt | 341 ----------- .../src/nativeMain/kotlin/Clock.kt | 18 - .../src/nativeMain/kotlin/Closeable.kt | 21 - .../src/nativeMain/kotlin/Collections.kt | 260 --------- .../src/nativeMain/kotlin/CommonDigest.kt | 350 ------------ .../src/nativeMain/kotlin/CoroutineUtils.kt | 72 --- .../nativeMain/kotlin/ExceptionCollector.kt | 22 - .../src/nativeMain/kotlin/MiraiFile.kt | 225 -------- .../kotlin/NativePlatformSupport.kt | 21 - .../nativeMain/kotlin/SecretsProtection.kt | 47 -- .../src/nativeMain/kotlin/Service.kt | 31 - .../src/nativeMain/kotlin/StandardUtils.kt | 17 - .../kotlin/StructureToStringTransformer.kt | 14 - .../src/nativeMain/kotlin/TimeUtils.kt | 58 -- .../src/nativeMain/kotlin/cipher.rs | 0 .../src/nativeMain/kotlin/getProperty.kt | 20 - .../src/nativeMainInterop/.gitignore | 8 - .../src/nativeMainInterop/Cargo.toml | 19 - .../src/nativeMainInterop/build.rs | 32 -- .../src/nativeMainInterop/cbindgen.toml | 10 - .../src/nativeMainInterop/interop.def | 0 .../src/nativeMainInterop/src/chmap.rs | 27 - .../src/nativeMainInterop/src/crypto.rs | 125 ---- .../src/nativeMainInterop/src/lib.rs | 20 - .../kotlin/AbstractNativeMiraiFileImplTest.kt | 183 ------ .../src/nativeTest/kotlin/ByteArrayOpTest.kt | 72 --- .../src/nativeTest/kotlin/CollectionsTest.kt | 41 -- .../src/nativeTest/kotlin/TimeUtilsTest.kt | 83 --- .../src/nativeTest/kotlin/package.kt | 10 - .../src/unixMain/kotlin/MiraiFileImpl.kt | 187 ------ .../src/unixMain/kotlin/StandardUtils.kt | 18 - .../unixTest/kotlin/UnixMiraiFileImplTest.kt | 49 -- mirai-core/build.gradle.kts | 94 --- .../components/QRCodeLoginProcessor.kt | 1 - .../kotlin/test/NativeTestWrapper.kt | 24 - .../kotlin/testFramework/Platform.kt | 15 - mirai-core/src/darwinMain/kotlin/MiraiImpl.kt | 24 - mirai-core/src/darwinMain/kotlin/package.kt | 10 - mirai-core/src/darwinTest/kotlin/package.kt | 10 - .../kotlin/test/NativeTestWrapper.kt | 3 +- .../src/linuxX64Main/kotlin/MiraiImpl.kt | 24 - mirai-core/src/linuxX64Main/kotlin/package.kt | 10 - mirai-core/src/linuxX64Test/kotlin/package.kt | 10 - .../kotlin/testFramework/currentPlatform.kt | 12 - .../src/macosArm64Test/kotlin/package.kt | 10 - .../kotlin/testFramework/currentPlatform.kt | 12 - mirai-core/src/macosX64Test/kotlin/package.kt | 10 - .../kotlin/testFramework/currentPlatform.kt | 12 - .../src/mingwX64Main/cinterop/Socket.def | 38 -- .../src/mingwX64Main/kotlin/MiraiImpl.kt | 24 - mirai-core/src/mingwX64Main/kotlin/package.kt | 10 - .../kotlin/utils/PlatformSocket.kt | 122 ---- mirai-core/src/mingwX64Test/kotlin/package.kt | 10 - .../kotlin/testFramework/currentPlatform.kt | 12 - .../src/nativeMain/cinterop/OpenSSL.def | 73 --- mirai-core/src/nativeMain/kotlin/MiraiImpl.kt | 34 -- .../nativeMain/kotlin/contact/GroupImpl.kt | 26 - .../kotlin/contact/active/GroupActiveImpl.kt | 20 - .../kotlin/contact/file/AbsoluteFolderImpl.kt | 24 - .../protocol/impl/getEmojiPatternResource.kt | 14 - .../component/getComponentTypeArgument.kt | 14 - .../handler/LengthDelimitedPacketReader.kt | 120 ---- .../network/handler/NativeNetworkHandler.kt | 113 ---- .../network/handler/NetworkHandlerFactory.kt | 33 -- .../kotlin/network/handler/SocketAddress.kt | 31 - .../SelectorRequireReconnectException.kt | 12 - .../data/richstatus/parseRichStatusImpl.kt | 14 - mirai-core/src/nativeMain/kotlin/package.kt | 10 - .../nativeMain/kotlin/utils/PlatformSocket.kt | 28 - .../kotlin/utils/crypto/AESNative.kt | 101 ---- .../kotlin/utils/crypto/EcdhNative.kt | 13 - .../kotlin/utils/crypto/OpenSslEcdh.kt | 147 ----- .../kotlin/utils/crypto/QQEcdhNative.kt | 15 - .../kotlin/utils/crypto/RSANative.kt | 299 ---------- .../nativeMain/kotlin/utils/freePointer.kt | 19 - .../kotlin/utils/getOpenSSLError.kt | 27 - mirai-core/src/nativeMain/kotlin/utils/ref.kt | 19 - .../nativeMain/kotlin/utils/workingDirPath.kt | 17 - mirai-core/src/nativeTest/.gitignore | 1 - .../src/nativeTest/kotlin/local/README.md | 8 - .../kotlin/local/TestMain.kt.template | 33 -- .../LengthDelimitedPacketReaderTest.kt | 538 ------------------ .../network/framework/AbstractCommonNHTest.kt | 39 -- mirai-core/src/nativeTest/kotlin/package.kt | 10 - .../kotlin/test/NativeTestWrapper.kt | 21 - .../kotlin/test/PlatformInitializationTest.kt | 36 -- .../kotlin/testFramework/DebugProbes.kt | 129 ----- .../kotlin/testFramework/DynamicTest.kt | 32 -- mirai-core/src/unixMain/cinterop/Socket.def | 30 - mirai-core/src/unixMain/kotlin/package.kt | 10 - .../unixMain/kotlin/utils/PlatformSocket.kt | 172 ------ mirai-deps-test/README.md | 2 +- mirai-deps-test/test/AbstractTest.kt | 2 - .../test/CoreDependencyResolutionTest.kt | 53 +- settings.gradle.kts | 4 + 152 files changed, 55 insertions(+), 9465 deletions(-) delete mode 100644 .github/codegen/generate-build-native.ws.kts delete mode 100644 .run/Build mirai-core for Host Native.run.xml delete mode 100644 .run/Build mirai-core libraries for host Native.run.xml delete mode 100644 .run/Run Native Main host.run.xml delete mode 100644 .run/Run Native Main linuxX64.run.xml delete mode 100644 .run/Run Native Main macosArm64.run.xml delete mode 100644 .run/Run Native Main macosX64.run.xml delete mode 100644 .run/Run Native Main mingwX64.run.xml delete mode 100644 .run/Test mirai-core for host Native.run.xml delete mode 100644 .run/Test mirai-core-api for host Native.run.xml delete mode 100644 .run/Test mirai-core-utils for host Native.run.xml delete mode 100644 docs/contributing/building/BuildingCoreNative.md delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/Contact.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/FileSupported.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/file/AbsoluteFolder.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/contact/roaming/RoamingMessages.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/event/EventChannel.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/event/MessageSelectBuilderUnit.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/internal/message/overwritePolymorphicWith.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/internal/utils/ExternalResourceImplByByteArray.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/internal/utils/Marker.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/internal/utils/MarkerManager.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/message/action/AsyncRecallResult.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/message/data/FileMessage.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/package.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/DeviceInfo.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/ExternalResource.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/FileCacheStrategy.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/LoginSolver.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/MiraiLogger.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/PlatformLogger.kt delete mode 100644 mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt delete mode 100644 mirai-core-utils/src/mingwX64Main/kotlin/MiraiFileImpl.kt delete mode 100644 mirai-core-utils/src/mingwX64Main/kotlin/StandardUtils.kt delete mode 100644 mirai-core-utils/src/mingwX64Test/kotlin/MiraiFileImplTest.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/Base64.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/Clock.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/Closeable.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/Collections.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/CommonDigest.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/CoroutineUtils.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/ExceptionCollector.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/NativePlatformSupport.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/SecretsProtection.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/Service.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/StructureToStringTransformer.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/TimeUtils.kt delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/cipher.rs delete mode 100644 mirai-core-utils/src/nativeMain/kotlin/getProperty.kt delete mode 100644 mirai-core-utils/src/nativeMainInterop/.gitignore delete mode 100644 mirai-core-utils/src/nativeMainInterop/Cargo.toml delete mode 100644 mirai-core-utils/src/nativeMainInterop/build.rs delete mode 100644 mirai-core-utils/src/nativeMainInterop/cbindgen.toml delete mode 100644 mirai-core-utils/src/nativeMainInterop/interop.def delete mode 100644 mirai-core-utils/src/nativeMainInterop/src/chmap.rs delete mode 100644 mirai-core-utils/src/nativeMainInterop/src/crypto.rs delete mode 100644 mirai-core-utils/src/nativeMainInterop/src/lib.rs delete mode 100644 mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt delete mode 100644 mirai-core-utils/src/nativeTest/kotlin/ByteArrayOpTest.kt delete mode 100644 mirai-core-utils/src/nativeTest/kotlin/CollectionsTest.kt delete mode 100644 mirai-core-utils/src/nativeTest/kotlin/TimeUtilsTest.kt delete mode 100644 mirai-core-utils/src/nativeTest/kotlin/package.kt delete mode 100644 mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt delete mode 100644 mirai-core-utils/src/unixMain/kotlin/StandardUtils.kt delete mode 100644 mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt delete mode 100644 mirai-core/src/commonTest/kotlin/test/NativeTestWrapper.kt delete mode 100644 mirai-core/src/darwinMain/kotlin/MiraiImpl.kt delete mode 100644 mirai-core/src/darwinMain/kotlin/package.kt delete mode 100644 mirai-core/src/darwinTest/kotlin/package.kt delete mode 100644 mirai-core/src/linuxX64Main/kotlin/MiraiImpl.kt delete mode 100644 mirai-core/src/linuxX64Main/kotlin/package.kt delete mode 100644 mirai-core/src/linuxX64Test/kotlin/package.kt delete mode 100644 mirai-core/src/linuxX64Test/kotlin/testFramework/currentPlatform.kt delete mode 100644 mirai-core/src/macosArm64Test/kotlin/package.kt delete mode 100644 mirai-core/src/macosArm64Test/kotlin/testFramework/currentPlatform.kt delete mode 100644 mirai-core/src/macosX64Test/kotlin/package.kt delete mode 100644 mirai-core/src/macosX64Test/kotlin/testFramework/currentPlatform.kt delete mode 100644 mirai-core/src/mingwX64Main/cinterop/Socket.def delete mode 100644 mirai-core/src/mingwX64Main/kotlin/MiraiImpl.kt delete mode 100644 mirai-core/src/mingwX64Main/kotlin/package.kt delete mode 100644 mirai-core/src/mingwX64Main/kotlin/utils/PlatformSocket.kt delete mode 100644 mirai-core/src/mingwX64Test/kotlin/package.kt delete mode 100644 mirai-core/src/mingwX64Test/kotlin/testFramework/currentPlatform.kt delete mode 100644 mirai-core/src/nativeMain/cinterop/OpenSSL.def delete mode 100644 mirai-core/src/nativeMain/kotlin/MiraiImpl.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/contact/GroupImpl.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/contact/active/GroupActiveImpl.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/contact/file/AbsoluteFolderImpl.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/message/protocol/impl/getEmojiPatternResource.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/component/getComponentTypeArgument.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/handler/LengthDelimitedPacketReader.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/handler/NativeNetworkHandler.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/handler/NetworkHandlerFactory.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/handler/SocketAddress.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/handler/selector/SelectorRequireReconnectException.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/network/protocol/data/richstatus/parseRichStatusImpl.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/package.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/PlatformSocket.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/crypto/AESNative.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/crypto/EcdhNative.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/crypto/OpenSslEcdh.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/crypto/QQEcdhNative.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/crypto/RSANative.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/freePointer.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/getOpenSSLError.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/ref.kt delete mode 100644 mirai-core/src/nativeMain/kotlin/utils/workingDirPath.kt delete mode 100644 mirai-core/src/nativeTest/.gitignore delete mode 100644 mirai-core/src/nativeTest/kotlin/local/README.md delete mode 100644 mirai-core/src/nativeTest/kotlin/local/TestMain.kt.template delete mode 100644 mirai-core/src/nativeTest/kotlin/network/LengthDelimitedPacketReaderTest.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/network/framework/AbstractCommonNHTest.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/package.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/test/NativeTestWrapper.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/test/PlatformInitializationTest.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/testFramework/DebugProbes.kt delete mode 100644 mirai-core/src/nativeTest/kotlin/testFramework/DynamicTest.kt delete mode 100644 mirai-core/src/unixMain/cinterop/Socket.def delete mode 100644 mirai-core/src/unixMain/kotlin/package.kt delete mode 100644 mirai-core/src/unixMain/kotlin/utils/PlatformSocket.kt diff --git a/.github/codegen/generate-build-native.ws.kts b/.github/codegen/generate-build-native.ws.kts deleted file mode 100644 index 3e06cee0c..000000000 --- a/.github/codegen/generate-build-native.ws.kts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 - */ - -val env = "\${{ env.gradleArgs }}" - -val isUbunutu = "\${{ env.isUbuntu == 'true' }}" -val isWindows = "\${{ env.isWindows == 'true' }}" -val isMac = "\${{ env.isMac == 'true' }}" - - -val template = """ - - if: CONDITION - name: "Compile mirai-core-api for macosArm64" - run: ./gradlew :mirai-core-api:compileKotlinMacosArm64 :mirai-core-api:compileTestKotlinMacosArm64 $env - - - if: CONDITION - name: "Link mirai-core-api for macosArm64" - run: ./gradlew mirai-core-api:linkDebugTestMacosArm64 $env - - - if: CONDITION - name: "Test mirai-core-api for macosArm64" - run: ./gradlew :mirai-core-api:macosArm64Test $env -""".trimIndent() - -val output = buildString { - val title = "############# GENERATED FROM generate-build-native.ws.kts #############" - appendLine("#".repeat(title.length)) - appendLine(title) - appendLine("#".repeat(title.length)) - appendLine() - - - - listOf("mirai-core-utils", "mirai-core-api", "mirai-core").forEach { moduleName -> - appendLine( - """ - - name: "Commonize mirai-core-api" - run: ./gradlew :mirai-core-api:commonize $env - """.trimIndent().replace("mirai-core-api", moduleName) - ) - appendLine() - } - - listOf("mirai-core-utils", "mirai-core-api", "mirai-core").forEach { moduleName -> - appendLine("# $moduleName") - appendLine() - appendLine( - """ - - name: "Compile mirai-core-api for common" - run: ./gradlew :mirai-core-api:compileCommonMainKotlinMetadata $env - - - name: "Compile mirai-core-api for native" - run: ./gradlew :mirai-core-api:compileNativeMainKotlinMetadata $env - - - name: "Compile mirai-core-api for unix-like" - run: ./gradlew :mirai-core-api:compileUnixMainKotlinMetadata $env - """.trimIndent().replace("mirai-core-api", moduleName) - ) - appendLine() - - listOf("macosX64" to isMac, "mingwX64" to isWindows, "linuxX64" to isUbunutu).forEach { (target, condition) -> - appendLine(useTemplate(moduleName, target, condition)) - appendLine() - appendLine() - } - appendLine() - } - - this.trimEnd().let { c -> clear().appendLine(c) } // remove trailing empty lines - - appendLine() - appendLine("#".repeat(title.length)) -} -println(output.prependIndent(" ".repeat(6))) - -fun useTemplate(moduleName: String, target: String, condition: String) = template - .replace("mirai-core-api", moduleName) - .replace("macosArm64", target) - .replace("MacosArm64", target.replaceFirstChar { it.uppercaseChar() }) - .replace("CONDITION", condition) - // Link release artifacts to save memory - .replace("linkDebugTestMingwX64", "linkReleaseTestMingwX64") diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 869f122db..bd3f96d87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,8 +14,8 @@ on: - '**/*.md' jobs: - build-mirai-jvm: - name: "JVM (${{ matrix.os }})" + build: + name: "Build (${{ matrix.os }})" runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -24,7 +24,7 @@ jobs: # - windows-2022 - macos-12 env: - gradleArgs: --scan "-Dmirai.target=jvm;android;!other" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx6000m" "-Dfile.encoding=UTF-8" + gradleArgs: --scan isMac: ${{ startsWith(matrix.os, 'macos') }} isWindows: ${{ startsWith(matrix.os, 'windows') }} isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }} @@ -77,6 +77,24 @@ jobs: - name: "Check" run: ./gradlew check ${{ env.gradleArgs }} + # Snapshots + + - if: ${{ env.isMac == 'true' }} + name: Ensure KDoc valid + run: ./gradlew dokkaHtmlMultiModule ${{ env.gradleArgs }} + + - name: Release RAM + run: node ci-release-helper/scripts/kill-java.js + + - name: Publish Snapshots + if: ${{ github.event.pusher && env.isMac == 'true' && vars.RUN_MIRAI_SNAPSHOTS == 'true' }} + run: ./gradlew publishAllPublicationsToMiraiRepoRepository ${{ env.gradleArgs }} + env: + MIRAI_IS_SNAPSHOTS_PUBLISHING: true + SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} + SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} + SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} + # Upload - name: Upload mirai-core-utils @@ -156,249 +174,3 @@ jobs: with: name: mirai-logging-slf4j-simple path: logging/mirai-logging-slf4j-simple/build/libs - - build-mirai-all: - name: "Everything (${{ matrix.os }})" - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - macos-12 - env: - enableLocalPublishingTest: 'false' - gradleArgs: --scan - isMac: ${{ startsWith(matrix.os, 'macos') }} - isWindows: ${{ startsWith(matrix.os, 'windows') }} - isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }} - isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }} - steps: - - uses: actions/checkout@v3 - with: - submodules: 'recursive' - - - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '17' - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Cache konan - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - if: ${{ env.isUnix == 'true' }} - run: chmod -R 777 * - - - name: Clean and download dependencies - run: ./gradlew clean ${{ env.gradleArgs }} - - - run: > - ./gradlew updateSnapshotVersion ${{ env.gradleArgs }} - if: github.event.pusher && vars.RUN_MIRAI_SNAPSHOTS == 'true' - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - MIRAI_BUILD_INDEX_AUTH_USERNAME: ${{ secrets.MIRAI_BUILD_INDEX_AUTH_USERNAME }} - MIRAI_BUILD_INDEX_AUTH_PASSWORD: ${{ secrets.MIRAI_BUILD_INDEX_AUTH_PASSWORD }} - - - name: "Assemble" - run: ./gradlew assemble ${{ env.gradleArgs }} - - - name: Publish Local Artifacts - if: ${{ env.enableLocalPublishingTest == 'true' }} - run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test" - - - name: "Check" - run: ./gradlew check ${{ env.gradleArgs }} - - - if: ${{ env.isMac == 'true' }} - name: Ensure KDoc valid - run: ./gradlew dokkaHtmlMultiModule ${{ env.gradleArgs }} - - - name: Release RAM - run: node ci-release-helper/scripts/kill-java.js - - - name: Publish Snapshots - if: ${{ github.event.pusher && env.isMac == 'true' && vars.RUN_MIRAI_SNAPSHOTS == 'true' }} - run: ./gradlew publishAllPublicationsToMiraiRepoRepository ${{ env.gradleArgs }} - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - - build-mirai-core-native: - name: "Native (${{ matrix.os }})" - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - windows-2022 - - ubuntu-20.04 - # - ubuntu-18.04 - # - macos-12 - # - macos-11 - include: - - os: windows-2022 - targetName: mingwX64 - - os: ubuntu-20.04 - targetName: linuxX64 - # - os: macos-12 - # targetName: macosX64 - # - os: macos-11 - # targetName: macosX64 - env: - # FIXME there must be two or more targets, or we'll get error on `@OptionalExpectation` - # > Declaration annotated with '@OptionalExpectation' can only be used in common module sources - enableLocalPublishingTest: 'false' - gradleArgs: --scan "-Dmirai.target=jvm;${{ matrix.targetName }};!other" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8" - isMac: ${{ startsWith(matrix.os, 'macos') }} - isWindows: ${{ startsWith(matrix.os, 'windows') }} - isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }} - isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }} - VCPKG_DEFAULT_BINARY_CACHE: ${{ startsWith(matrix.os, 'windows') && 'C:\vcpkg\binary_cache' || '/usr/local/share/vcpkg/binary_cache' }} - steps: - - uses: actions/checkout@v3 - with: - submodules: 'recursive' - - - uses: actions/setup-java@v3 - with: - distribution: 'adopt-openj9' - java-version: '17' - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Cache konan - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Prepare to cache vcpkg - if: ${{ env.isWindows == 'true' }} - run: mkdir -p ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} - - - name: Cache vcpkg - if: ${{ env.isWindows == 'true' }} - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} - key: ${{ runner.os }}-vcpkg-binary-cache-${{ github.job }} - restore-keys: | - ${{ runner.os }}-vcpkg-binary-cache- - - - if: ${{ env.isUnix == 'true' }} - run: chmod -R 777 * - - # Prepare environment for linking on macOS - - if: ${{ env.isMac == 'true' }} - name: Install OpenSSL on Mac OS - run: > - git clone https://github.com/openssl/openssl.git --recursive && - cd openssl && - git checkout tags/openssl-3.0.3 && - ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl && - make && - sudo make install - - # Prepare environment for linking on Ubuntu - - if: ${{ env.isUbuntu == 'true' }} - name: Install OpenSSL on Ubuntu - run: sudo apt install libssl-dev -y - - # Prepare environment for linking on Windows - - if: ${{ env.isWindows == 'true' }} - name: Setup Memory Environment on Windows - run: > - wmic pagefileset where name="D:\\pagefile.sys" set InitialSize=1024,MaximumSize=9216 & - net stop mongodb - shell: cmd - continue-on-error: true - - - if: ${{ env.isWindows == 'true' }} - name: Install OpenSSL & cURL on Windows - run: | - echo "set(VCPKG_BUILD_TYPE release)" | Out-File -FilePath "$env:VCPKG_INSTALLATION_ROOT\triplets\x64-windows.cmake" -Encoding utf8 -Append - vcpkg install openssl:x64-windows curl[core,ssl]:x64-windows - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\crypto.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcrypto.lib - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\ssl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libssl.lib - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\curl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcurl.lib - echo "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Clean and download dependencies - run: ./gradlew clean ${{ env.gradleArgs }} - - - run: > - ./gradlew updateSnapshotVersion ${{ env.gradleArgs }} - if: github.event.pusher && vars.RUN_MIRAI_SNAPSHOTS == 'true' - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - MIRAI_BUILD_INDEX_AUTH_USERNAME: ${{ secrets.MIRAI_BUILD_INDEX_AUTH_USERNAME }} - MIRAI_BUILD_INDEX_AUTH_PASSWORD: ${{ secrets.MIRAI_BUILD_INDEX_AUTH_PASSWORD }} - - - name: "Test mirai-core-utils for ${{ matrix.os }}" - run: ./gradlew :mirai-core-utils:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: "Test mirai-core-api for ${{ matrix.os }}" - run: ./gradlew :mirai-core-api:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: "Test mirai-core for ${{ matrix.os }}" - run: ./gradlew :mirai-core:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: Publish Local Artifacts - if: ${{ env.enableLocalPublishingTest == 'true' }} - run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test" - - - name: Check Publication - if: ${{ env.enableLocalPublishingTest == 'true' }} - run: ./gradlew :mirai-deps-test:check ${{ env.gradleArgs }} - - # Publish native snapshots. Other artifacts are published in build-mirai-all - - - name: Release RAM - run: node ci-release-helper/scripts/kill-java.js - - - name: Publish MingwX64 Snapshots - if: ${{ github.event.pusher && env.isWindows == 'true' && vars.RUN_MIRAI_SNAPSHOTS == 'true' }} - run: ./gradlew publishMingwX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }} - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - - - name: Publish LinuxX64 Snapshots - if: ${{ github.event.pusher && env.isUbuntu == 'true' && vars.RUN_MIRAI_SNAPSHOTS == 'true' }} - run: ./gradlew publishLinuxX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }} - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - - - name: Publish macOSX64 Snapshots - if: ${{ github.event.pusher && env.isMac == 'true' && vars.RUN_MIRAI_SNAPSHOTS == 'true' }} - run: ./gradlew publishMacosX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }} - env: - MIRAI_IS_SNAPSHOTS_PUBLISHING: true - SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }} - SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }} - SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }} - diff --git a/.github/workflows/check-publishing.yml b/.github/workflows/check-publishing.yml index d671c6087..fbb239b97 100644 --- a/.github/workflows/check-publishing.yml +++ b/.github/workflows/check-publishing.yml @@ -25,7 +25,7 @@ jobs: fail-fast: false matrix: os: -# - windows-2022 + # - windows-2022 # OOM - ubuntu-20.04 - macos-12 include: @@ -41,7 +41,7 @@ jobs: env: # FIXME there must be two or more targets, or we'll get error on `@OptionalExpectation` # > Declaration annotated with '@OptionalExpectation' can only be used in common module sources - gradleArgs: --scan "-Dmirai.target=jvm;${{ matrix.targetName }};~others" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx4096m" "-Dfile.encoding=UTF-8" + gradleArgs: --scan isMac: ${{ startsWith(matrix.os, 'macos') }} isWindows: ${{ startsWith(matrix.os, 'windows') }} isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e870aef6f..9cb2d4922 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -102,16 +102,6 @@ jobs: # Prepare environment for linking for macOS - - if: ${{ env.isMac == 'true' }} - name: Install OpenSSL - run: > - git clone https://github.com/openssl/openssl.git --recursive && - cd openssl && - git checkout tags/openssl-3.0.3 && - ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl && - make && - sudo make install - - name: Clean and download dependencies run: ./gradlew clean ${{ env.gradleArgs }} @@ -155,164 +145,6 @@ jobs: -Dgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }} -Pgradle.publish.secret=${{ secrets.GRADLE_PUBLISH_SECRET }} continue-on-error: true - publish-core-native: - name: "Native (${{ matrix.os }})" - needs: [ publish-others ] # Allow MPP metadata to be uploaded first. - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: - - windows-2022 - - ubuntu-20.04 - # - macos-12 # macOS artifacts published in 'publish-others' - include: - - os: windows-2022 - targetName: mingwX64 - # parallelCompilation: false - - os: ubuntu-20.04 - targetName: linuxX64 - # parallelCompilation: false - - os: macos-12 - targetName: macosX64 - # parallelCompilation: true # macOS machine has 14G - env: - # FIXME there must be two or more targets, or we'll get error on `@OptionalExpectation` - # > Declaration annotated with '@OptionalExpectation' can only be used in common module sources - gradleArgs: --scan "-Dmirai.target=jvm;${{ matrix.targetName }};~other" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx4096m" "-Dfile.encoding=UTF-8" - isMac: ${{ startsWith(matrix.os, 'macos') }} - isWindows: ${{ startsWith(matrix.os, 'windows') }} - isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }} - isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }} - VCPKG_DEFAULT_BINARY_CACHE: ${{ startsWith(matrix.os, 'windows') && 'C:\vcpkg\binary_cache' || '/usr/local/share/vcpkg/binary_cache' }} - steps: - - uses: actions/checkout@v3 - with: - submodules: 'recursive' - - - uses: actions/setup-java@v3 - with: - distribution: 'adopt-openj9' - java-version: '17' - - - name: Keys setup - shell: bash - run: | - mkdir build-gpg-sign - echo "$GPG_PRIVATE" > build-gpg-sign/keys.gpg - echo "$GPG_PUBLIC_" > build-gpg-sign/keys.gpg.pub - env: - GPG_PRIVATE: ${{ secrets.GPG_PRIVATE_KEY }} - GPG_PUBLIC_: ${{ secrets.GPG_PUBLIC_KEY }} - - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - - name: Cache konan - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Prepare to cache vcpkg - if: ${{ env.isWindows == 'true' }} - run: mkdir -p ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} - - - name: Cache vcpkg - if: ${{ env.isWindows == 'true' }} - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} - key: ${{ runner.os }}-vcpkg-binary-cache-${{ github.job }} - restore-keys: | - ${{ runner.os }}-vcpkg-binary-cache- - - - if: ${{ env.isUnix == 'true' }} - run: chmod -R 777 * - - # Prepare environment for linking on macOS - - if: ${{ env.isMac == 'true' }} - name: Install OpenSSL on Mac OS - run: > - git clone https://github.com/openssl/openssl.git --recursive && - cd openssl && - git checkout tags/openssl-3.0.3 && - ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl && - make && - sudo make install - - # Prepare environment for linking on Ubuntu - - if: ${{ env.isUbuntu == 'true' }} - name: Install OpenSSL on Ubuntu - run: sudo apt install libssl-dev -y - - # Prepare environment for linking on Windows - - if: ${{ env.isWindows == 'true' }} - name: Setup Memory Environment on Windows - run: > - wmic pagefileset where name="D:\\pagefile.sys" set InitialSize=1024,MaximumSize=9216 & - net stop mongodb - shell: cmd - continue-on-error: true - - - if: ${{ env.isWindows == 'true' }} - name: Install OpenSSL & cURL on Windows - run: | - echo "set(VCPKG_BUILD_TYPE release)" | Out-File -FilePath "$env:VCPKG_INSTALLATION_ROOT\triplets\x64-windows.cmake" -Encoding utf8 -Append - vcpkg install openssl:x64-windows curl[core,ssl]:x64-windows - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\crypto.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcrypto.lib - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\ssl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libssl.lib - New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\curl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcurl.lib - echo "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - - name: Clean and download dependencies - run: ./gradlew clean ${{ env.gradleArgs }} - - - name: "Test mirai-core-utils for ${{ matrix.os }}" - run: ./gradlew :mirai-core-utils:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: "Test mirai-core-api for ${{ matrix.os }}" - run: ./gradlew :mirai-core-api:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: "Test mirai-core for ${{ matrix.os }}" - run: ./gradlew :mirai-core:${{ matrix.targetName }}Test ${{ env.gradleArgs }} - - - name: Initialize Publishing Caching Repository - run: ./gradlew runcihelper --args sync-maven-metadata ${{ env.gradleArgs }} - - - name: Release RAM - run: node ci-release-helper/scripts/kill-java.js - - # # Parallel compilation will exhaust machine memory causing OOM - # - name: Assemble - # run: ./gradlew assemble ${{ env.gradleArgs }} "-Porg.gradle.parallel=${{ matrix.parallelCompilation }}" - - - name: Publish MingwX64 - if: ${{ env.isWindows == 'true' }} - run: ./gradlew publishMingwX64PublicationToMiraiStageRepoRepository ${{ env.gradleArgs }} - - - name: Publish LinuxX64 - if: ${{ env.isUbuntu == 'true' }} - run: ./gradlew publishLinuxX64PublicationToMiraiStageRepoRepository ${{ env.gradleArgs }} - - - name: Publish macOSX64 - if: ${{ env.isMac == 'true' }} - run: ./gradlew publishMacosX64PublicationToMiraiStageRepoRepository ${{ env.gradleArgs }} - - - name: Restore staging repository id - uses: actions/download-artifact@v3 - with: - name: publish-stage-id - path: ci-release-helper/repoid - - - name: Release RAM - run: node ci-release-helper/scripts/kill-java.js - - - name: Publish to maven central - run: ./gradlew runcihelper --args publish-to-maven-central --scan "-Pcihelper.cert.username=${{ secrets.SONATYPE_USER }}" "-Pcihelper.cert.password=${{ secrets.SONATYPE_KEY }}" - # # close-repository: # runs-on: macos-12 diff --git a/.run/Build mirai-core for Host Native.run.xml b/.run/Build mirai-core for Host Native.run.xml deleted file mode 100644 index be73589ce..000000000 --- a/.run/Build mirai-core for Host Native.run.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/.run/Build mirai-core libraries for host Native.run.xml b/.run/Build mirai-core libraries for host Native.run.xml deleted file mode 100644 index ea9b32310..000000000 --- a/.run/Build mirai-core libraries for host Native.run.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/.run/Run Native Main host.run.xml b/.run/Run Native Main host.run.xml deleted file mode 100644 index bbeaadaa4..000000000 --- a/.run/Run Native Main host.run.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - false - true - false - - - \ No newline at end of file diff --git a/.run/Run Native Main linuxX64.run.xml b/.run/Run Native Main linuxX64.run.xml deleted file mode 100644 index 93e990033..000000000 --- a/.run/Run Native Main linuxX64.run.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - false - true - false - - - \ No newline at end of file diff --git a/.run/Run Native Main macosArm64.run.xml b/.run/Run Native Main macosArm64.run.xml deleted file mode 100644 index 73617a26c..000000000 --- a/.run/Run Native Main macosArm64.run.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - false - true - false - - - \ No newline at end of file diff --git a/.run/Run Native Main macosX64.run.xml b/.run/Run Native Main macosX64.run.xml deleted file mode 100644 index 4a79bce41..000000000 --- a/.run/Run Native Main macosX64.run.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - false - true - false - - - \ No newline at end of file diff --git a/.run/Run Native Main mingwX64.run.xml b/.run/Run Native Main mingwX64.run.xml deleted file mode 100644 index b9fe9a782..000000000 --- a/.run/Run Native Main mingwX64.run.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - false - true - false - - - \ No newline at end of file diff --git a/.run/Test mirai-core for host Native.run.xml b/.run/Test mirai-core for host Native.run.xml deleted file mode 100644 index c45827201..000000000 --- a/.run/Test mirai-core for host Native.run.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/.run/Test mirai-core-api for host Native.run.xml b/.run/Test mirai-core-api for host Native.run.xml deleted file mode 100644 index 1474c30f9..000000000 --- a/.run/Test mirai-core-api for host Native.run.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/.run/Test mirai-core-utils for host Native.run.xml b/.run/Test mirai-core-utils for host Native.run.xml deleted file mode 100644 index b2f2ba885..000000000 --- a/.run/Test mirai-core-utils for host Native.run.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - true - true - false - - - \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/HmppConfigure.kt b/buildSrc/src/main/kotlin/HmppConfigure.kt index b15fe8a6e..02b9906af 100644 --- a/buildSrc/src/main/kotlin/HmppConfigure.kt +++ b/buildSrc/src/main/kotlin/HmppConfigure.kt @@ -10,21 +10,10 @@ import com.google.gradle.osdetector.OsDetector import org.gradle.api.Project import org.gradle.api.attributes.Attribute -import org.gradle.kotlin.dsl.get import org.gradle.kotlin.dsl.getting import org.gradle.kotlin.dsl.provideDelegate -import org.gradle.kotlin.dsl.withType import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME -import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType -import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet -import org.jetbrains.kotlin.gradle.plugin.KotlinTarget -import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset -import org.jetbrains.kotlin.gradle.plugin.mpp.* -import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink -import java.io.File -import java.util.* val MIRAI_PLATFORM_ATTRIBUTE: Attribute = Attribute.of( "net.mamoe.mirai.platform", String::class.java @@ -78,10 +67,6 @@ val HOST_KIND by lazy { } } -enum class HostArch { - X86, X64, ARM32, ARM64 -} - /// eg. "!a;!b" means to enable all targets but a or b /// eg. "a;b;!other" means to disable all targets but a or b val ENABLED_TARGETS by projectLazy { @@ -98,16 +83,11 @@ fun getMiraiTargetFromGradle() = ?: "others" fun isTargetEnabled(name: String): Boolean { - val isNative = name in POSSIBLE_NATIVE_TARGETS return when { name in ENABLED_TARGETS -> true // explicitly enabled "!$name" in ENABLED_TARGETS -> false // explicitly disabled "~$name" in ENABLED_TARGETS -> false // explicitly disabled - "native" in ENABLED_TARGETS && isNative -> true // native targets explicitly enabled - "!native" in ENABLED_TARGETS && isNative -> false // native targets explicitly disabled - "~native" in ENABLED_TARGETS && isNative -> false // native targets explicitly disabled - "!other" in ENABLED_TARGETS -> false // others disabled "~other" in ENABLED_TARGETS -> false // others disabled "!others" in ENABLED_TARGETS -> false // others disabled @@ -119,41 +99,6 @@ fun isTargetEnabled(name: String): Boolean { fun Set.filterTargets() = this.filter { isTargetEnabled(it) }.toSet() -val MAC_TARGETS: Set by projectLazy { - setOf( -// "watchosX86", - "macosX64", - "macosArm64", - - // Failed to generate cinterop for :mirai-core:cinteropOpenSSLIosX64: Process 'command '/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1 - // Exception in thread "main" java.lang.Error: /var/folders/kw/ndw272ns06s7cys2mcwwlb5c0000gn/T/1181140105365175708.c:1:10: fatal error: 'openssl/ec.h' file not found - // - // Note: the openssl/ec.h is actually there, seems Kotlin doesn't support that - -// "iosX64", -// "iosArm64", -// "iosArm32", -// "iosSimulatorArm64", -// "watchosX64", -// "watchosArm32", -// "watchosArm64", -// "watchosSimulatorArm64", -// "tvosX64", -// "tvosArm64", -// "tvosSimulatorArm64", - ).filterTargets() -} - -val WIN_TARGETS by projectLazy { setOf("mingwX64").filterTargets() } - -val LINUX_TARGETS by projectLazy { setOf("linuxX64").filterTargets() } - -val UNIX_LIKE_TARGETS by projectLazy { LINUX_TARGETS + MAC_TARGETS } - -val NATIVE_TARGETS by projectLazy { UNIX_LIKE_TARGETS + WIN_TARGETS } - -private val POSSIBLE_NATIVE_TARGETS by lazy { setOf("mingwX64", "macosX64", "macosArm64", "linuxX64") } - const val JVM_TOOLCHAIN_VERSION = 8 val JVM_TOOLCHAIN_ENABLED by projectLazy { @@ -165,8 +110,6 @@ val JVM_TOOLCHAIN_ENABLED by projectLazy { * * 如果[启用 Android Instrumented Test][ENABLE_ANDROID_INSTRUMENTED_TESTS], 将会配置使用 Android SDK 配置真 Android target, * `androidMain` 将能访问 Android SDK, 也能获得针对 Android 的 IDE 错误检查. - * - * @see configureNativeTargetsHierarchical */ fun Project.configureJvmTargetsHierarchical(androidNamespace: String) { extensions.getByType(KotlinMultiplatformExtension::class.java).apply { @@ -220,401 +163,6 @@ fun Project.configureJvmTargetsHierarchical(androidNamespace: String) { } } - -/** - * Target 结构: - * ``` - * common - * | - * /---------------+---------------\ - * jvmBase native - * / \ / \ - * jvm android unix \ - * / \ mingwX64 - * / \ - * darwin linuxX64 - * | - * * - * - * ``` - * - * ``: macosX64, macosArm64 - * - * @see configureJvmTargetsHierarchical - */ -fun KotlinMultiplatformExtension.configureNativeTargetsHierarchical( - project: Project -) { - if (NATIVE_TARGETS.isEmpty()) return - - val nativeMainSets = mutableListOf() - val nativeTestSets = mutableListOf() - val nativeTargets = - mutableListOf() // actually KotlinNativeTarget, but KotlinNativeTarget is an internal API (complained by IDEA) - - - fun KotlinMultiplatformExtension.addNativeTarget( - preset: KotlinTargetPreset<*>, - ): KotlinTarget { - val target = targetFromPreset(preset, preset.name) - nativeMainSets.add(target.compilations[MAIN_COMPILATION_NAME].kotlinSourceSets.first()) - nativeTestSets.add(target.compilations[TEST_COMPILATION_NAME].kotlinSourceSets.first()) - nativeTargets.add(target) - return target - } - - - // project.configureNativeInterop("main", project.projectDir.resolve("src/nativeMainInterop"), nativeTargets) - // project.configureNativeInterop("test", project.projectDir.resolve("src/nativeTestInterop"), nativeTargets) - - - val sourceSets = project.objects.domainObjectContainer(KotlinSourceSet::class.java) - .apply { addAll(project.kotlinSourceSets.orEmpty()) } - - val commonMain by sourceSets.getting - val commonTest by sourceSets.getting - - val nativeMain by lazy { - this.sourceSets.maybeCreate("nativeMain").apply { - dependsOn(commonMain) - } - } - val nativeTest by lazy { - this.sourceSets.maybeCreate("nativeTest").apply { - dependsOn(commonTest) - } - } - - if (UNIX_LIKE_TARGETS.isNotEmpty()) { - val unixMain by lazy { - this.sourceSets.maybeCreate("unixMain").apply { - dependsOn(nativeMain) - } - } - val unixTest by lazy { - this.sourceSets.maybeCreate("unixTest").apply { - dependsOn(nativeTest) - } - } - - val darwinMain by lazy { - this.sourceSets.maybeCreate("darwinMain").apply { - dependsOn(unixMain) - } - } - val darwinTest by lazy { - this.sourceSets.maybeCreate("darwinTest").apply { - dependsOn(unixTest) - } - } - - presets.filter { it.name in MAC_TARGETS }.forEach { preset -> - addNativeTarget(preset).run { - compilations[MAIN_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(darwinMain) } - compilations[TEST_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(darwinTest) } - } - } - - presets.filter { it.name in LINUX_TARGETS }.forEach { preset -> - addNativeTarget(preset).run { - compilations[MAIN_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(unixMain) } - compilations[TEST_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(unixTest) } - } - } - } - - presets.filter { it.name in WIN_TARGETS }.forEach { preset -> - addNativeTarget(preset).run { - compilations[MAIN_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(nativeMain) } - compilations[TEST_COMPILATION_NAME].kotlinSourceSets.forEach { it.dependsOn(nativeTest) } - } - } - - // Workaround from https://youtrack.jetbrains.com/issue/KT-52433/KotlinNative-Unable-to-generate-framework-with-Kotlin-1621-and-Xcode-134#focus=Comments-27-6140143.0-0 - project.tasks.withType().configureEach { - val properties = listOf( - "ios_arm32", "watchos_arm32", "watchos_x86" - ).joinToString(separator = ";") { "clangDebugFlags.$it=-Os" } - kotlinOptions.freeCompilerArgs += listOf( - "-Xoverride-konan-properties=$properties" - ) - } - -// WIN_TARGETS.forEach { targetName -> -// val target = targets.getByName(targetName) as KotlinNativeTarget -// if (!IDEA_ACTIVE && HOST_KIND == HostKind.WINDOWS) { -// // add release test to run on CI -// project.afterEvaluate { -// target.findOrCreateTest(NativeBuildType.RELEASE) { -// // use linkReleaseTestMingwX64 for mingwX64Test to save memory -// tasks.getByName("mingwX64Test", KotlinNativeTest::class) -// .executable(linkTask) { linkTask.binary.outputFile } -// } -// } -// } -// } - - // Register platform tasks, e.g. linkDebugSharedHost - project.afterEvaluate { - val targetName = HOST_KIND.targetName - val targetNameCapitalized = targetName.capitalize() - project.tasks.run { - listOf( - "compileKotlin", - "linkDebugTest", - "linkReleaseTest", - "linkDebugShared", - "linkReleaseShared", - "linkDebugStatic", - "linkReleaseStatic", - ).forEach { name -> - findByName("$name$targetNameCapitalized")?.let { plat -> - register("${name}Host") { - group = "mirai" - description = "Run ${plat.name} which can be run on the current Host." - dependsOn(plat) - } - } - } - - findByName("${targetName}Test")?.let { plat -> - register("hostTest") { - group = "mirai" - description = "Run ${plat.name} which can be run on the current Host." - dependsOn(plat) - } - } - } - project.disableCrossCompile() // improve speed - } -} - -fun KotlinMultiplatformExtension.configureNativeTargetBinaries(project: Project) { - if (!System.getProperty("mirai.native.binaries", "false").toBoolean()) { - // Must enable KotlinNativeLink by argument "mirai.native.link". - - // :mirai-core:linkReleaseSharedMacosX64 - return -// disableNativeLinkTasks(project) - } - - NATIVE_TARGETS.forEach { targetName -> - val target = targets.getByName(targetName) as KotlinNativeTarget - target.binaries { - sharedLib(listOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)) { - baseName = project.name.lowercase(Locale.ROOT).replace("-", "") - } - staticLib(listOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)) { - baseName = project.name.lowercase(Locale.ROOT).replace("-", "") - } - } - } -} - -private fun disableNativeLinkTasks(project: Project) { - project.tasks.withType() - .filter { it.binary.outputKind != NativeOutputKind.TEST } - .forEach { - it.enabled = false - project.logger.warn("Disabling KotlinNativeLink: ${it.path}") - } -} - -private fun KotlinNativeTarget.findOrCreateTest(buildType: NativeBuildType, configure: TestExecutable.() -> Unit) = - binaries.findTest(buildType)?.apply(configure) ?: binaries.test(listOf(buildType), configure) - - -// e.g. Linker will try to link curl for mingwX64 but this can't be done on macOS. -fun Project.disableCrossCompile() { - project.afterEvaluate { - if (HOST_KIND != HostKind.MACOS_ARM64) { - disableTargetLink(this, HostKind.MACOS_ARM64.targetName) - } - if (HOST_KIND != HostKind.MACOS_X64) { - disableTargetLink(this, HostKind.MACOS_X64.targetName) - } - if (HOST_KIND != HostKind.WINDOWS) { - WIN_TARGETS.forEach { target -> disableTargetLink(this, target) } - } - if (HOST_KIND != HostKind.LINUX) { - LINUX_TARGETS.forEach { target -> disableTargetLink(this, target) } - } - } -} - -private fun disableTargetLink(project: Project, target: String) { - // Don't disable compileKotlin tasks. These tasks ensure code syntax is correct. - project.tasks.findByName("linkDebugTest${target.titlecase()}")?.enabled = false - project.tasks.findByName("linkReleaseTest${target.titlecase()}")?.enabled = false - project.tasks.findByName("linkDebugShared${target.titlecase()}")?.enabled = false - project.tasks.findByName("linkReleaseShared${target.titlecase()}")?.enabled = false - project.tasks.findByName("linkDebugStatic${target.titlecase()}")?.enabled = false - project.tasks.findByName("linkReleaseStatic${target.titlecase()}")?.enabled = false - project.tasks.findByName("${target}Test")?.enabled = false -} - -private fun Project.linkerDirs(): List { - return listOf( - ":mirai-core", - ":mirai-core-api", - ":mirai-core-utils", - ).map { - rootProject.project(it).projectDir.resolve("src/nativeMainInterop/target/debug/").absolutePath - } -} - -private fun Project.includeDirs(): List { - return listOf( - ":mirai-core", - ":mirai-core-api", - ":mirai-core-utils", - ).map { - rootProject.project(it).projectDir.resolve("src/nativeMainInterop/").absolutePath - } -} - -private fun Project.configureNativeInterop( - compilationName: String, nativeInteropDir: File, nativeTargets: MutableList -) { - val crateName = project.name.replace("-", "_") + "_i" - - if (nativeInteropDir.exists() && nativeInteropDir.isDirectory && nativeInteropDir.resolve("build.rs").exists()) { - val kotlinDylibName = project.name.replace("-", "_") + "_i" - - val headerName = "$crateName.h" - val rustLibDir = nativeInteropDir.resolve("target/debug/") - - var interopTaskName = "" - - configure(nativeTargets) { - interopTaskName = compilations.getByName(compilationName).cinterops.create(compilationName) { - defFile(nativeInteropDir.resolve("interop.def")) - val headerFile = nativeInteropDir.resolve(headerName) - if (headerFile.exists()) headers(headerFile) - }.interopProcessingTaskName - - binaries { - sharedLib { - linkerOpts("-v") - linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}") -// linkerOpts("-lmirai_core_utils_i") - linkerOpts("-undefined", "dynamic_lookup") - baseName = project.name - } - getTest(NativeBuildType.DEBUG).apply { - linkerOpts("-v") - linkerOpts("-L${rustLibDir.absolutePath.replace("\\", "/")}") - linkerOpts("-lmirai_core_utils_i") -// linkerOpts("-undefined", "dynamic_lookup") - } - } - } - - val cbindgen = tasks.register("cbindgen${compilationName.titlecase()}") { - group = "mirai" - description = "Generate C Headers from Rust" - inputs.files(project.objects.fileTree().from(nativeInteropDir.resolve("src")) - .filterNot { it.name == "bindings.rs" }) - outputs.file(nativeInteropDir.resolve(headerName)) - doLast { - exec { - workingDir(nativeInteropDir) - commandLine( - "cbindgen", "--config", "cbindgen.toml", "--crate", crateName, "--output", headerName - ) - } - } - } - - val generateRustBindings = tasks.register("generateRustBindings${compilationName.titlecase()}") { - group = "mirai" - description = "Generates Rust bindings for Kotlin" - dependsOn(cbindgen) - } - - afterEvaluate { - val cinteropTask = tasks.getByName(interopTaskName) - cinteropTask.mustRunAfter(cbindgen) - generateRustBindings.get().dependsOn(cinteropTask) - } - - val bindgen = tasks.register("bindgen${compilationName.titlecase()}") { - group = "mirai" - val bindingsPath = nativeInteropDir.resolve("src/bindings.rs") - val headerFile = buildDir.resolve("bin/native/debugShared/lib${kotlinDylibName}_api.h") - inputs.files(headerFile) - outputs.file(bindingsPath) - mustRunAfter(tasks.findByName("linkDebugSharedNative")) - doLast { - exec { - workingDir(nativeInteropDir) - // bindgen input.h -o bindings.rs - commandLine( - "bindgen", - headerFile, - "-o", bindingsPath, - ) - } - } - } - - tasks.register("generateKotlinBindings${compilationName.titlecase()}") { - group = "mirai" - description = "Generates Kotlin bindings for Rust" - dependsOn(bindgen) - dependsOn(tasks.findByName("linkDebugSharedNative")) - } - - var targetCompilation: KotlinNativeCompilation? = null - configure(nativeTargets) { - val compilations = compilations.filter { nativeInteropDir.name.contains(it.name, ignoreCase = true) } - check(compilations.isNotEmpty()) { "Should be at lease one corresponding native compilation, but found 0" } - targetCompilation = compilations.single() -// targetCompilation!!.compileKotlinTask.dependsOn(cbindgen) -// tasks.getByName("cinteropNative$name").dependsOn(cbindgen) - } - - if (targetCompilation != null) { - val compileRust = tasks.register("compileRust${compilationName.titlecase()}") { - group = "mirai" - inputs.files(nativeInteropDir.resolve("src")) - outputs.file(rustLibDir.resolve("lib$crateName.dylib")) -// dependsOn(targetCompilation!!.compileKotlinTask) - dependsOn(bindgen) - dependsOn(tasks.findByName("linkDebugSharedNative")) // dylib to link - doLast { - exec { - workingDir(nativeInteropDir) - commandLine( - "cargo", - "build", - "--color", "always", - "--all", -// "--", "--color", "always", "2>&1" - ) - } - } - } - - tasks.getByName("assemble").dependsOn(compileRust) - } - } -} - -private fun Project.configureNativeLinkOptions(nativeTargets: MutableList) { - configure(nativeTargets) { - binaries { - for (buildType in NativeBuildType.values()) { - findTest(buildType)?.apply { - linkerOpts("-v") - linkerOpts(*linkerDirs().map { "-L$it" }.toTypedArray()) - linkerOpts("-undefined", "dynamic_lookup") // resolve symbol in runtime - } - } - } - } -} - fun String.titlecase(): String { if (this.isEmpty()) return this val c = get(0) diff --git a/docs/ConfiguringMultiplatformProjects.md b/docs/ConfiguringMultiplatformProjects.md index 2c607b730..69b6e9d19 100644 --- a/docs/ConfiguringMultiplatformProjects.md +++ b/docs/ConfiguringMultiplatformProjects.md @@ -11,16 +11,12 @@ mirai 上传到 Maven Central 的预编译模块列表如下表所示。在表中列举的平台即为你的项目可以使用的平台。 如果你使用了一个不受支持的平台,在构建项目时将会得到来自 Gradle 的依赖解决错误。 -mirai 实际上能支持 arm 架构,但由于 GitHub Actions 均为 x86 主机,而现阶段配置 Kotlin 交叉编译也较困难,就没有支持。 -没有支持其他小众平台是因为实用性有限。若有需求欢迎 PR。 +mirai 曾在 2.13.0 ~ 2.15.0-RC(不包含)支持编译到 macOS、Window、Linux 平台。自 2.15.0-RC 已完全删除对这些平台的支持。 -| 发布平台名称 | 描述 | -|------------|------------------| -| jvm | JVM | -| android | Android (Dalvik) | -| mingwX64 | Windows x64 | -| macosX64 | macOS x64 | -| linuxX64 | Linux x64 | +| 发布平台名称 | 描述 | +|---------|------------------| +| jvm | JVM | +| android | Android (Dalvik) | ## 添加依赖 @@ -49,7 +45,7 @@ kotlin { ## 解决问题 -如果你在使用多平台项目时遇到问题,那应该是正常的。Kotlin 多平台项目在 1.7 仍然是一个测试版功能。mirai 的 native 平台支持是在 2.13.0 才提供。欢迎在 issues 提交多平台相关问题。 +如果你在使用多平台项目时遇到问题,那应该是正常的。Kotlin 多平台项目在 1.7 仍然是一个测试版功能。欢迎在 issues 提交多平台相关问题。 > 依赖配置完成, > - [回到 Mirai 文档索引](README.md#使用-mirai) \ No newline at end of file diff --git a/docs/contributing/README.md b/docs/contributing/README.md index e0bbc6314..2877c9af5 100644 --- a/docs/contributing/README.md +++ b/docs/contributing/README.md @@ -105,40 +105,26 @@ core' [HMPP]: https://kotlinlang.org/docs/multiplatform-discover-project.html -core 三个模块都使用 Kotlin [HMPP] 功能,同时支持 JVM 和 Native +core 三个模块都使用 Kotlin [HMPP] 功能,同时支持 JVM 和 Android 两种平台。你可以在 [Kotlin 官方文档][HMPP] 了解 HMPP 模式。 core 的编译目标层级结构如图所示: ``` - common - | - /---------------+---------------\ - jvmBase native - / \ / \ - jvm android unix \ - / \ mingwX64 - / \ - darwin linuxX64 - | - * - + common + / \ + jvm android ``` -| 发布平台名称 | 描述 | -|------------|------------------| -| jvm | JVM | -| android | Android (Dalvik) | -| mingwX64 | Windows x64 | -| macosX64 | macOS x64 | -| macosArm64 | macOS arm64 | -| linuxX64 | Linux x64 | +| 发布平台名称 | 描述 | +|---------|------------------| +| jvm | JVM | +| android | Android (Dalvik) | 备注: - common 包含全平台通用代码,绝大部分代码都位于 common; - jvmBase 包含针对 JVM 平台的通用代码; -- `` 为 macOS,iOS,WatchOS 等 Apple 平台目标。 ## 开发提示 @@ -175,32 +161,24 @@ mirai.enable.jvmtoolchain.special=false 所有目标默认都启用。 -**注意**,在关闭一个目标后,将无法编辑该目标的相关源集的源码。关闭部分 native 目标后也可能会影响 native 目标平台原生接口的数据类型。 -因此若非主机性能太差或在 CI 机器运行,**不建议**关闭 native 目标。 +**注意**,在关闭一个目标后,将无法编辑该目标的相关源集的源码。 +因此若非主机性能太差或在 CI 机器运行,**不建议**关闭目标。 [//]: # (备注: 如果要发版, 必须开启全部目标, 否则会导致 metadata 中的平台不全) - `xxx`:显式启用 `xxx` 目标 - `!xxx`:显式禁用 `xxx` 目标 -- `native`:显式启用所有 native 目标 -- `!native`:禁用没有显式启用的所有 native 目标 - `others`:显式启用其他所有所有目标 - `!others`:禁用没有显式启用的所有目标 -其中 xxx 表示构建目标名称。可用的目标名称有(区分大小写):`jvm`、`android`、`macosX64`、`macosArm64`、`mingwX64`、`linuxX64` +其中 xxx 表示构建目标名称。可用的目标名称有(区分大小写):`jvm`、`android` ``` -# 禁用所有 native 目标,启用其他目标(启用 jvm 和 android) -projects.mirai-core.targets=!native;others - -# 启用 `jvm` 和 `android` 目标,禁用其他所有目标(禁用所有 native 目标) -projects.mirai-core.targets=jvm;android;!others - -# 只启用 `jvm` 目标,禁用其他所有目标 +# 只启用 `jvm` 目标,禁用其他所有目标 (Android) projects.mirai-core.targets=jvm;!others -# 指定启用 `jvm` 和 `macosX64` 目标,禁用其他所有目标 -projects.mirai-core.targets=jvm;macosX64;!others +# 启用 `jvm` 和 `android` 目标 +projects.mirai-core.targets=jvm;android ``` ### 直接启动 mirai-core 本地测试 @@ -209,9 +187,7 @@ projects.mirai-core.targets=jvm;macosX64;!others 在 JVM 平台直接启动 mirai-core, 见 [mirai-core/jvmTest](/mirai-core/src/jvmTest/README.md) -在 native 平台直接启动 mirai-core, 见 [mirai-core/nativeTest](/mirai-core/src/nativeTest/kotlin/local/README.md) - -## 构建 mirai 项目 JAR 以及动态链接库 +## 构建 mirai 项目 JAR 查看 [Building](building/README.md) diff --git a/docs/contributing/SimpleInstructions.md b/docs/contributing/SimpleInstructions.md index aacb49bee..dde2173b5 100644 --- a/docs/contributing/SimpleInstructions.md +++ b/docs/contributing/SimpleInstructions.md @@ -29,5 +29,3 @@ ./gradlew publishMiraiArtifactsToMavenLocal "-Dprojects.mirai-core.targets=jvm;android;!others" ``` 若上述命令不工作,尝试在 Android Studio 中打开项目并在 Studio 的终端中执行命令。 -- 我是 mirai native 用户,我需要 `.dll/.so/.dylib`: - 你不能简单地构建这些动态链接库,因为它们需要依赖。阅读 [BuildingCoreNative](building/BuildingCoreNative.md)。 diff --git a/docs/contributing/building/BuildingCoreNative.md b/docs/contributing/building/BuildingCoreNative.md deleted file mode 100644 index 5d56144d2..000000000 --- a/docs/contributing/building/BuildingCoreNative.md +++ /dev/null @@ -1,194 +0,0 @@ -[OpenSSL.def]: ../../mirai-core/src/nativeMain/cinterop/OpenSSL.def - -Kotlin 会自动配置 Native 编译器,要构建 Mirai 的 Native 目标还需要准备相关依赖。 - -### 操作系统条件 - -主机操作系统为以下任一: - -- Windows x86_64 (amd64) -- macOS x86_64 (amd64) -- macOS aarch64 (arm64) -- Linux x86_64 (amd64) - -注意:32 位操作系统不受支持。未列举的操作系统不受支持。 - -目前 Kotlin 对交叉编译支持有限,只能在一个主机上编译该主机平台的目标。例如在 Windows x86_64 主机上只能编译 -Windows x86_64 目标;在 macOS aarch64 主机上只能编译 macOS aarch64 目标。 - -与其他 Native 语言相同,Kotlin 的应用使用依赖时同样需要配置链接,mirai -已经配置了常用目录。也可以在 `mirai-core/src/nativeMain/cinterop/OpenSSL.def` -修改 `linkerOpts` 即链接器参数,以增加自定义路径。 - -### 性能提示 - -在编译和链接时可能需要大量内存,请使用至少拥有 8GB 内存的主机。使用 32GB 内存的主机可以获得不错的体验。mirai -默认启用多项目同时编译,编译时可能会使用大量主机资源。 - -如果主机可用内存较低,请不要执行 `./gradlew assemble` -编译全部项目,这可能会导致内存溢出,也将会导致编译缓慢。可以单独为某个模块执行批量编译,如 `./gradlew :mirai-console:assemble` -。 - -#### 编译耗时 - -若使用 Apple M1 Max 或同等级 CPU (AMD R7 5800X / Intel i7-12700K / Intel -i9-12950HX),单独执行 `./gradlew assemble` 编译并连接全部项目 (含动态链接库和静态链接库) 需时约 9 -分钟。单独执行 `./gradlew check` 需约 4 分钟。 -但在 GitHub 的 2 核心 CPU Actions 机器上执行 `assemble` 通常需要约 40 分钟,。 - -### 安装 OpenSSL - -所有上述主机都需要进行这一步。 - -可以访问 OpenSSL 官网 `https://curl.se/download.html` 安装。 - -#### 在 Ubuntu 通过 Aptitude 安装 OpenSSL - -```shell -$ sudo apt install libssl-dev # 安装 OpenSSL -$ sudo apt install gcc-multilib # 若遇到链接问题可额外尝试此命令 -``` - -#### 在 macOS 通过 Homebrew 安装 OpenSSL - -```shell -$ brew install openssl@3 -``` - -注意:若遇到无法链接等问题,可以尝试通过源码编译安装。 - -#### 在 macOS 或 Linux 通过源码编译安装 OpenSSL - -请参考 [OpenSSL 文档](https://github.com/openssl/openssl/blob/master/INSTALL.md#prerequisites) -准备 OpenSSL 的要求。 - -以下命令可能会帮助你(这是 mirai 的 GitHub Actions 使用的命令)。 - -```shell -$ git clone https://github.com/openssl/openssl.git --recursive -$ cd openssl -$ git checkout tags/openssl-3.0.3 -$ ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl -$ make -$ sudo make install -``` - -若在 Ubuntu 遇到链接问题,可额外尝试此命令: - -```shell -$ sudo apt install gcc-multilib -``` - -#### 在 Windows 通过 vcpkg 安装 OpenSSL - -你需要提前安装 [vcpkg](https://github.com/microsoft/vcpkg/blob/master/README_zh_CN.md) -。 - -以下命令可能会帮助你(这是 mirai 的 GitHub Actions 使用的命令)。 - -```powershell -echo "set(VCPKG_BUILD_TYPE release)" | Out-File -FilePath "$env:VCPKG_INSTALLATION_ROOT\triplets\x64-windows.cmake" -Encoding utf8 -Append -vcpkg install openssl:x64-windows curl[core, ssl]: x64-windows -New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\crypto.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcrypto.lib -New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\ssl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libssl.lib -New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\curl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcurl.lib -echo "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append -``` - -由于链接器只识别不包含 `lib` 前缀的文件(如 `ssl.lib` 而非 `libssl.lib`,vcpkg 编译产物为后者),上述 `New-Item` 创建一个无 `lib` 前缀的链接指向库文件。 - -注意: - -- 你将需要修改链接器配置(位于 `mirai-core/src/nativeMain/cinterop/OpenSSL.def` - ),增加 `linkerOpts` 和 `compilerOpts` 指向你本地安装的路径。 -- 不要将修改路径后的 `OpenSSL.def` 通过 Git 推送到 mirai 仓库或 PR。 - -#### 在 Windows 通过源码编译安装 OpenSSL - -在 Windows,可通过源码编译安装,请使用 Command Prompt (cmd)。 - -你需要提前安装 [Git](https://git-scm.com/) -和 [Microsoft Visual Studio](https://visualstudio.microsoft.com/zh-hans/) -,并修改以下命令中的路径。 - -请参考 [OpenSSL 文档](https://github.com/openssl/openssl/blob/master/INSTALL.md#prerequisites) -准备 OpenSSL 的要求。 - -以下命令可能会帮助你(这是 mirai 的 GitHub Actions 使用过的命令)。 - -```shell -git clone https://github.com/openssl/openssl.git --recursive -cd openssl -git checkout tags/openssl-3.0.3 -perl Configure VC-WIN64A --prefix=C:/openssl --openssldir=C:/openssl/ssl no-asm -"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64 && nmake && nmake install -``` - -注意: - -- `--prefix=C:/openssl --openssldir=C:/openssl/ssl` 表示将 OpenSSL - 安装在 `C:/openssl`,mirai - 已经配置会使用此路径寻找链接库。你也可以更换为其他路径,但就需要同步修改配置(位于 `mirai-core/src/nativeMain/cinterop/OpenSSL.def` - ); -- 不要将修改路径后的 `OpenSSL.def` 通过 Git 推送到 mirai 仓库或 PR。 - -### 安装 cURL - -mirai 在 Windows 上使用 -cURL,在其他平台使用 [Ktor CIO](https://ktor.io/docs/http-client-engines.html#cio) -,因此只有 Windows 系统需要进行这一步。 - -可以访问 cURL 官网 安装。 - -提示:如果在[链接](#链接并测试)时遇到找不到 cURL -相关符号的问题,请尝试修改链接器参数。尽管 `mirai-core/src/nativeMain/cinterop/OpenSSL.def` -是用于 `OpenSSL.def` 的,也可以在这个文件配置 cURL 路径。 - -### 编译 - -在任意主机上可以执行所有目标的 Kotlin 编译,但不能执行链接。要执行特定目标的编译,运行 Gradle -任务 `compileKotlinXXX`,其中 `XXX` 可以是:`MacosX64`、`MacosArm64`、`MingwX64` -或 `LinuxX64`。 - -也可以执行 `compileKotlinHost`,将自动根据当前主机选择合适的目标。 - -### 链接并测试 - -执行 core 模块的 `hostTest`,将根据主机选择合适的测试并运行。 - -详情参考 [Kotlin 官方文档](https://kotlinlang.org/docs/multiplatform-run-tests.html) -。 - -### 链接并构建动态链接库 - -注意,只有 mirai-core 可以构建可用的动态链接库。所有动态链接库和静态链接库的构建都是默认关闭的,需要使用 `-Dmirai.native.binaries=true` 才能启用。 - -## 构建 core 的 Native 目标 - -在提供 `-Dmirai.native.binaries=true` 参数的情况下,执行 `:mirai-core:linkDebugSharedHost` -或 `:mirai-core:linkReleaseSharedHost`。Debug 版本会保留调试符号,能显示完整错误堆栈;而 -Release 拥有更小体积(比 Debug 减小 50%)。 - -示例: - -```shell -./gradlew :mirai-core:linkDebugSharedHost "-Dmirai.native.binaries=true" - -./gradlew :mirai-core:linkReleaseSharedMacoxX64 "-Dmirai.native.binaries=true" -``` - -这也会同时生成一个头文件(`.h` -)供交互使用。详情查看 [Kotlin 官方文档](https://kotlinlang.org/docs/native-c-interop.html) -。 - -可以在 `mirai-core/build/bin/macosArm64/debugShared/` 类似路径找到生成的动态链接库和头文件。 - -### 链接并构建静态链接库 - -注意,只有 mirai-core 可以构建可用的静态链接库。 - -与构建动态链接库类似,在提供 `-Dmirai.native.binaries=true` 参数的情况下,执行 `:mirai-core:linkDebugStaticHost` -或 `:mirai-core:linkReleaseStaticHost`。Debug 版本会保留调试符号,能显示完整错误堆栈;而 -Release 拥有更小体积(比 Debug 减小 50%)。 - -可以在 `mirai-core/build/bin/macosArm64/debugStatic/` 类似路径找到生成的静态链接库和头文件。 diff --git a/docs/contributing/building/README.md b/docs/contributing/building/README.md index 4f02183ed..a355d6108 100644 --- a/docs/contributing/building/README.md +++ b/docs/contributing/building/README.md @@ -31,10 +31,6 @@ Gradle 任务: 查看 [BuildingCoreAndroid](BuildingCoreAndroid.md)。 -### 构建 core 的 Native 目标 - -查看 [BuildingCoreNative](BuildingCoreNative.md)。 - ## 构建 IntelliJ 插件 可通过如下命令构建 IntelliJ 平台 IDE 的插件。构建成功的插件将可以在 `mirai-console/tools/intellij-plugin/build/distribution` 中找到。 diff --git a/gradle.properties b/gradle.properties index 7ed88a5e9..62749b2ca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,7 +12,6 @@ kotlin.incremental.multiplatform=true org.gradle.jvmargs=-Xmx7000m -Dfile.encoding=UTF-8 --illegal-access=permit -Dkotlin.daemon.jvm.options=--illegal-access=permit --add-opens java.base/java.util=ALL-UNNAMED org.gradle.parallel=true org.gradle.vfs.watch=true -kotlin.native.binary.memoryModel=experimental #kotlin.mpp.enableCompatibilityMetadataVariant=true systemProp.org.gradle.internal.publish.checksums.insecure=true gnsp.disableApplyOnlyOnRootProjectEnforcement=true @@ -20,7 +19,6 @@ mirai.android.target.api.level=21 # Enable if you want to use mavenLocal for both Gradle plugin and project dependencies resolutions. systemProp.use.maven.local=false org.gradle.caching=true -kotlin.native.ignoreIncorrectDependencies=true kotlin.mpp.enableCInteropCommonization=true kotlin.mpp.stability.nowarn=true kotlin.mpp.androidSourceSetLayoutVersion=2 diff --git a/mirai-console/tools/compiler-annotations/build.gradle.kts b/mirai-console/tools/compiler-annotations/build.gradle.kts index 0b638ec30..eb8a288fa 100644 --- a/mirai-console/tools/compiler-annotations/build.gradle.kts +++ b/mirai-console/tools/compiler-annotations/build.gradle.kts @@ -22,7 +22,6 @@ kotlin { apply(plugin = "explicit-api") configureJvmTargetsHierarchical("net.mamoe.mirai.compiler.annotations") - configureNativeTargetsHierarchical(project) } configureMppPublishing() diff --git a/mirai-core-api/build.gradle.kts b/mirai-core-api/build.gradle.kts index 6dfd27703..70fba6757 100644 --- a/mirai-core-api/build.gradle.kts +++ b/mirai-core-api/build.gradle.kts @@ -32,8 +32,6 @@ kotlin { configureJvmTargetsHierarchical("net.mamoe.mirai") - configureNativeTargetsHierarchical(project) - sourceSets { val commonMain by getting { dependencies { @@ -87,11 +85,6 @@ kotlin { runtimeOnly(files("build/classes/kotlin/jvm/test")) // classpath is not properly set by IDE } } - - findByName("nativeMain")?.apply { - dependencies { - } - } } } diff --git a/mirai-core-api/src/commonMain/kotlin/contact/announcement/OfflineAnnouncement.kt b/mirai-core-api/src/commonMain/kotlin/contact/announcement/OfflineAnnouncement.kt index c1dff206f..8f5226cc7 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/announcement/OfflineAnnouncement.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/announcement/OfflineAnnouncement.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -16,15 +16,10 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import net.mamoe.mirai.contact.announcement.OfflineAnnouncement.Companion.serializer import net.mamoe.mirai.utils.cast -import net.mamoe.mirai.utils.copy import net.mamoe.mirai.utils.map import net.mamoe.mirai.utils.safeCast import kotlin.contracts.InvocationKind import kotlin.contracts.contract -import kotlin.jvm.JvmOverloads -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** * 表示在本地构建的 [Announcement]. @@ -95,7 +90,6 @@ public sealed interface OfflineAnnouncement : Announcement { * 依据 [from] 创建 [OfflineAnnouncement]. 若 [from] 类型为 [OfflineAnnouncement] 则直接返回 [from]. * @since 2.7 */ -@CName("", "OfflineAnnouncement_new") public inline fun OfflineAnnouncement(from: Announcement): OfflineAnnouncement = OfflineAnnouncement.from(from) @@ -105,7 +99,6 @@ public inline fun OfflineAnnouncement(from: Announcement): OfflineAnnouncement = * @param parameters 可选的附加参数 * @since 2.7 */ -@CName("", "OfflineAnnouncement_new2") public inline fun OfflineAnnouncement( content: String, parameters: AnnouncementParameters = AnnouncementParameters.DEFAULT @@ -118,7 +111,6 @@ public inline fun OfflineAnnouncement( * @see AnnouncementParametersBuilder * @since 2.7 */ -@CName("", "OfflineAnnouncement_new3") public inline fun OfflineAnnouncement( content: String, parameters: AnnouncementParametersBuilder.() -> Unit diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/At.kt b/mirai-core-api/src/commonMain/kotlin/message/data/At.kt index a3ff0a887..3e97b67dc 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/At.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/At.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -24,10 +24,6 @@ import net.mamoe.mirai.message.code.CodableMessage import net.mamoe.mirai.message.data.visitor.MessageVisitor import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiInternalApi -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** @@ -88,7 +84,6 @@ public data class At( * @see Member.at */ @JvmSynthetic -@CName("", "At_new") public inline fun At(user: UserOrBot): At = At(user.id) /** diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Audio.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Audio.kt index 6a106dba3..c8a5fc381 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Audio.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Audio.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -22,11 +22,6 @@ import net.mamoe.mirai.message.MessageSerializers import net.mamoe.mirai.message.data.MessageChain.Companion.serializeToJsonString import net.mamoe.mirai.message.data.visitor.MessageVisitor import net.mamoe.mirai.utils.* -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName import kotlin.time.Duration import kotlin.time.Duration.Companion.seconds @@ -234,7 +229,6 @@ public interface OfflineAudio : Audio { * @since 2.7 */ @JvmSynthetic -@CName("", "OfflineAudio_new") public inline fun OfflineAudio( filename: String, fileMd5: ByteArray, @@ -248,7 +242,6 @@ public inline fun OfflineAudio( * @since 2.7 */ @JvmSynthetic -@CName("", "OfflineAudio_new2") public inline fun OfflineAudio( onlineAudio: OnlineAudio ): OfflineAudio = OfflineAudio.Factory.from(onlineAudio) diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/FileMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/FileMessage.kt index 5ee48b71b..2eca81f1b 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/FileMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/FileMessage.kt @@ -26,11 +26,6 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiInternalApi import net.mamoe.mirai.utils.NotStableForInheritance import net.mamoe.mirai.utils.map -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** * 文件消息. @@ -133,6 +128,5 @@ internal open class FallbackFileMessageSerializer : * @since 2.5 */ @JvmSynthetic -@CName("", "FileMessage_new") public fun FileMessage(id: String, internalId: Int, name: String, size: Long): FileMessage = FileMessage.create(id, internalId, name, size) \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/FlashImage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/FlashImage.kt index d2d8a8bd8..5f4111365 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/FlashImage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/FlashImage.kt @@ -18,9 +18,6 @@ import net.mamoe.mirai.message.data.visitor.MessageVisitor import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiInternalApi import net.mamoe.mirai.utils.safeCast -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** * 闪照. 闪照的内容取决于 [image] 代表的图片. @@ -97,7 +94,6 @@ public data class FlashImage( * 将普通图片转换为闪照. */ @JvmSynthetic -@CName("", "FlashImage_new") public inline fun FlashImage(imageId: String): FlashImage = FlashImage.from(imageId) /** diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt index 01ad46299..75163ff7c 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt @@ -47,11 +47,6 @@ import net.mamoe.mirai.message.data.Image.Key.queryUrl import net.mamoe.mirai.message.data.visitor.MessageVisitor import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** * 自定义表情 (收藏的表情) 和普通图片. @@ -487,7 +482,6 @@ public interface Image : Message, MessageContent, CodableMessage { * @see IMirai.createImage */ @JvmSynthetic -@CName("", "Image_new") public fun Image(imageId: String): Image = Builder.newBuilder(imageId).build() /** @@ -497,7 +491,6 @@ public fun Image(imageId: String): Image = Builder.newBuilder(imageId).build() * @since 2.9.0 */ @JvmSynthetic -@CName("", "Image_new2") public inline fun Image(imageId: String, builderAction: Builder.() -> Unit = {}): Image = Builder.newBuilder(imageId).apply(builderAction).build() diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt index fa17e78ad..ce9425db8 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/UnsupportedMessage.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -21,11 +21,6 @@ import net.mamoe.mirai.IMirai import net.mamoe.mirai.Mirai import net.mamoe.mirai.message.data.visitor.MessageVisitor import net.mamoe.mirai.utils.* -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic -import kotlin.native.CName /** * mirai 尚未支持的消息类型. @@ -81,5 +76,4 @@ public interface UnsupportedMessage : MessageContent { * @see UnsupportedMessage.create */ @JvmSynthetic -@CName("", "UnsupportedMessage_new") public inline fun UnsupportedMessage(struct: ByteArray): UnsupportedMessage = UnsupportedMessage.create(struct) \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt index 9e9ef48bd..0c6462e63 100644 --- a/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt +++ b/mirai-core-api/src/commonMain/kotlin/utils/BotConfiguration.kt @@ -24,8 +24,6 @@ import net.mamoe.mirai.event.events.BotOfflineEvent import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.coroutineContext -import kotlin.jvm.* -import kotlin.native.CName import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds @@ -551,7 +549,6 @@ public open class BotConfiguration : AbstractBotConfiguration() { // open for Ja * @since 2.3 */ @JvmSynthetic -@CName("", "BotConfiguration_new2") public inline fun BotConfiguration(block: BotConfiguration.() -> Unit): BotConfiguration { return BotConfiguration().apply(block) } diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/Contact.kt b/mirai-core-api/src/nativeMain/kotlin/contact/Contact.kt deleted file mode 100644 index acb15735e..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/Contact.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.contact - -import io.ktor.utils.io.core.* -import kotlinx.coroutines.CoroutineScope -import net.mamoe.mirai.Bot -import net.mamoe.mirai.event.events.* -import net.mamoe.mirai.message.MessageReceipt -import net.mamoe.mirai.message.data.* -import net.mamoe.mirai.utils.ExternalResource -import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage -import net.mamoe.mirai.utils.NotStableForInheritance -import net.mamoe.mirai.utils.OverFileSizeMaxException -import kotlin.coroutines.cancellation.CancellationException - -/** - * 联系对象, 即可以与 [Bot] 互动的对象. 包含 [用户][User], 和 [群][Group]. - */ -@NotStableForInheritance -public actual interface Contact : ContactOrBot, CoroutineScope { - /** - * 这个联系对象所属 [Bot]. - */ - public actual override val bot: Bot - - /** - * 可以是 QQ 号码或者群号码. - * - * @see User.id - * @see Group.id - */ - public actual override val id: Long - - /** - * 向这个对象发送消息. - * - * 单条消息最大可发送 4500 字符或 50 张图片. - * - * @see MessagePreSendEvent 发送消息前事件 - * @see MessagePostSendEvent 发送消息后事件 - * - * @throws EventCancelledException 当发送消息事件被取消时抛出 - * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 - * @throws MessageTooLargeException 当消息过长时抛出 - * @throws IllegalArgumentException 当消息内容为空时抛出 (详见 [Message.isContentEmpty]) - * - * @return 消息回执. 可 [引用][MessageReceipt.quote] 或 [撤回][MessageReceipt.recall] 这条消息. - */ - public actual suspend fun sendMessage(message: Message): MessageReceipt - - /** - * 发送纯文本消息 - * @see sendMessage - */ - public actual suspend fun sendMessage(message: String): MessageReceipt = sendMessage(message.toPlainText()) - - /** - * 上传一个 [资源][ExternalResource] 作为图片以备发送. - * - * **无论上传是否成功都不会关闭 [resource]. 需要调用方手动关闭资源** - * - * 也可以使用其他扩展: [ExternalResource.uploadAsImage] 使用 [Input] 等上传. - * - * @see Image 查看有关图片的更多信息, 如上传图片 - * - * @see BeforeImageUploadEvent 图片发送前事件, 可拦截. - * @see ImageUploadEvent 图片发送完成事件, 不可拦截. - * - * @see ExternalResource - * - * @throws EventCancelledException 当发送消息事件被取消时抛出 - * @throws OverFileSizeMaxException 当图片文件过大而被服务器拒绝上传时抛出. (最大大小约为 20 MB, 但 mirai 限制的大小为 30 MB) - */ - public actual suspend fun uploadImage(resource: ExternalResource): Image - - public actual companion object { - /** - * 将资源作为单独的图片消息发送给 [this] - * - * @see Contact.sendMessage 最终调用, 发送消息. - */ - public actual suspend fun C.sendImage(resource: ExternalResource): MessageReceipt { - return this.uploadImage(resource).sendTo(this) - } - - /** - * 将文件作为图片上传, 但不发送 - * @throws OverFileSizeMaxException - */ - @kotlin.internal.LowPriorityInOverloadResolution - @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXTENSION_SHADOWED_BY_MEMBER") - @Throws(OverFileSizeMaxException::class, CancellationException::class) - public actual suspend fun Contact.uploadImage(resource: ExternalResource): Image { - return uploadImage(resource) - } - - } - -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/FileSupported.kt b/mirai-core-api/src/nativeMain/kotlin/contact/FileSupported.kt deleted file mode 100644 index 39744e521..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/FileSupported.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.contact - -import net.mamoe.mirai.contact.file.RemoteFiles -import net.mamoe.mirai.utils.NotStableForInheritance - -/** - * 支持文件操作的 [Contact]. 目前仅 [Group]. - * - * 获取文件操作相关示例: [RemoteFiles] - * - * @since 2.5 - * - * @see RemoteFiles - */ -@NotStableForInheritance -public actual interface FileSupported : Contact { - /** - * 获取远程文件列表 (管理器). - * - * @since 2.8 - */ - public actual val files: RemoteFiles -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/file/AbsoluteFolder.kt b/mirai-core-api/src/nativeMain/kotlin/contact/file/AbsoluteFolder.kt deleted file mode 100644 index 05981121a..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/file/AbsoluteFolder.kt +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.contact.file - -import kotlinx.coroutines.flow.Flow -import net.mamoe.mirai.contact.PermissionDeniedException -import net.mamoe.mirai.utils.ExternalResource -import net.mamoe.mirai.utils.NotStableForInheritance -import net.mamoe.mirai.utils.ProgressionCallback - -/** - * 绝对目录标识. 精确表示一个远程目录. 不会受同名文件或目录的影响. - * - * @since 2.8 - * @see RemoteFiles - * @see AbsoluteFile - * @see AbsoluteFileFolder - */ -@Suppress("SEALED_INHERITOR_IN_DIFFERENT_MODULE") -@NotStableForInheritance -public actual interface AbsoluteFolder : AbsoluteFileFolder { - /** - * 当前快照中文件数量, 当有文件更新时(上传/删除文件) 该属性不会更新. - * - * 只可能通过 [refresh] 手动刷新 - * - * 特别的, 若该目录表示根目录, [contentsCount] 返回 `0`. (无法快速获取) - */ - public actual val contentsCount: Int - - /** - * 当该目录为空时返回 `true`. - */ - public actual fun isEmpty(): Boolean = contentsCount == 0 - - /** - * 返回更新了文件或目录信息 ([lastModifiedTime] 等) 的, 指向相同文件的 [AbsoluteFileFolder]. - * 不会更新当前 [AbsoluteFileFolder] 对象. - * - * 当远程文件或目录不存在时返回 `null`. - * - * 该函数会遍历上级目录的所有文件并匹配当前文件, 因此可能会非常慢, 请不要频繁使用. - */ - actual override suspend fun refreshed(): AbsoluteFolder? - - /////////////////////////////////////////////////////////////////////////// - // list children - /////////////////////////////////////////////////////////////////////////// - - /** - * 获取该目录下所有子目录列表. - */ - public actual suspend fun folders(): Flow - - /** - * 获取该目录下所有文件列表. - */ - public actual suspend fun files(): Flow - - - /** - * 获取该目录下所有文件和子目录列表. - */ - public actual suspend fun children(): Flow - - /////////////////////////////////////////////////////////////////////////// - // resolve and upload - /////////////////////////////////////////////////////////////////////////// - - /** - * 创建一个名称为 [name] 的子目录. 返回成功创建的或已有的子目录. 当目标目录已经存在时则直接返回该目录. - * - * @throws IllegalArgumentException 当 [name] 为空或包含非法字符 (`:*?"<>|`) 时抛出 - * @throws PermissionDeniedException 当权限不足时抛出 - */ - public actual suspend fun createFolder(name: String): AbsoluteFolder - - /** - * 获取一个已存在的名称为 [name] 的子目录. 当该名称的子目录不存在时返回 `null`. - * - * @throws IllegalArgumentException 当 [name] 为空或包含非法字符 (`:*?"<>|`) 时抛出 - */ - public actual suspend fun resolveFolder(name: String): AbsoluteFolder? - - /** - * 获取一个已存在的 [AbsoluteFileFolder.id] 为 [id] 的子目录. 当该名称的子目录不存在时返回 `null`. - * - * @throws IllegalArgumentException 当 [id] 为空或无效时抛出 - * - * @since 2.9.0 - */ - public actual suspend fun resolveFolderById(id: String): AbsoluteFolder? - - /** - * 精确获取 [AbsoluteFile.id] 为 [id] 的文件. 在目标文件不存在时返回 `null`. 当 [deep] 为 `true` 时还会深入子目录查找. - */ - public actual suspend fun resolveFileById( - id: String, - deep: Boolean - ): AbsoluteFile? - - /** - * 根据路径获取指向的所有路径为 [path] 的文件列表. 同时支持相对路径和绝对路径. 支持获取子目录内的文件. - */ - public actual suspend fun resolveFiles( - path: String - ): Flow - - /** - * 根据路径获取指向的所有路径为 [path] 的文件和目录列表. 同时支持相对路径和绝对路径. 支持获取子目录内的文件和目录. - */ - public actual suspend fun resolveAll( - path: String - ): Flow - - /** - * 上传一个文件到该目录, 返回上传成功的文件标识. - * - * 会在必要时尝试创建远程目录. - * - * ### [filepath] - * - * - 可以是 `foo.txt` 表示该目录下的文件 "foo.txt" - * - 也可以是 `sub/foo.txt` 表示该目录的子目录 "sub" 下的文件 "foo.txt". - * - 或是绝对路径 `/sub/foo.txt` 表示根目录的 "sub" 目录下的文件 "foo.txt" - * - * @param filepath 目标文件名 - * @param content 文件内容 - * @param callback 下载进度回调, 传递的 `progression` 是已下载字节数. - * - * @throws PermissionDeniedException 当无管理员权限时抛出 (若群仅允许管理员上传) - */ - public actual suspend fun uploadNewFile( - filepath: String, - content: ExternalResource, - callback: ProgressionCallback?, - ): AbsoluteFile - - public actual companion object { - /** - * 根目录 folder ID. - * @see id - */ - public actual const val ROOT_FOLDER_ID: String = "/" - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/contact/roaming/RoamingMessages.kt b/mirai-core-api/src/nativeMain/kotlin/contact/roaming/RoamingMessages.kt deleted file mode 100644 index 3145ab89c..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/contact/roaming/RoamingMessages.kt +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.contact.roaming - -import kotlinx.coroutines.flow.Flow -import net.mamoe.mirai.message.data.MessageChain -import net.mamoe.mirai.message.data.MessageSource - - -/** - * 漫游消息记录管理器. 可通过 [RoamingSupported.roamingMessages] 获得. - * - * @since 2.8 - * @see RoamingSupported - */ -public actual interface RoamingMessages { - /////////////////////////////////////////////////////////////////////////// - // Get list - /////////////////////////////////////////////////////////////////////////// - - /** - * 查询指定时间段内的漫游消息记录. - * - * 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息. - * 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回. - * - * 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息. - * 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.source`), 判断 [MessageSource.fromId] (发送人). - * 消息的其他*元数据*信息也要通过 [MessageSource] 获取 (如 [MessageSource.time] 获取时间). - * - * 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] 或 [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递. - * - * 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响. - * - * @param timeStart 起始时间戳, 单位为秒. 可以为 `0`, 即表示从可以获取的最早的消息起. 负数将会被看是 `0`. - * @param timeEnd 结束时间戳, 单位为秒. 可以为 [Long.MAX_VALUE], 即表示到可以获取的最晚的消息为止. 低于 [timeStart] 的值将会被看作是 [timeStart] 的值. - * @param filter 过滤器. - */ - public actual suspend fun getMessagesIn( - timeStart: Long, - timeEnd: Long, - filter: RoamingMessageFilter? - ): Flow - - /** - * 查询所有漫游消息记录. - * - * 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息. - * 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回. - * - * 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息. - * 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.source`), 判断 [MessageSource.fromId] (发送人). - * 消息的其他*元数据*信息也要通过 [MessageSource] 获取 (如 [MessageSource.time] 获取时间). - * - * 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] 或 [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递. - * - * 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响. - * - * @param filter 过滤器. - */ - public actual suspend fun getAllMessages( - filter: RoamingMessageFilter? - ): Flow = getMessagesIn(0, Long.MAX_VALUE, filter) -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/event/EventChannel.kt b/mirai-core-api/src/nativeMain/kotlin/event/EventChannel.kt deleted file mode 100644 index 10525f12b..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/event/EventChannel.kt +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright 2019-2023 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.event - -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.channels.ClosedSendChannelException -import kotlinx.coroutines.channels.SendChannel -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.sync.Mutex -import net.mamoe.mirai.Bot -import net.mamoe.mirai.IMirai -import net.mamoe.mirai.event.ConcurrencyKind.CONCURRENT -import net.mamoe.mirai.event.ConcurrencyKind.LOCKED -import net.mamoe.mirai.event.events.BotEvent -import net.mamoe.mirai.utils.* -import kotlin.coroutines.CoroutineContext -import kotlin.reflect.KClass - -/** - * 事件通道. - * - * 事件通道是监听事件的入口, 但不负责广播事件. 要广播事件, 使用 [Event.broadcast] 或 [IMirai.broadcastEvent]. - * - * ## 获取事件通道 - * - * [EventChannel] 不可自行构造, 只能通过 [GlobalEventChannel], [BotEvent], 或基于一个通道的过滤等操作获得. - * - * ### 全局事件通道 - * - * [GlobalEventChannel] 是单例对象, 表示全局事件通道, 可以获取到在其中广播的所有事件. - * - * ### [BotEvent] 事件通道 - * - * 若只需要监听某个 [Bot] 的事件, 可通过 [Bot.eventChannel] 获取到这样的 [EventChannel]. - * - * ## 通道操作 - * - * ### 对通道的操作 - * - 过滤通道: 通过 [EventChannel.filter]. 例如 `filter { it is BotEvent }` 得到一个只能监听到 [BotEvent] 的事件通道. - * - 转换为 Kotlin 协程 [Channel]: [EventChannel.forwardToChannel] - * - 添加 [CoroutineContext]: [context], [parentJob], [parentScope], [exceptionHandler] - * - * ### 创建事件监听 - * - [EventChannel.subscribe] 创建带条件的一个事件监听器. - * - [EventChannel.subscribeAlways] 创建一个总是监听事件的事件监听器. - * - [EventChannel.subscribeOnce] 创建一个只监听单次的事件监听器. - * - * ### 监听器生命周期 - * - * 阅读 [EventChannel.subscribe] 以获取监听器生命周期相关信息. - * - * ## 与 kotlinx-coroutines 交互 - * - * mirai [EventChannel] 设计比 kotlinx-coroutines 的 [Flow] 稳定版更早. - * [EventChannel] 的功能与 [Flow] 类似, 不过 [EventChannel] 在 [subscribe] (类似 [Flow.collect]) 时有优先级判定, 也允许[拦截][Event.intercept]. - * - * ### 通过 [Flow] 接收事件 - * - * 使用 [EventChannel.asFlow] 获得 [Flow], 然后可使用 [Flow.collect] 等操作. - * - * ### 转发事件到 [SendChannel] - * - * 使用 [EventChannel.forwardToChannel] 可将事件转发到指定 [SendChannel]. - */ -@NotStableForInheritance // since 2.12, before it was `final class`. -public actual abstract class EventChannel @MiraiInternalApi public actual constructor( - public actual val baseEventClass: KClass, - /** - * 此事件通道的默认 [CoroutineScope.coroutineContext]. 将会被添加给所有注册的事件监听器. - */ - public actual val defaultCoroutineContext: CoroutineContext, -) { - - /** - * 创建事件监听并将监听结果转发到 [channel]. 当 [Channel.send] 抛出 [ClosedSendChannelException] 时停止 [Listener] 监听和转发. - * - * 返回创建的会转发监听到的所有事件到 [channel] 的[事件监听器][Listener]. [停止][Listener.complete] 该监听器会停止转发, 不会影响目标 [channel]. - * - * 若 [Channel.send] 挂起, 则监听器也会挂起, 也就可能会导致事件广播过程挂起. - * - * 示例: - * - * ``` - * val eventChannel: EventChannel = ... - * val channel = Channel() // kotlinx.coroutines.channels.Channel - * eventChannel.forwardToChannel(channel, priority = ...) - * - * // 其他地方 - * val event: BotEvent = channel.receive() // 挂起并接收一个事件 - * ``` - * - * @see subscribeAlways - * @see Channel - * @since 2.10 - */ - public actual fun forwardToChannel( - channel: SendChannel<@UnsafeVariance BaseEvent>, - coroutineContext: CoroutineContext, - priority: EventPriority, - ): Listener<@UnsafeVariance BaseEvent> { - // keep this LOCKED, otherwise compiler will choose the 'inline subscribe' which takes no KClass arg. - return subscribe(baseEventClass, coroutineContext, LOCKED, priority) { - try { - channel.send(it) - ListeningStatus.LISTENING - } catch (_: ClosedSendChannelException) { - ListeningStatus.STOPPED - } - } - } - - /** - * 通过 [Flow] 接收此通道内的所有事件. - * - * ``` - * val eventChannel: EventChannel = ... - * val flow: Flow = eventChannel.asFlow() - * - * flow.collect { // it - * // - * } - * - * flow.filterIsInstance.collect { // it: GroupMessageEvent - * // 处理事件 ... - * } - * - * flow.filterIsInstance.collect { // it: FriendMessageEvent - * // 处理事件 ... - * } - * ``` - * - * 类似于 [SharedFlow], [EventChannel.asFlow] 返回的 [Flow] 永远都不会停止. 因此上述示例 [Flow.collect] 永远都不会正常 (以抛出异常之外的) 结束. - * - * 通过 [asFlow] 接收事件相当于通过 [subscribeAlways] 以 [EventPriority.MONITOR] 监听事件. - * - * **注意**: [context], [parentJob] 等控制 [EventChannel.defaultCoroutineContext] 的操作对 [asFlow] 无效. 因为 [asFlow] 并不创建协程. - * - * @see Flow - * @since 2.12 - */ - public actual abstract fun asFlow(): Flow - - // region transforming operations - - /** - * 添加一个过滤器. 过滤器将在收到任何事件之后, 传递给通过 [EventChannel.subscribe] 注册的监听器之前调用. - * - * 若 [filter] 返回 `true`, 该事件将会被传给监听器. 否则将会被忽略, **监听器继续监听**. - * - * ## 线性顺序 - * 多个 [filter] 的处理是线性且有顺序的. 若一个 [filter] 已经返回了 `false` (代表忽略这个事件), 则会立即忽略, 而不会传递给后续过滤器. - * - * 示例: - * ``` - * GlobalEventChannel // GlobalEventChannel 会收到全局所有事件, 事件类型是 Event - * .filterIsInstance() // 过滤, 只接受 BotEvent - * .filter { event: BotEvent -> - * // 此时的 event 一定是 BotEvent - * event.bot.id == 123456 // 再过滤 event 的 bot.id - * } - * .subscribeAlways { event: BotEvent -> - * // 现在 event 是 BotEvent, 且 bot.id == 123456 - * } - * ``` - * - * ## 过滤器挂起 - * [filter] 允许挂起协程. **过滤器的挂起将被认为是事件监听器的挂起**. - * - * 过滤器挂起是否会影响事件处理, - * 取决于 [subscribe] 时的 [ConcurrencyKind] 和 [EventPriority]. - * - * ## 过滤器异常处理 - * 若 [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出. - * - * @see filterIsInstance 过滤指定类型的事件 - */ - public actual fun filter(filter: suspend (event: BaseEvent) -> Boolean): EventChannel { - return FilterEventChannel(this, filter) - } - - /** - * [EventChannel.filter] 的 Java 版本. - * - * 添加一个过滤器. 过滤器将在收到任何事件之后, 传递给通过 [EventChannel.subscribe] 注册的监听器之前调用. - * - * 若 [filter] 返回 `true`, 该事件将会被传给监听器. 否则将会被忽略, **监听器继续监听**. - * - * ## 线性顺序 - * 多个 [filter] 的处理是线性且有顺序的. 若一个 [filter] 已经返回了 `false` (代表忽略这个事件), 则会立即忽略, 而不会传递给后续过滤器. - * - * 示例: - * ``` - * GlobalEventChannel // GlobalEventChannel 会收到全局所有事件, 事件类型是 Event - * .filterIsInstance(BotEvent.class) // 过滤, 只接受 BotEvent - * .filter(event -> - * // 此时的 event 一定是 BotEvent - * event.bot.id == 123456 // 再过滤 event 的 bot.id - * ) - * .subscribeAlways(event -> { - * // 现在 event 是 BotEvent, 且 bot.id == 123456 - * }) - * ``` - * - * ## 过滤器阻塞 - * [filter] 允许阻塞线程. **过滤器的阻塞将被认为是事件监听器的阻塞**. - * - * 过滤器阻塞是否会影响事件处理, - * 取决于 [subscribe] 时的 [ConcurrencyKind] 和 [EventPriority]. - * - * ## 过滤器异常处理 - * 若 [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出. - * - * @see filterIsInstance 过滤指定类型的事件 - * - * @since 2.2 - */ - @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") - @kotlin.internal.LowPriorityInOverloadResolution - public actual fun filter(filter: (event: BaseEvent) -> Boolean): EventChannel { - return filter { runBIO { filter(it) } } - } - - /** - * 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel] - * @see filter 获取更多信息 - */ - public actual inline fun filterIsInstance(): EventChannel = - filterIsInstance(E::class) - - /** - * 过滤事件的类型. 返回一个只包含 [E] 类型事件的 [EventChannel] - * @see filter 获取更多信息 - */ - public actual fun filterIsInstance(kClass: KClass): EventChannel { - return filter { kClass.isInstance(it) }.cast() - } - - /** - * 创建一个新的 [EventChannel], 该 [EventChannel] 包含 [`this.coroutineContext`][defaultCoroutineContext] 和添加的 [coroutineContexts]. - * [coroutineContexts] 会覆盖 [defaultCoroutineContext] 中的重复元素. - * - * 此操作不会修改 [`this.coroutineContext`][defaultCoroutineContext], 只会创建一个新的 [EventChannel]. - */ - public actual abstract fun context(vararg coroutineContexts: CoroutineContext): EventChannel - - /** - * 创建一个新的 [EventChannel], 该 [EventChannel] 包含 [this.coroutineContext][defaultCoroutineContext] 和添加的 [coroutineExceptionHandler] - * @see context - */ - @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") - @kotlin.internal.LowPriorityInOverloadResolution - public actual fun exceptionHandler(coroutineExceptionHandler: CoroutineExceptionHandler): EventChannel { - return context(coroutineExceptionHandler) - } - - /** - * 创建一个新的 [EventChannel], 该 [EventChannel] 包含 [`this.coroutineContext`][defaultCoroutineContext] 和添加的 [coroutineExceptionHandler] - * @see context - */ - public actual fun exceptionHandler(coroutineExceptionHandler: (exception: Throwable) -> Unit): EventChannel { - return context(CoroutineExceptionHandler { _, throwable -> - coroutineExceptionHandler(throwable) - }) - } - - /** - * 将 [coroutineScope] 作为这个 [EventChannel] 的父作用域. - * - * 实际作用为创建一个新的 [EventChannel], - * 该 [EventChannel] 包含 [`this.coroutineContext`][defaultCoroutineContext] 和添加的 [CoroutineScope.coroutineContext], - * 并以 [CoroutineScope] 中 [Job] (如果有) [作为父 Job][parentJob] - * - * @see parentJob - * @see context - * - * @see CoroutineScope.globalEventChannel `GlobalEventChannel.parentScope()` 的扩展 - */ - public actual fun parentScope(coroutineScope: CoroutineScope): EventChannel { - return context(coroutineScope.coroutineContext) - } - - /** - * 指定协程父 [Job]. 之后在此 [EventChannel] 下创建的事件监听器都会成为 [job] 的子任务, 当 [job] 被取消时, 所有的事件监听器都会被取消. - * - * 注意: 监听器不会失败 ([Job.cancel]). 监听器处理过程的异常都会被捕获然后交由 [CoroutineExceptionHandler] 处理, 因此 [job] 不会因为子任务监听器的失败而被取消. - * - * @see parentScope - * @see context - */ - public actual fun parentJob(job: Job): EventChannel { - return context(job) - } - - // endregion - - // region subscribe - - /** - * 创建一个事件监听器, 监听事件通道中所有 [E] 及其子类事件. - * - * 每当 [事件广播][Event.broadcast] 时, [handler] 都会被执行. - * - * - * ## 创建监听 - * 调用本函数: - * ``` - * eventChannel.subscribe { /* 会收到此通道中的所有是 E 的事件 */ } - * ``` - * - * ## 生命周期 - * - * ### 通过协程作用域管理监听器 - * 本函数将会创建一个 [Job], 成为 [parentJob] 中的子任务. 可创建一个 [CoroutineScope] 来管理所有的监听器: - * ``` - * val scope = CoroutineScope(SupervisorJob()) - * - * val scopedChannel = eventChannel.parentScope(scope) // 将协程作用域 scope 附加到这个 EventChannel - * - * scopedChannel.subscribeAlways { /* ... */ } // 启动监听, 监听器协程会作为 scope 的子任务 - * scopedChannel.subscribeAlways { /* ... */ } // 启动监听, 监听器协程会作为 scope 的子任务 - * - * scope.cancel() // 停止了协程作用域, 也就取消了两个监听器 - * ``` - * - * 这个函数返回 [Listener], 它是一个 [CompletableJob]. 它会成为 [parentJob] 或 [parentScope] 的一个 [子任务][Job] - * - * ### 停止监听 - * 如果 [handler] 返回 [ListeningStatus.STOPPED] 监听器将被停止. - * - * 也可以通过 [subscribe] 返回值 [Listener] 的 [Listener.complete] - * - * ## 监听器调度 - * 监听器会被创建一个协程任务, 语义上在 [parentScope] 下运行. - * 通过 Kotlin [默认协程调度器][Dispatchers.Default] 在固定的全局共享线程池里执行, 除非有 [coroutineContext] 指定. - * - * 默认在 [handler] 中不能处理阻塞任务. 阻塞任务将会阻塞一个 Kotlin 全局协程调度线程并可能导致严重问题. - * 请通过 `withContext(Dispatchers.IO) { }` 等方法执行阻塞工作. - * - * ## 异常处理 - * - * **监听过程抛出的异常是需要尽可能避免的, 因为这将产生不确定性.** - * - * 当参数 [handler] 处理事件抛出异常时, 只会从监听方协程上下文 ([CoroutineContext]) 寻找 [CoroutineExceptionHandler] 处理异常, 即如下顺序: - * 1. 本函数参数 [coroutineContext] - * 2. [EventChannel.defaultCoroutineContext] - * 3. 若以上步骤无法获取 [CoroutineExceptionHandler], 则只会在日志记录异常. - * 因此建议先指定 [CoroutineExceptionHandler] (可通过 [EventChannel.exceptionHandler]) 再监听事件, 或者在监听事件中捕获异常. - * - * 因此, 广播方 ([Event.broadcast]) 不会知晓监听方产生的异常, 其 [Event.broadcast] 过程也不会因监听方产生异常而提前结束. - * - * ***备注***: 在 2.11 以前, 发生上述异常时还会从广播方和有关 [Bot] 协程域获取 [CoroutineExceptionHandler]. 因此行为不稳定而在 2.11 变更为上述过程. - * - * 事件处理时抛出异常不会停止监听器. - * - * 建议在事件处理中 (即 [handler] 里) 处理异常, - * 或在参数 [coroutineContext] 中添加 [CoroutineExceptionHandler], 或通过 [EventChannel.exceptionHandler]. - * - * ## 并发安全性 - * 基于 [concurrency] 参数, 事件监听器可以被允许并行执行. - * - * - 若 [concurrency] 为 [ConcurrencyKind.CONCURRENT], [handler] 可能被并行调用, 需要保证并发安全. - * - 若 [concurrency] 为 [ConcurrencyKind.LOCKED], [handler] 会被 [Mutex] 限制, 串行异步执行. - * - * ## 衍生监听方法 - * - * 这些方法仅 Kotlin 可用. - * - * - [syncFromEvent]: 挂起当前协程, 监听一个事件, 并尝试从这个事件中**获取**一个值 - * - [nextEvent]: 挂起当前协程, 直到监听到特定类型事件的广播并通过过滤器, 返回这个事件实例. - * - * @param coroutineContext 在 [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext]. - * @param concurrency 并发类型. 查看 [ConcurrencyKind] - * @param priority 监听优先级,优先级越高越先执行 - * @param handler 事件处理器. 在接收到事件时会调用这个处理器. 其返回值意义参考 [ListeningStatus]. 其异常处理参考上文 - * - * @return 监听器实例. 此监听器已经注册到指定事件上, 在事件广播时将会调用 [handler] - * - * - * @see selectMessages 以 `when` 的语法 '选择' 即将到来的一条消息. - * @see whileSelectMessages 以 `when` 的语法 '选择' 即将到来的所有消息, 直到不满足筛选结果. - * - * @see subscribeAlways 一直监听 - * @see subscribeOnce 只监听一次 - * - * @see subscribeMessages 监听消息 DSL - */ - public actual inline fun subscribe( - coroutineContext: CoroutineContext, - concurrency: ConcurrencyKind, - priority: EventPriority, - noinline handler: suspend E.(E) -> ListeningStatus, - ): Listener = subscribe(E::class, coroutineContext, concurrency, priority, handler) - - /** - * 与 [subscribe] 的区别是接受 [eventClass] 参数, 而不使用 `reified` 泛型. 通常推荐使用具体化类型参数. - * - * @return 监听器实例. 此监听器已经注册到指定事件上, 在事件广播时将会调用 [handler] - * @see subscribe - */ - public actual fun subscribe( - eventClass: KClass, - coroutineContext: CoroutineContext, - concurrency: ConcurrencyKind, - priority: EventPriority, - handler: suspend E.(E) -> ListeningStatus, - ): Listener = subscribeInternal( - eventClass, - createListener0(coroutineContext, concurrency, priority) { it.handler(it); } - ) - - /** - * 创建一个事件监听器, 监听事件通道中所有 [E] 及其子类事件. - * 每当 [事件广播][Event.broadcast] 时, [handler] 都会被执行. - * - * 可在任意时候通过 [Listener.complete] 来主动停止监听. - * - * @param concurrency 并发类型默认为 [CONCURRENT] - * @param coroutineContext 在 [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext] - * @param priority 处理优先级, 优先级高的先执行 - * - * @return 监听器实例. 此监听器已经注册到指定事件上, 在事件广播时将会调用 [handler] - * - * @see subscribe 获取更多说明 - */ - public actual inline fun subscribeAlways( - coroutineContext: CoroutineContext, - concurrency: ConcurrencyKind, - priority: EventPriority, - noinline handler: suspend E.(E) -> Unit, - ): Listener = subscribeAlways(E::class, coroutineContext, concurrency, priority, handler) - - - /** - * @see subscribe - * @see subscribeAlways - */ - public actual fun subscribeAlways( - eventClass: KClass, - coroutineContext: CoroutineContext, - concurrency: ConcurrencyKind, - priority: EventPriority, - handler: suspend E.(E) -> Unit, - ): Listener = subscribeInternal( - eventClass, - createListener0(coroutineContext, concurrency, priority) { it.handler(it); ListeningStatus.LISTENING } - ) - - /** - * 创建一个事件监听器, 监听事件通道中所有 [E] 及其子类事件, 只监听一次. - * 当 [事件广播][Event.broadcast] 时, [handler] 会被执行. - * - * 可在任意时候通过 [Listener.complete] 来主动停止监听. - * - * @param coroutineContext 在 [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext] - * @param priority 处理优先级, 优先级高的先执行 - * - * @see subscribe 获取更多说明 - */ - public actual inline fun subscribeOnce( - coroutineContext: CoroutineContext, - priority: EventPriority, - noinline handler: suspend E.(E) -> Unit, - ): Listener = subscribeOnce(E::class, coroutineContext, priority, handler) - - /** - * @see subscribeOnce - */ - public actual fun subscribeOnce( - eventClass: KClass, - coroutineContext: CoroutineContext, - priority: EventPriority, - handler: suspend E.(E) -> Unit, - ): Listener = subscribeInternal( - eventClass, - createListener0(coroutineContext, ConcurrencyKind.LOCKED, priority) { it.handler(it); ListeningStatus.STOPPED } - ) - - // endregion - - // region impl - - - // protected, to hide from users - @MiraiInternalApi - protected actual abstract fun registerListener(eventClass: KClass, listener: Listener) - - // to overcome visibility issue - @OptIn(MiraiInternalApi::class) - internal actual fun registerListener0(eventClass: KClass, listener: Listener) { - return registerListener(eventClass, listener) - } - - private fun , E : Event> subscribeInternal(eventClass: KClass, listener: L): L { - registerListener0(eventClass, listener) - return listener - } - - /** - * Creates [Listener] instance using the [listenerBlock] action. - */ -// @Contract("_ -> new") // always creates new instance - @MiraiInternalApi - protected actual abstract fun createListener( - coroutineContext: CoroutineContext, - concurrencyKind: ConcurrencyKind, - priority: EventPriority, - listenerBlock: suspend (E) -> ListeningStatus, - ): Listener - - // to overcome visibility issue - @OptIn(MiraiInternalApi::class) - internal actual fun createListener0( - coroutineContext: CoroutineContext, - concurrencyKind: ConcurrencyKind, - priority: EventPriority, - listenerBlock: suspend (E) -> ListeningStatus, - ): Listener = createListener(coroutineContext, concurrencyKind, priority, listenerBlock) - - // endregion -} diff --git a/mirai-core-api/src/nativeMain/kotlin/event/MessageSelectBuilderUnit.kt b/mirai-core-api/src/nativeMain/kotlin/event/MessageSelectBuilderUnit.kt deleted file mode 100644 index 09e599463..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/event/MessageSelectBuilderUnit.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2023 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.event - -import net.mamoe.mirai.event.events.MessageEvent -import net.mamoe.mirai.utils.MiraiInternalApi - -/** - * [selectMessagesUnit] 或 [selectMessages] 时的 DSL 构建器. - * - * 它是特殊化的消息监听 ([EventChannel.subscribeMessages]) DSL - * - * @see MessageSubscribersBuilder 查看上层 API - */ -@OptIn(MiraiInternalApi::class) -public actual abstract class MessageSelectBuilderUnit @PublishedApi internal actual constructor( - ownerMessagePacket: M, - stub: Any?, - subscriber: (M.(String) -> Boolean, MessageListener) -> Unit -) : CommonMessageSelectBuilderUnit(ownerMessagePacket, stub, subscriber) \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/internal/message/overwritePolymorphicWith.kt b/mirai-core-api/src/nativeMain/kotlin/internal/message/overwritePolymorphicWith.kt deleted file mode 100644 index a530e025a..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/internal/message/overwritePolymorphicWith.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.internal.message - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.modules.SerializersModule -import kotlin.reflect.KClass - -internal actual fun SerializersModule.overwritePolymorphicWith( - type: KClass, - serializer: KSerializer -): SerializersModule { - throw UnsupportedOperationException("overwritePolymorphicWith is not supported on native.") -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/internal/utils/ExternalResourceImplByByteArray.kt b/mirai-core-api/src/nativeMain/kotlin/internal/utils/ExternalResourceImplByByteArray.kt deleted file mode 100644 index 5cdd53881..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/internal/utils/ExternalResourceImplByByteArray.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils - -import io.ktor.utils.io.core.* -import kotlinx.coroutines.CompletableDeferred -import net.mamoe.mirai.utils.* - -internal class ExternalResourceImplByByteArray( - private val data: ByteArray, - formatName: String? -) : ExternalResource { - override val size: Long = data.size.toLong() - override val md5: ByteArray by lazy { data.md5() } - override val sha1: ByteArray by lazy { data.sha1() } - override val formatName: String by lazy { - formatName ?: getFileType(data.copyOf(COUNT_BYTES_USED_FOR_DETECTING_FILE_TYPE)) - ?: ExternalResource.DEFAULT_FORMAT_NAME - } - override val closed: CompletableDeferred = CompletableDeferred() - override val origin: Any - get() = data//.clone() - - @MiraiInternalApi - override fun input(): Input = ByteReadPacket(data) - - override fun close() { - kotlin.runCatching { closed.complete(Unit) } - } -} diff --git a/mirai-core-api/src/nativeMain/kotlin/internal/utils/Marker.kt b/mirai-core-api/src/nativeMain/kotlin/internal/utils/Marker.kt deleted file mode 100644 index 801bc1440..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/internal/utils/Marker.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.internal.utils - -internal actual interface Marker { - actual fun addParents(vararg parent: Marker) -} - -internal class MarkerImpl( - private val name: String -) : Marker { - override fun addParents(vararg parent: Marker) { - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/internal/utils/MarkerManager.kt b/mirai-core-api/src/nativeMain/kotlin/internal/utils/MarkerManager.kt deleted file mode 100644 index 352122dd6..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/internal/utils/MarkerManager.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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.internal.utils - -internal actual object MarkerManager { - actual fun getMarker(name: String): Marker { - return MarkerImpl(name) - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/message/action/AsyncRecallResult.kt b/mirai-core-api/src/nativeMain/kotlin/message/action/AsyncRecallResult.kt deleted file mode 100644 index cb8ce069f..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/message/action/AsyncRecallResult.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.message.action - -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import net.mamoe.mirai.message.data.MessageSource -import net.mamoe.mirai.message.data.MessageSource.Key.recallIn - -/** - * 异步撤回结果. - * - * 可由 [MessageSource.recallIn] 返回得到. - * - * ## 用法 - * - * ### 获取撤回失败时的异常 - * - * ``` - * val exception = result.exception.await() // 挂起协程并等待撤回的结果. - * if (exception == null) { - * // 撤回成功 - * } else { - * // 撤回失败 - * } - * ``` - * - * 若仅需要了解撤回是否成功而不需要获取详细异常实例, 可使用 [isSuccess] - * - * @see MessageSource.recallIn - */ -public actual class AsyncRecallResult internal actual constructor( - /** - * 撤回时产生的异常, 当撤回成功时为 `null`. - */ - public actual val exception: Deferred, -) { - /** - * 撤回是否成功. - */ - public actual val isSuccess: Deferred by lazy { - CompletableDeferred().apply { - exception.invokeOnCompletion { - complete(it == null) - } - } - } - - /** - * 挂起协程直到撤回完成, 返回撤回时产生的异常. 当撤回成功时返回 `null`. - */ - public actual suspend fun awaitException(): Throwable? { - return exception.await() - } - - /** - * 挂起协程直到撤回完成, 返回撤回的结果. - */ - public actual suspend fun awaitIsSuccess(): Boolean { - return isSuccess.await() - } -} diff --git a/mirai-core-api/src/nativeMain/kotlin/message/data/FileMessage.kt b/mirai-core-api/src/nativeMain/kotlin/message/data/FileMessage.kt deleted file mode 100644 index f458f4e24..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/message/data/FileMessage.kt +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2019-2023 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.message.data - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import net.mamoe.mirai.Mirai -import net.mamoe.mirai.contact.FileSupported -import net.mamoe.mirai.contact.file.AbsoluteFile -import net.mamoe.mirai.event.events.MessageEvent -import net.mamoe.mirai.message.code.CodableMessage -import net.mamoe.mirai.message.code.internal.appendStringAsMiraiCode -import net.mamoe.mirai.message.data.visitor.MessageVisitor -import net.mamoe.mirai.utils.MiraiExperimentalApi -import net.mamoe.mirai.utils.MiraiInternalApi -import net.mamoe.mirai.utils.NotStableForInheritance -import net.mamoe.mirai.utils.safeCast - -/** - * 文件消息. - * - * [name] 与 [size] 只供本地使用, 发送消息时只会使用 [id] 和 [internalId]. - * - * 注: [FileMessage] 不可二次发送 - * - * ### 文件操作 - * 要下载这个文件, 可通过 [toAbsoluteFile] 获取到 [AbsoluteFile] 然后操作. - * - * 要获取到 [FileMessage], 可以通过 [MessageEvent.message] 获取, 或通过 [AbsoluteFile.toMessage] 得到. - * - * @since 2.5 - * @suppress [FileMessage] 的使用是稳定的, 但自行实现不稳定. - */ -@Serializable(FileMessage.Serializer::class) -@SerialName(FileMessage.SERIAL_NAME) -@NotStableForInheritance -public actual interface FileMessage : MessageContent, ConstrainSingle, CodableMessage { - /** - * 服务器需要的某种 ID. - */ - public actual val id: String - - /** - * 服务器需要的某种 ID. - */ - public actual val internalId: Int - - /** - * 文件名 - */ - public actual val name: String - - /** - * 文件大小 bytes - */ - public actual val size: Long - - actual override fun contentToString(): String = "[文件]$name" // orthodox - - @MiraiExperimentalApi - actual override fun appendMiraiCodeTo(builder: StringBuilder) { - builder.append("[mirai:file:") - builder.appendStringAsMiraiCode(id).append(",") - builder.append(internalId).append(",") - builder.appendStringAsMiraiCode(name).append(",") - builder.append(size).append("]") - } - - /** - * 获取一个对应的 [AbsoluteFile]. 当目标群或好友不存在这个文件时返回 `null`. - * - * @since 2.8 - */ - public actual suspend fun toAbsoluteFile(contact: FileSupported): AbsoluteFile? - - actual override val key: Key get() = Key - - @MiraiInternalApi - actual override fun accept(visitor: MessageVisitor, data: D): R { - return visitor.visitFileMessage(this, data) - } - - /** - * 注意, baseKey [MessageContent] 不稳定. 未来可能会有变更. - */ - public actual companion object Key : - AbstractPolymorphicMessageKey( - MessageContent, { it.safeCast() }) { - - public actual const val SERIAL_NAME: String = "FileMessage" - - /** - * 构造 [FileMessage] - * @since 2.5 - */ - public actual fun create(id: String, internalId: Int, name: String, size: Long): FileMessage = - Mirai.createFileMessage(id, internalId, name, size) - } - - public actual object Serializer : - KSerializer by @OptIn(MiraiInternalApi::class) FallbackFileMessageSerializer() -} diff --git a/mirai-core-api/src/nativeMain/kotlin/package.kt b/mirai-core-api/src/nativeMain/kotlin/package.kt deleted file mode 100644 index 8a63cebca..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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 diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt b/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt deleted file mode 100644 index 9d5fbc47c..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/BotConfiguration.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2019-2023 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 io.ktor.utils.io.core.* -import net.mamoe.mirai.Bot - -/** - * [BotConfiguration] 的 Native 平台特别配置 - * @since 2.15 - */ -@NotStableForInheritance -public actual abstract class AbstractBotConfiguration { // open for Java - protected actual abstract var deviceInfo: ((Bot) -> DeviceInfo)? - protected actual abstract var networkLoggerSupplier: ((Bot) -> MiraiLogger) - protected actual abstract var botLoggerSupplier: ((Bot) -> MiraiLogger) - - /** - * 工作目录. 默认为当前目录 - */ - public var workingDir: String = "." - - /** - * 使用文件存储设备信息. - * - * 此函数只在 JVM 和 Android 有效. 在其他平台将会抛出异常. - * @param filepath 文件路径. 默认是相对于 [workingDir] 的文件 "device.json". - * @see deviceInfo - */ - @BotConfiguration.ConfigurationDsl - public actual fun fileBasedDeviceInfo(filepath: String) { - deviceInfo = { - val file = MiraiFile.create(workingDir).resolve(filepath) - if (!file.exists()) { - file.writeText(DeviceInfoManager.serialize(DeviceInfo.random(), BotConfiguration.json)) - } - DeviceInfoManager.deserialize(file.readText(), BotConfiguration.json) { - file.writeText(DeviceInfoManager.serialize(it, BotConfiguration.json)) - } - - } - } - - /** - * 缓存数据目录路径. 若 [cacheDir] 为绝对路径, 将解析该绝对路径, 否则作为相对于 [workingDir] 的路径解析. - * 例如, `cache` 将会解析为 `$workingDir/cache`, 而 `/Users/Chisato/Desktop/bot/cache` 指代绝对路径, 将解析为绝对路径. - * - * 缓存目录保存的内容均属于不稳定的 Mirai 内部数据, 请不要手动修改它们. 清空缓存不会影响功能. 只会导致一些操作如读取全部群列表要重新进行. - * 默认启用的缓存可以加快登录过程. - * - * 注意: 这个目录只存储能在 [BotConfiguration] 配置的内容, 即包含: - * - 联系人列表 - * - 登录服务器列表 - * - 资源服务秘钥 - * - * 其他内容如通过 [Input] 发送图片时的缓存使用 [FileCacheStrategy], 默认使用系统临时文件且会在关闭时删除文件. - * - * @since 2.4 - */ - public var cacheDir: String = "cache" - - internal actual fun applyMppCopy(new: BotConfiguration) { - new.workingDir = workingDir - new.cacheDir = cacheDir - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/DeviceInfo.kt b/mirai-core-api/src/nativeMain/kotlin/utils/DeviceInfo.kt deleted file mode 100644 index ff21cdb40..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/DeviceInfo.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2019-2023 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.Serializable -import kotlinx.serialization.Transient -import kotlin.random.Random - -/** - * 表示设备信息 - * @see DeviceInfoBuilder - */ -@Serializable(DeviceInfoV1LegacySerializer::class) -public actual class DeviceInfo -@Deprecated(DeviceInfoConstructorDeprecationMessage, level = DeprecationLevel.WARNING) -@DeprecatedSinceMirai(warningSince = "2.15") // planned internal -public actual constructor( - public actual val display: ByteArray, - public actual val product: ByteArray, - public actual val device: ByteArray, - public actual val board: ByteArray, - public actual val brand: ByteArray, - public actual val model: ByteArray, - public actual val bootloader: ByteArray, - public actual val fingerprint: ByteArray, - public actual val bootId: ByteArray, - public actual val procVersion: ByteArray, - public actual val baseBand: ByteArray, - public actual val version: Version, - public actual val simInfo: ByteArray, - public actual val osType: ByteArray, - public actual val macAddress: ByteArray, - public actual val wifiBSSID: ByteArray, - public actual val wifiSSID: ByteArray, - public actual val imsiMd5: ByteArray, - public actual val imei: String, - public actual val apn: ByteArray, - public actual val androidId: ByteArray, -) { - public actual val ipAddress: ByteArray get() = byteArrayOf(192.toByte(), 168.toByte(), 1, 123) - - init { - require(imsiMd5.size == 16) { "Bad `imsiMd5.size`. Required 16, given ${imsiMd5.size}." } - } - - @Transient - @MiraiInternalApi - public actual val guid: ByteArray = generateGuid(androidId, macAddress) - - @Serializable - public actual class Version actual constructor( - public actual val incremental: ByteArray, - public actual val release: ByteArray, - public actual val codename: ByteArray, - public actual val sdk: Int - ) { - /** - * @since 2.9 - */ - actual override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Version) return false - - if (!incremental.contentEquals(other.incremental)) return false - if (!release.contentEquals(other.release)) return false - if (!codename.contentEquals(other.codename)) return false - if (sdk != other.sdk) return false - - return true - } - - /** - * @since 2.9 - */ - actual override fun hashCode(): Int { - var result = incremental.contentHashCode() - result = 31 * result + release.contentHashCode() - result = 31 * result + codename.contentHashCode() - result = 31 * result + sdk - return result - } - } - - public actual companion object { - internal actual val logger = MiraiLogger.Factory.create(DeviceInfo::class, "DeviceInfo") - - /** - * 生成随机 [DeviceInfo] - * - * @see DeviceInfoBuilder - * @since 2.0 - */ - public actual fun random(): DeviceInfo = random(Random.Default) - - /** - * 使用特定随机数生成器生成 [DeviceInfo] - * - * @see DeviceInfoBuilder - * @since 2.9 - */ - public actual fun random(random: Random): DeviceInfo { - return DeviceInfoCommonImpl.randomDeviceInfo(random) - } - - /** - * 将此 [DeviceInfo] 序列化为字符串. 序列化的字符串可以在以后通过 [DeviceInfo.deserializeFromString] 反序列化为 [DeviceInfo]. - * - * 序列化的字符串有兼容性保证, 在旧版 mirai 序列化的字符串, 可以在新版 mirai 使用. 但新版 mirai 序列化的字符串不一定能在旧版使用. - * - * @since 2.15 - */ - public actual fun serializeToString(deviceInfo: DeviceInfo): String = DeviceInfoManager.serialize(deviceInfo) - - /** - * 将通过 [serializeToString] 序列化得到的字符串反序列化为 [DeviceInfo]. - * 此函数兼容旧版 mirai 序列化的字符串. - * @since 2.15 - */ - public actual fun deserializeFromString(string: String): DeviceInfo = DeviceInfoManager.deserialize(string) - } - - /** - * @since 2.9 - */ - @Suppress("DuplicatedCode") - actual override fun equals(other: Any?): Boolean { - return DeviceInfoCommonImpl.equalsImpl(this, other) - } - - - /** - * @since 2.9 - */ - actual override fun hashCode(): Int { - return DeviceInfoCommonImpl.hashCodeImpl(this) - } -} diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/ExternalResource.kt b/mirai-core-api/src/nativeMain/kotlin/utils/ExternalResource.kt deleted file mode 100644 index 07be744f9..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/ExternalResource.kt +++ /dev/null @@ -1,273 +0,0 @@ -/* - * 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 io.ktor.utils.io.core.* -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import net.mamoe.mirai.contact.Contact -import net.mamoe.mirai.contact.Contact.Companion.sendImage -import net.mamoe.mirai.contact.Contact.Companion.uploadImage -import net.mamoe.mirai.internal.utils.* -import net.mamoe.mirai.message.MessageReceipt -import net.mamoe.mirai.message.data.Image -import net.mamoe.mirai.message.data.sendTo -import net.mamoe.mirai.utils.ExternalResource.Companion.sendAsImageTo -import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource -import net.mamoe.mirai.utils.ExternalResource.Companion.uploadAsImage - -/** - * 一个*不可变的*外部资源. 仅包含资源内容, 大小, 文件类型, 校验值而不包含文件名, 文件位置等. 外部资源有可能是一个文件, 也有可能只存在于内存, 或者以任意其他方式实现. - * - * [ExternalResource] 在创建之后就应该保持其属性的不变, 即任何时候获取其属性都应该得到相同结果, 任何时候打开流都得到的一样的数据. - * - * # 创建 - * - [ByteArray.toExternalResource] - * - * ## 在 Kotlin 获得和使用 [ExternalResource] 实例 - * - * ``` - * file.toExternalResource().use { resource -> // 安全地使用资源 - * contact.uploadImage(resource) // 用来上传图片 - * contact.files.uploadNewFile("/foo/test.txt", file) // 或者用来上传文件 - * } - * ``` - * - * 注意, 若使用 [Input], 必须手动关闭 [Input]. 一种使用情况示例: - * - * ``` - * inputStream.use { input -> // 安全地使用 InputStream - * input.toExternalResource().use { resource -> // 安全地使用资源 - * contact.uploadImage(resource) // 用来上传图片 - * contact.files.uploadNewFile("/foo/test.txt", file) // 或者用来上传文件 - * } - * } - * ``` - * - * ## 在 Java 获得和使用 [ExternalResource] 实例 - * - * ``` - * try (ExternalResource resource = ExternalResource.create(file)) { // 使用文件 file - * contact.uploadImage(resource); // 用来上传图片 - * contact.files.uploadNewFile("/foo/test.txt", file); // 或者用来上传文件 - * } - * ``` - * - * 注意, 若使用 [Input], 必须手动关闭 [Input]. 一种使用情况示例: - * - * ```java - * try (InputStream stream = ...) { // 安全地使用 InputStream - * try (ExternalResource resource = ExternalResource.create(stream)) { // 安全地使用资源 - * contact.uploadImage(resource); // 用来上传图片 - * contact.files.uploadNewFile("/foo/test.txt", file); // 或者用来上传文件 - * } - * } - * ``` - * - * # 释放 - * - * 当 [ExternalResource] 创建时就可能会打开一些资源. - * 类似于 [Input], [ExternalResource] 需要被 [关闭][close]. - * - * ## 未释放资源的补救策略 - * - * 自 2.7 起, 每个 mirai 内置的 [ExternalResource] 实现都有引用跟踪, 当 [ExternalResource] 被 GC 后会执行被动释放. - * 这依赖于 JVM 垃圾收集策略, 因此不可靠, 资源仍然需要手动 close. - * - * ## 使用单次自动释放 - * - * 若创建的资源仅需要*很快地*使用一次, 可使用 [toAutoCloseable] 获得在使用一次后就会自动关闭的资源. - * - * 示例: - * ```java - * contact.uploadImage(ExternalResource.create(file).toAutoCloseable()); // 创建并立即使用单次自动释放的资源 - * ``` - * - * **注意**: 如果仅使用 [toAutoCloseable] 而不通过 [Contact.uploadImage] 等 mirai 内置方法使用资源, 资源仍然会处于打开状态且不会被自动关闭. - * 最终资源会由上述*未释放资源的补救策略*关闭, 但这依赖于 JVM 垃圾收集策略而不可靠. - * 因此建议在创建单次自动释放的资源后就尽快使用它, 否则仍然需要考虑在正确的时间及时关闭资源. - * - * # 实现 [ExternalResource] - * - * 可以自行实现 [ExternalResource]. 但通常上述创建方法已足够使用. - * - * 建议继承 [AbstractExternalResource], 这将支持上文提到的资源自动释放功能. - * - * 实现时需保持 [ExternalResource] 在构造后就不可变, 并且所有属性都总是返回一个固定值. - * - * @see ExternalResource.uploadAsImage 将资源作为图片上传, 得到 [Image] - * @see ExternalResource.sendAsImageTo 将资源作为图片发送 - * @see Contact.uploadImage 上传一个资源作为图片, 得到 [Image] - * @see Contact.sendImage 发送一个资源作为图片 - * - * @see FileCacheStrategy - */ -public actual interface ExternalResource : Closeable { - - /** - * 是否在 _使用一次_ 后自动 [close]. - * - * 该属性仅供调用方参考. 如 [Contact.uploadImage] 会在方法结束时关闭 [isAutoClose] 为 `true` 的 [ExternalResource], 无论上传图片是否成功. - * - * 所有 mirai 内置的上传图片, 上传语音等方法都支持该行为. - * - * @since 2.8 - */ - public actual val isAutoClose: Boolean - get() = false - - /** - * 文件内容 MD5. 16 bytes - */ - public actual val md5: ByteArray - - /** - * 文件内容 SHA1. 16 bytes - * @since 2.5 - */ - public actual val sha1: ByteArray - get() = - throw UnsupportedOperationException("ExternalResource.sha1 is not implemented by ${this::class.simpleName}") - // 如果你要实现 [ExternalResource], 你也应该实现 [sha1]. - // 这里默认抛出 [UnsupportedOperationException] 是为了 (姑且) 兼容 2.5 以前的版本的实现. - - - /** - * 文件格式,如 "png", "amr". 当无法自动识别格式时为 [DEFAULT_FORMAT_NAME]. - * - * 默认会从文件头识别, 支持的文件类型: - * png, jpg, gif, tif, bmp, amr, silk - * - * @see net.mamoe.mirai.utils.getFileType - * @see net.mamoe.mirai.utils.FILE_TYPES - * @see DEFAULT_FORMAT_NAME - */ - public actual val formatName: String - - /** - * 文件大小 bytes - */ - public actual val size: Long - - /** - * 当 [close] 时会 [CompletableDeferred.complete] 的 [Deferred]. - */ - public actual val closed: Deferred - - /** - * 打开 [Input]. 在返回的 [Input] 被 [关闭][Input.close] 前无法再次打开流. - * - * 关闭此流不会关闭 [ExternalResource]. - * @throws IllegalStateException 当上一个流未关闭又尝试打开新的流时抛出 - * - * @since 2.13 - */ - @MiraiInternalApi - public actual fun input(): Input - - @MiraiInternalApi - public actual fun calculateResourceId(): String { - return generateImageId(md5, formatName.ifEmpty { DEFAULT_FORMAT_NAME }) - } - - /** - * 该 [ExternalResource] 的数据来源, 可能有以下的返回 - * - * - [ByteArray] RAM - * - ... - * - * implementation note: - * - * - 对于无法二次读取的数据来源 (如 [Input]), 返回 `null` - * - 不要返回 [String], 没有约定 [String] 代表什么 - * - 数据源外漏会严重影响 [inputStream] 等的执行的可以返回 `null` (如文件句柄) - * - * @since 2.8.0 - */ - public actual val origin: Any? get() = null - - /** - * 创建一个在 _使用一次_ 后就会自动 [close] 的 [ExternalResource]. - * - * @since 2.8.0 - */ - public actual fun toAutoCloseable(): ExternalResource { - return if (isAutoClose) this else { - val delegate = this - object : ExternalResource by delegate { - override val isAutoClose: Boolean get() = true - override fun toString(): String = "ExternalResourceWithAutoClose(delegate=$delegate)" - override fun toAutoCloseable(): ExternalResource { - return this - } - } - } - } - - - public actual companion object { - /** - * 在无法识别文件格式时使用的默认格式名. "mirai". - * - * @see ExternalResource.formatName - */ - public actual const val DEFAULT_FORMAT_NAME: String = "mirai" - - /////////////////////////////////////////////////////////////////////////// - // region toExternalResource - /////////////////////////////////////////////////////////////////////////// - - /** - * 创建 [ExternalResource]. 注意, 返回的 [ExternalResource] 需要在使用完毕后调用 [ExternalResource.close] 关闭. - * - * @param formatName 查看 [ExternalResource.formatName] - */ - public actual fun ByteArray.toExternalResource(formatName: String?): ExternalResource = - ExternalResourceImplByByteArray(this, formatName) - - // endregion - - /////////////////////////////////////////////////////////////////////////// - // region sendAsImageTo - /////////////////////////////////////////////////////////////////////////// - - /** - * 将图片作为单独的消息发送给指定联系人. - * - * **注意**:本函数不会关闭 [ExternalResource]. - * - * @see Contact.uploadImage 上传图片 - * @see Contact.sendMessage 最终调用, 发送消息. - * - * @throws OverFileSizeMaxException - */ - public actual suspend fun ExternalResource.sendAsImageTo(contact: C): MessageReceipt = - contact.uploadImage(this).sendTo(contact) - - // endregion - - /////////////////////////////////////////////////////////////////////////// - // region uploadAsImage - /////////////////////////////////////////////////////////////////////////// - - /** - * 上传图片并构造 [Image]. 这个函数可能需消耗一段时间. - * - * **注意**:本函数不会关闭 [ExternalResource]. - * - * @param contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人. - * - * @see Contact.uploadImage 最终调用, 上传图片. - */ - public actual suspend fun ExternalResource.uploadAsImage(contact: Contact): Image = contact.uploadImage(this) - - // endregion - } -} diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/FileCacheStrategy.kt b/mirai-core-api/src/nativeMain/kotlin/utils/FileCacheStrategy.kt deleted file mode 100644 index a94ae52f0..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/FileCacheStrategy.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 - -/** - * 资源缓存策略. - * - * 注意: 本接口只用于 JVM 平台. 在 native 平台没有作用. - * - * 由于上传资源时服务器要求提前给出 MD5 和文件大小等数据, 一些资源如 [InputStream] 需要首先缓存才能使用. - * - * 资源的缓存都是将 [InputStream] 缓存未 [ExternalResource]. 根据 [FileCacheStrategy] 实现不同, 可以以临时文件存储, 也可以在数据库或是内存按需存储. - * Mirai 内置的实现有 [内存存储][MemoryCache] 和 [临时文件存储][TempCache]. - * 操作 [ExternalResource.toExternalResource] 时将会使用 [IMirai.FileCacheStrategy]. 可以覆盖, 示例: - * ``` - * // Kotlin - * Mirai.FileCacheStrategy = FileCacheStrategy.TempCache() // 使用系统默认缓存路径, 也是默认的行为 - * Mirai.FileCacheStrategy = FileCacheStrategy.TempCache(File("C:/cache")) // 使用自定义缓存路径 - * - * // Java - * Mirai.getInstance().setFileCacheStrategy(new FileCacheStrategy.TempCache()); // 使用系统默认缓存路径, 也是默认的行为 - * Mirai.getInstance().setFileCacheStrategy(new FileCacheStrategy.TempCache(new File("C:/cache"))); // 使用自定义的缓存路径 - * ``` - * - * 此接口的实现和使用都是稳定的. 自行实现的 [FileCacheStrategy] 也可以被 Mirai 使用. - * - * 注意, 此接口目前仅缓存 [InputStream] 等一次性数据. 好友列表等数据由每个 [Bot] 的 [BotConfiguration.cacheDir] 缓存. - * - * ### 使用 [FileCacheStrategy] 的操作 - * - [ExternalResource.toExternalResource] - * - [ExternalResource.uploadAsImage] - * - [ExternalResource.sendAsImageTo] - * - * @see ExternalResource - */ -public actual interface FileCacheStrategy { - public actual companion object { - /** - * 当前平台下默认的缓存策略. 注意, 这可能不是 Mirai 全局默认使用的, Mirai 从 [IMirai.FileCacheStrategy] 获取. - * - * @see IMirai.FileCacheStrategy - */ - @MiraiExperimentalApi - public actual val PlatformDefault: FileCacheStrategy = object : FileCacheStrategy {} - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/LoginSolver.kt b/mirai-core-api/src/nativeMain/kotlin/utils/LoginSolver.kt deleted file mode 100644 index 675352e71..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/LoginSolver.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 object PlatformLoginSolverImplementations { - actual val isSliderCaptchaSupported: Boolean get() = false - actual val default: LoginSolver? get() = null -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/MiraiLogger.kt b/mirai-core-api/src/nativeMain/kotlin/utils/MiraiLogger.kt deleted file mode 100644 index d4af23e41..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/MiraiLogger.kt +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2019-2023 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 - -/** - * 日志记录器. - * - * ## Mirai 日志系统 - * - * Mirai 内建简单的日志系统, 即 [MiraiLogger]. [MiraiLogger] 的实现有 [SimpleLogger], [PlatformLogger], [SilentLogger]. - * - * ## 实现或使用 [MiraiLogger] - * - * 不建议实现或使用 [MiraiLogger]. 请优先考虑使用上述第三方框架. [MiraiLogger] 仅应用于兼容旧版本代码. - * - * @see SimpleLogger 简易 logger, 它将所有的日志记录操作都转移给 lambda `(String?, Throwable?) -> Unit` - * @see PlatformLogger 各个平台下的默认日志记录实现. - * @see SilentLogger 忽略任何日志记录操作的 logger 实例. - * - * @see MiraiLoggerPlatformBase 平台通用基础实现. 若 Mirai 自带的日志系统无法满足需求, 请继承这个类并实现其抽象函数. - */ -public actual interface MiraiLogger { - /** - * 可以 service 实现的方式覆盖. - * - * @since 2.7 - */ - public actual interface Factory { - /** - * 创建 [MiraiLogger] 实例. - * - * @param requester 请求创建 [MiraiLogger] 的对象的 class - * @param identity 对象标记 (备注) - */ - public actual fun create(requester: KClass<*>, identity: String?): MiraiLogger { - return create(requester) - } - - /** - * 创建 [MiraiLogger] 实例. - * - * @param requester 请求创建 [MiraiLogger] 的对象 - */ - public actual fun create(requester: KClass<*>): MiraiLogger { - throw UnsupportedOperationException() // Cannot be abstract since on JVM it is open - } - - public actual companion object INSTANCE : Factory by loadService(Factory::class, fallbackImplementation = { - @OptIn(MiraiInternalApi::class) - object : Factory { - override fun create(requester: KClass<*>): MiraiLogger { - return PlatformLogger(requester.simpleName ?: requester.qualifiedName) - } - - override fun create(requester: KClass<*>, identity: String?): MiraiLogger { - return PlatformLogger(identity ?: requester.simpleName ?: requester.qualifiedName) - } - } - }) - } - - public actual companion object; - - /** - * 日志的标记. 在 Mirai 中, identity 可为 - * - "Bot" - * - "BotNetworkHandler" - * 等. - * - * 它只用于帮助调试或统计. 十分建议清晰定义 identity - */ - public actual val identity: String? - - /** - * 获取 [MiraiLogger] 是否已开启 - * - * 除 [MiraiLoggerWithSwitch] 可控制开关外, 其他的所有 [MiraiLogger] 均一直开启. - */ - public actual val isEnabled: Boolean - - /** - * 当 VERBOSE 级别的日志启用时返回 `true`. - * - * 若 [isEnabled] 为 `false`, 返回 `false`. - * 其他情况下返回 [isEnabled] 的值. - * - * @since 2.7 - */ - public actual val isVerboseEnabled: Boolean get() = isEnabled - - /** - * 当 DEBUG 级别的日志启用时返回 `true` - * - * 若 [isEnabled] 为 `false`, 返回 `false`. - * 其他情况下返回 [isEnabled] 的值. - * - * @since 2.7 - */ - public actual val isDebugEnabled: Boolean get() = isEnabled - - /** - * 当 INFO 级别的日志启用时返回 `true` - * - * 若 [isEnabled] 为 `false`, 返回 `false`. - * 其他情况下返回 [isEnabled] 的值. - * - * @since 2.7 - */ - public actual val isInfoEnabled: Boolean get() = isEnabled - - /** - * 当 WARNING 级别的日志启用时返回 `true` - * - * 若 [isEnabled] 为 `false`, 返回 `false`. - * 其他情况下返回 [isEnabled] 的值. - * - * @since 2.7 - */ - public actual val isWarningEnabled: Boolean get() = isEnabled - - /** - * 当 ERROR 级别的日志启用时返回 `true` - * - * 若 [isEnabled] 为 `false`, 返回 `false`. - * 其他情况下返回 [isEnabled] 的值. - * - * @since 2.7 - */ - public actual val isErrorEnabled: Boolean get() = isEnabled - - /** - * 记录一个 `verbose` 级别的日志. - * 无关紧要的, 经常大量输出的日志应使用它. - */ - public actual fun verbose(message: String?) - - public actual fun verbose(e: Throwable?): Unit = verbose(null, e) - public actual fun verbose(message: String?, e: Throwable?) - - /** - * 记录一个 _调试_ 级别的日志. - */ - public actual fun debug(message: String?) - - public actual fun debug(e: Throwable?): Unit = debug(null, e) - public actual fun debug(message: String?, e: Throwable?) - - - /** - * 记录一个 _信息_ 级别的日志. - */ - public actual fun info(message: String?) - - public actual fun info(e: Throwable?): Unit = info(null, e) - public actual fun info(message: String?, e: Throwable?) - - - /** - * 记录一个 _警告_ 级别的日志. - */ - public actual fun warning(message: String?) - - public actual fun warning(e: Throwable?): Unit = warning(null, e) - public actual fun warning(message: String?, e: Throwable?) - - - /** - * 记录一个 _错误_ 级别的日志. - */ - public actual fun error(message: String?) - - public actual fun error(e: Throwable?): Unit = error(null, e) - public actual fun error(message: String?, e: Throwable?) - - /** 根据优先级调用对应函数 */ - public actual fun call(priority: SimpleLogger.LogPriority, message: String?, e: Throwable?): Unit = - @OptIn(MiraiExperimentalApi::class) - priority.correspondingFunction(this, message, e) -} diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/PlatformLogger.kt b/mirai-core-api/src/nativeMain/kotlin/utils/PlatformLogger.kt deleted file mode 100644 index d950a33e4..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/PlatformLogger.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 net.mamoe.mirai.internal.utils.StdoutLogger - -/** - * 当前平台的默认的日志记录器. - * - 在 _JVM 控制台_ 端的实现为 [println] - * - 在 _Android_ 端的实现为 `android.util.Log` - * - * - * 单条日志格式 (正则) 为: - * ```regex - * ^([\w-]*\s[\w:]*)\s(\w)\/(.*?):\s(.+)$ - * ``` - * 其中 group 分别为: 日期与时间, 严重程度, [identity], 消息内容. - * - * 示例: - * ```log - * 2020-05-21 19:51:09 V/Bot 123456789: Send: OidbSvc.0x88d_7 - * ``` - * - * 日期时间格式为 `yyyy-MM-dd HH:mm:ss`, - * - * 严重程度为 V, I, W, E. 分别对应 verbose, info, warning, error - * - * @see MiraiLogger.create - */ -@MiraiInternalApi -public actual open class PlatformLogger actual constructor(identity: String?) : - MiraiLoggerPlatformBase(), MiraiLogger { - - private val delegate = StdoutLogger(identity) - - override val identity: String? get() = delegate.identity - override val isEnabled: Boolean get() = delegate.isEnabled - override val isVerboseEnabled: Boolean get() = delegate.isVerboseEnabled - override val isDebugEnabled: Boolean get() = delegate.isDebugEnabled - override val isInfoEnabled: Boolean get() = delegate.isInfoEnabled - override val isWarningEnabled: Boolean get() = delegate.isWarningEnabled - override val isErrorEnabled: Boolean get() = delegate.isErrorEnabled - - override fun verbose0(message: String?, e: Throwable?) { - delegate.verbose0(message, e) - } - - override fun debug0(message: String?, e: Throwable?) { - delegate.debug(message, e) - } - - override fun info0(message: String?, e: Throwable?) { - delegate.info0(message, e) - } - - override fun warning0(message: String?, e: Throwable?) { - delegate.warning(message, e) - } - - override fun error0(message: String?, e: Throwable?) { - delegate.error0(message, e) - } -} \ No newline at end of file diff --git a/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt b/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt deleted file mode 100644 index a726cbab1..000000000 --- a/mirai-core-api/src/nativeMain/kotlin/utils/Streamable.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.flow.Flow -import kotlinx.coroutines.flow.toList -import net.mamoe.mirai.contact.announcement.Announcement -import net.mamoe.mirai.contact.announcement.Announcements - -/** - * 表示一个可以创建[数据流][Flow]的对象. - * - * 实现这个接口的对象可以看做为元素 [T] 的集合. - * 例如 [Announcements] 可以看作是 [Announcement] 的集合, - * 使用 [Announcements.asFlow] 可以获取到包含所有 [Announcement] 列表的 [Flow] - * 在 JVM, 还可以使用 `Announcements.asStream` 可以获取到包含所有 [Announcement] 列表的 `Stream`. - * - * @since 2.13 - */ -public actual interface Streamable { - /** - * 创建一个能获取 [T] 的 [Flow]. - */ - public actual fun asFlow(): Flow - - /** - * 获取所有 [T] 列表, 将全部 [T] 都加载后再返回. - * - * @return 此时刻的 [T] 只读列表. - */ - public actual suspend fun toList(): List = asFlow().toList() -} \ No newline at end of file diff --git a/mirai-core-utils/build.gradle.kts b/mirai-core-utils/build.gradle.kts index b53a79a9c..25d82759a 100644 --- a/mirai-core-utils/build.gradle.kts +++ b/mirai-core-utils/build.gradle.kts @@ -28,7 +28,6 @@ kotlin { apply(plugin = "explicit-api") configureJvmTargetsHierarchical("net.mamoe.mirai.utils") - configureNativeTargetsHierarchical(project) sourceSets { val commonMain by getting { @@ -42,15 +41,6 @@ kotlin { relocateImplementation(`ktor-io_relocated`) } } - configure(NATIVE_TARGETS.map { getByName(it + "Main") } - + NATIVE_TARGETS.map { getByName(it + "Test") }) { - dependencies { - // no relocation in native - implementation(`ktor-io`) { - exclude(ExcludeProperties.`slf4j-api`) - } - } - } val commonTest by getting { dependencies { @@ -81,12 +71,6 @@ kotlin { runtimeOnly(files("build/classes/kotlin/jvm/test")) // classpath is not properly set by IDE } } - - findByName("nativeMain")?.apply { - dependencies { -// implementation("com.soywiz.korlibs.krypto:krypto:2.4.12") // ':mirai-core-utils:compileNativeMainKotlinMetadata' fails because compiler cannot find reference - } - } } } diff --git a/mirai-core-utils/src/mingwX64Main/kotlin/MiraiFileImpl.kt b/mirai-core-utils/src/mingwX64Main/kotlin/MiraiFileImpl.kt deleted file mode 100644 index da57e46e3..000000000 --- a/mirai-core-utils/src/mingwX64Main/kotlin/MiraiFileImpl.kt +++ /dev/null @@ -1,343 +0,0 @@ -/* - * 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 io.ktor.utils.io.bits.* -import io.ktor.utils.io.core.* -import io.ktor.utils.io.errors.* -import kotlinx.cinterop.* -import platform.posix.* -import platform.windows.* - -private fun getFullPathName(path: String): String = memScoped { - ShortArray(MAX_PATH).usePinned { pin -> - val len = GetFullPathNameW(path, MAX_PATH, pin.addressOf(0).reinterpret(), null).toInt() - if (len != 0) { - return pin.get().toKStringFromUtf16(len) - } else { - when (val errno = errno) { - ENOTDIR -> return@memScoped path - EACCES -> return@memScoped path // permission denied - ENOENT -> return@memScoped path // no such file - else -> throw IllegalArgumentException( - "Invalid path($errno): $path", - cause = PosixException.forErrno(posixFunctionName = "GetFullPathNameW()") - ) - } - } - } -} - -private fun ShortArray.toKStringFromUtf16(len: Int): String { - val chars = CharArray(len) - var index = 0 - while (index < len) { - chars[index] = this[index].toInt().toChar() - ++index - } - return chars.concatToString() -} - -internal actual class MiraiFileImpl actual constructor( - // canonical - path: String -) : MiraiFile { - override val path = path.replace("/", "\\") - - actual companion object { - private val ROOT_REGEX = Regex("""^([a-zA-z]+:[/\\])""") - private const val SEPARATOR = '\\' - - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(UnsafeNumber::class) - actual fun getWorkingDir(): MiraiFile { - val path = memScoped { - ByteArray(PATH_MAX).usePinned { - getcwd(it.addressOf(0), it.get().size.convert()) - it.get().toKString() - } - } - return MiraiFile.create(path) - } - } - - override val absolutePath: String by lazy { - val result = ROOT_REGEX.matchEntire(this.path) - ?: return@lazy getFullPathName(this.path).removeSuffix(SEPARATOR.toString()) - return@lazy result.groups.first()!!.value - } - - private fun Char.isSeparator() = this == '/' || this == '\\' - - override val parent: MiraiFile? by lazy { - if (ROOT_REGEX.matchEntire(this.path) != null) return@lazy null - val absolute = absolutePath - val p = absolute.substringBeforeLast(SEPARATOR, "") - if (p.isEmpty()) { - return@lazy null - } - if (p.lastOrNull() == ':') { - if (absolute.lastIndexOf(SEPARATOR) == p.lastIndex) { - // file is C:/ - return@lazy null - } else { - return@lazy MiraiFileImpl("$p/") // file is C:/xxx - } - } - MiraiFileImpl(p) - } - - override val name: String - get() = if (absolutePath.matches(ROOT_REGEX)) absolutePath - else absolutePath.substringAfterLast(SEPARATOR) - - init { - checkName(absolutePath.substringAfterLast(SEPARATOR)) // do not check drive letter - } - - private fun checkName(name: String) { - name.substringAfterLast(SEPARATOR).forEach { c -> - if (c in """\/:?*"><|""") { - throw IllegalArgumentException("'${name}' contains illegal character '$c'.") - } - } - -// memScoped { -// val b = alloc() -// CheckNameLegalDOS8Dot3A(absolutePath, nullPtr(), 0, nullPtr(), b.ptr) -// if (b.value != 1) { -// throw IllegalArgumentException("'${name}' contains illegal character.") -// } -// } - } - - override val length: Long - get() = useStat { it.st_size.convert() } ?: 0 -// memScoped { -// val handle = CreateFileW( -// absolutePath, -// GENERIC_READ, -// FILE_SHARE_READ, -// null, -// OPEN_EXISTING, -// FILE_ATTRIBUTE_NORMAL, -// null -// ) ?: return@memScoped 0 -// val length = alloc() -// if (GetFileSize(handle, length.ptr) == INVALID_FILE_SIZE) { -// if (GetLastError() == NO_ERROR.toUInt()) { -// return INVALID_FILE_SIZE.convert() -// } -// throw PosixException.forErrno(posixFunctionName = "GetFileSize()").wrapIO() -// } -// if (CloseHandle(handle) == FALSE) { -// throw PosixException.forErrno(posixFunctionName = "CloseHandle()").wrapIO() -// } -// length.value.convert() -// } - - - override val isFile: Boolean - get() = useStat { it.st_mode.convert() flag S_IFREG } ?: false - - override val isDirectory: Boolean - get() = useStat { it.st_mode.convert() flag S_IFDIR } ?: false - - override fun exists(): Boolean = getFileAttributes() != INVALID_FILE_ATTRIBUTES - - private fun getFileAttributes(): DWORD = memScoped { GetFileAttributesW(absolutePath) } - - override fun resolve(path: String): MiraiFile { - when (path) { - "." -> return this - ".." -> return parent ?: this // root - } - - if (ROOT_REGEX.find(path) != null) { // absolute - return MiraiFileImpl(path) - } - - return MiraiFileImpl(this.absolutePath + SEPARATOR + path) // assuming path is 'appendable' - } - - override fun resolve(file: MiraiFile): MiraiFile { - val parent = file.parent ?: return resolve(file.name) - return resolve(parent).resolve(file.name) - } - - override fun createNewFile(): Boolean { - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea - val handle = CreateFileW( - absolutePath, - GENERIC_READ, - FILE_SHARE_DELETE, - null, - CREATE_NEW, - FILE_ATTRIBUTE_NORMAL, - null - ) - if (handle == null || handle == INVALID_HANDLE_VALUE) { - return false - } - if (CloseHandle(handle) == FALSE) { - throw PosixException.forErrno(posixFunctionName = "CloseHandle()").wrapIO() - } - return true - } - - override fun delete(): Boolean { - return if (isFile) { - DeleteFileW(absolutePath) != 0 - } else { - RemoveDirectoryW(absolutePath) != 0 - } - } - - override fun mkdir(): Boolean { - memScoped { - val v = alloc<_SECURITY_ATTRIBUTES>() - return CreateDirectoryW(absolutePath, v.ptr) != 0 - } - } - - override fun mkdirs(): Boolean { - this.parent?.mkdirs() - return mkdir() - } - - override fun input(): Input { -// println(absolutePath) -// val handle2 = fopen(absolutePath, "rb") ?:throw IOException( -// "Failed to open file '$absolutePath'", -// PosixException.forErrno(posixFunctionName = "fopen()") -// ) -// return PosixInputForFile(handle2) - // Will get I/O operation failed due to posix error code 2 - - val handle = CreateFileW( - absolutePath, - GENERIC_READ, - FILE_SHARE_DELETE, - null, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - null - ) - if (handle == null || handle == INVALID_HANDLE_VALUE) throw IOException( - "Failed to open file '$absolutePath'", - PosixException.forErrno(posixFunctionName = "CreateFileW()") - ) - return WindowsFileInput(handle) - } - - override fun output(): Output { -// val handle2 = fopen(absolutePath, "wb") -// ?: throw IOException( -// "Failed to open file '$absolutePath'", -// PosixException.forErrno(posixFunctionName = "fopen()") -// ) -// return PosixFileInstanceOutput(handle) -// - val handle = CreateFileW( - absolutePath, - GENERIC_WRITE, - FILE_SHARE_DELETE, - null, - (if (exists()) TRUNCATE_EXISTING else CREATE_NEW).toUInt(), - FILE_ATTRIBUTE_NORMAL, - null - ) - if (handle == null || handle == INVALID_HANDLE_VALUE) throw IOException( - "Failed to open file '$absolutePath'", - PosixException.forErrno(posixFunctionName = "CreateFileW()") - ) - return WindowsFileOutput(handle) - } - - override fun hashCode(): Int { - return this.path.hashCode() - } - - override fun equals(other: Any?): Boolean { - if (other == null) return false - if (!isSameType(this, other)) return false - return this.path == other.path - } - - override fun toString(): String { - return "MiraiFileImpl($path)" - } -} - - -internal class WindowsFileInput(private val file: HANDLE) : Input() { - private var closed = false - - override fun fill(destination: Memory, offset: Int, length: Int): Int { - if (file == INVALID_HANDLE_VALUE) return 0 - - memScoped { - val n = alloc() - if (ReadFile(file, destination.pointer + offset, length.convert(), n.ptr, null) == FALSE) { - throw PosixException.forErrno(posixFunctionName = "ReadFile()").wrapIO() - } - - return n.value.convert().toInt() - } - } - - override fun closeSource() { - if (closed) return - closed = true - - if (file != INVALID_HANDLE_VALUE) { - if (CloseHandle(file) == FALSE) { - throw PosixException.forErrno(posixFunctionName = "CloseHandle()").wrapIO() - } - } - } -} - -@Suppress("DEPRECATION") -internal class WindowsFileOutput(private val file: HANDLE) : Output() { - private var closed = false - - override fun flush(source: Memory, offset: Int, length: Int) { - val end = offset + length - var currentOffset = offset - - memScoped { - val written = alloc() - while (currentOffset < end) { - val result = WriteFile( - file, - source.pointer + currentOffset.convert(), - (end - currentOffset).convert(), - written.ptr, - null - ).convert() - if (result == FALSE) { - throw PosixException.forErrno(posixFunctionName = "WriteFile()").wrapIO() - } - currentOffset += written.value.toInt() - } - - } - } - - override fun closeDestination() { - if (closed) return - closed = true - - if (CloseHandle(file) == FALSE) { - throw PosixException.forErrno(posixFunctionName = "CloseHandle()").wrapIO() - } - } -} diff --git a/mirai-core-utils/src/mingwX64Main/kotlin/StandardUtils.kt b/mirai-core-utils/src/mingwX64Main/kotlin/StandardUtils.kt deleted file mode 100644 index d7c86e5fc..000000000 --- a/mirai-core-utils/src/mingwX64Main/kotlin/StandardUtils.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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 platform.windows.GetCurrentProcessorNumber - - -public actual fun availableProcessors(): Int = - GetCurrentProcessorNumber().toInt().coerceAtLeast(4) // somehow it worked on my machine but not on CI \ No newline at end of file diff --git a/mirai-core-utils/src/mingwX64Test/kotlin/MiraiFileImplTest.kt b/mirai-core-utils/src/mingwX64Test/kotlin/MiraiFileImplTest.kt deleted file mode 100644 index 60db9642a..000000000 --- a/mirai-core-utils/src/mingwX64Test/kotlin/MiraiFileImplTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.math.absoluteValue -import kotlin.random.Random -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class WindowsMiraiFileImplTest : AbstractNativeMiraiFileImplTest() { - private val rand = Random.nextInt().absoluteValue - override val baseTempDir: MiraiFile = MiraiFile.create("C:\\mirai_unit_tests") - override val tempPath = "C:\\mirai_unit_tests\\temp$rand" - - @Test - override fun parent() { - assertEquals("C:\\mirai_unit_tests", tempDir.parent!!.absolutePath) - super.parent() - } - - @Test - override fun `canonical paths for non-canonical input`() { - super.`canonical paths for non-canonical input`() - - // extra /sss/.. - MiraiFile.create("$tempPath/sss/..").resolve("test").let { - assertPathEquals("${tempPath}/test", it.path) // Windows resolves always - assertPathEquals("${tempPath}/test", it.absolutePath) - } - } - - @Test - override fun `resolve absolute`() { - MiraiFile.create("$tempPath/").resolve("C:\\mirai_unit_tests").let { - assertEquals("C:\\mirai_unit_tests", it.path) - assertEquals("C:\\mirai_unit_tests", it.absolutePath) - } - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/Base64.kt b/mirai-core-utils/src/nativeMain/kotlin/Base64.kt deleted file mode 100644 index 2d9ba0af8..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/Base64.kt +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import io.ktor.utils.io.core.* - -public actual fun String.decodeBase64(): ByteArray { - return Base64Impl.decode(this) -} - -public actual fun ByteArray.encodeBase64(): String { - return Base64Impl.encode(this) -} - -/** - * From . - * @author EmilHernvall - */ -private object Base64Impl { - fun encode(data: ByteArray): String { - val tbl = charArrayOf( - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', - 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' - ) - val buffer = StringBuilder() - var pad = 0 - var i = 0 - while (i < data.size) { - var b = data[i].toInt() and 0xFF shl 16 and 0xFFFFFF - if (i + 1 < data.size) { - b = b or (data[i + 1].toInt() and 0xFF shl 8) - } else { - pad++ - } - if (i + 2 < data.size) { - b = b or (data[i + 2].toInt() and 0xFF) - } else { - pad++ - } - for (j in 0 until 4 - pad) { - val c = b and 0xFC0000 shr 18 - buffer.append(tbl[c]) - b = b shl 6 - } - i += 3 - } - for (j in 0 until pad) { - buffer.append("=") - } - return buffer.toString() - } - - fun decode(data: String): ByteArray { - val tbl = intArrayOf( - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - ) - val bytes: ByteArray = data.toByteArray() - return buildPacket { - var i = 0 - while (i < bytes.size) { - var b: Int - b = if (tbl[bytes[i].toInt()] != -1) { - tbl[bytes[i].toInt()] and 0xFF shl 18 - } else { - i++ - continue - } - var num = 0 - if (i + 1 < bytes.size && tbl[bytes[i + 1].toInt()] != -1) { - b = b or (tbl[bytes[i + 1].toInt()] and 0xFF shl 12) - num++ - } - if (i + 2 < bytes.size && tbl[bytes[i + 2].toInt()] != -1) { - b = b or (tbl[bytes[i + 2].toInt()] and 0xFF shl 6) - num++ - } - if (i + 3 < bytes.size && tbl[bytes[i + 3].toInt()] != -1) { - b = b or (tbl[bytes[i + 3].toInt()] and 0xFF) - num++ - } - while (num > 0) { - val c = b and 0xFF0000 shr 16 - writeByte(c.toByte()) - b = b shl 8 - num-- - } - i += 4 - } - }.readBytes() - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt b/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt deleted file mode 100644 index e923d95b8..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/ByteArrayOp.kt +++ /dev/null @@ -1,341 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import io.ktor.utils.io.bits.* -import io.ktor.utils.io.core.* -import kotlinx.cinterop.* -import platform.zlib.* - - -public actual val DEFAULT_BUFFER_SIZE: Int get() = 8192 - -public actual fun ByteArray.md5(offset: Int, length: Int): ByteArray { - MD5.create().run { - update(this@md5, offset, length) - return digest().bytes - } -} - -public actual fun ByteArray.sha1(offset: Int, length: Int): ByteArray = SHA1.create().run { - update(this@sha1, offset, length) - return digest().bytes -} - -public actual fun ByteArray.sha256(offset: Int, length: Int): ByteArray = SHA256.create().run { - update(this@sha256, offset, length) - return digest().bytes -} - -/** - * WARNING: DO NOT SET THIS BUFFER TOO SMALL, OR YOU WILL SEE COMPRESSION ERROR. - */ -@set:TestOnly -public var ZLIB_BUFFER_SIZE: Long = 8192 - -public actual fun ByteArray.gzip(offset: Int, length: Int): ByteArray { - return GzipCompressionInput(this.toReadPacket(offset, length)).use { it.readBytes() } -} - -public actual fun ByteArray.ungzip(offset: Int, length: Int): ByteArray { - return GzipDecompressionInput(this.toReadPacket(offset, length)).use { it.readBytes() } -} - -public actual fun ByteArray.deflate(offset: Int, length: Int): ByteArray { - return DeflateInput(this.toReadPacket(offset, length)).use { it.readBytes() } -} - -public actual fun ByteArray.inflate(offset: Int, length: Int): ByteArray { - return InflateInput(this.toReadPacket(offset, length)).use { it.readBytes() } -} - - -@Suppress("FunctionName") -public fun GzipCompressionInput(source: Input): Input { - return ZlibInput( - source = source, - zlibInit = { deflateInit2(it, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 or 16, 8, Z_DEFAULT_STRATEGY) }, - zlibProcess = { z, flush -> deflate(z, flush) }, - zlibHasPending = null, - zlibFlushMode = { if (it) Z_FINISH else Z_NO_FLUSH }, - zlibEnd = { deflateEnd(it) }, - ) -} - -@Suppress("FunctionName") -public actual fun GzipDecompressionInput(source: Input): Input { - return ZlibInput( - source = source, - zlibInit = { inflateInit2(it, 15 or 16) }, - zlibProcess = { z, flush -> inflate(z, flush) }, - zlibHasPending = null, - zlibFlushMode = { if (it) Z_SYNC_FLUSH else Z_NO_FLUSH }, - zlibEnd = { inflateEnd(it) }, - ) -} - -@Suppress("FunctionName") -public actual fun InflateInput(source: Input): Input { - return ZlibInput( - source = source, - zlibInit = { inflateInit2(it, 15) }, - zlibProcess = { z, flush -> inflate(z, flush) }, - zlibHasPending = null, - zlibFlushMode = { if (it) Z_SYNC_FLUSH else Z_NO_FLUSH }, - zlibEnd = { inflateEnd(it) }, - ) -} - -@Suppress("FunctionName") -public actual fun DeflateInput(source: Input): Input { - return ZlibInput( - source = source, - zlibInit = { deflateInit(it, Z_DEFAULT_COMPRESSION) }, - zlibProcess = { z, flush -> deflate(z, flush) }, - zlibHasPending = { z -> - memScoped { - val pendingBytes = cValue().ptr - val pendingBits = cValue().ptr - - if (deflatePending(z, pendingBytes, pendingBits) != Z_OK) { - false - } else { - pendingBytes.pointed.value > 0u || pendingBits.pointed.value > 0 - } - } - }, - zlibFlushMode = { if (it) Z_FINISH else Z_NO_FLUSH }, - zlibEnd = { deflateEnd(it) }, - ) -} - - -/** - * Input will be closed. - */ -public actual fun Input.gzipAllAvailable(): ByteArray { - return GzipCompressionInput(this).use { it.readBytes() } -} - -/** - * Input will be closed. - */ -public actual fun Input.ungzipAllAvailable(): ByteArray { - return GzipDecompressionInput(this).use { it.readBytes() } -} - -/** - * Input will be closed. - */ -public actual fun Input.inflateAllAvailable(): ByteArray { - return InflateInput(this).use { it.readBytes() } -} - -/** - * Input will be closed. - */ -public actual fun Input.deflateAllAvailable(): ByteArray { - return DeflateInput(this).use { it.readBytes() } -} - - -/** - * [source] will be closed on [ZlibInput.close] - */ -internal class ZlibInput( - private val source: Input, - zlibInit: (z_streamp) -> Int, - private val zlibProcess: (z_streamp, flush: Int) -> Int, - private val zlibHasPending: ((z_streamp) -> Boolean)?, // null lambda means operation not defined - private val zlibFlushMode: (shouldFlushAll: Boolean) -> Int, - private val zlibEnd: (z_streamp) -> Int, -) : Input() { - private val z: z_stream = nativeHeap.alloc() - // Zlib manual: https://refspecs.linuxbase.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/zlib-inflate-1.html - - init { - val r = zlibInit(z.ptr) - if (r != 0) { - nativeHeap.free(z) - error("Failed to init zlib: $r (${getZlibError(r)})") - } - } - - private var bufferReadableSize = 0L - private val inputBuffer = nativeHeap.allocArray(ZLIB_BUFFER_SIZE) - - private var closed = false - - override fun close() { - if (closed) return - closed = true - debug { "close" } - super.close() - debug { "freeing inputBuffer" } - nativeHeap.free(inputBuffer) - debug { "freed" } - } - - override fun closeSource() { - debug { "closeSource" } - source.close() - debug { "zlibEnd" } - zlibEnd(z.ptr) - debug { "zlibEnd done" } - } - - override fun fill(destination: Memory, offset: Int, length: Int): Int { - require(offset in 0..destination.size32) { "invalid offset: $offset" } - require(length in 0..destination.size32) { "invalid length: $length" } - require(offset + length in 0..destination.size32) { "invalid offset and length: $offset, $length" } - - debug { "prepare: bufferReadableSize = $bufferReadableSize" } - debug { "prepare: previous value: z.avail_in=${z.avail_in}, z.avail_out=${z.avail_out}" } - - val filled = try { - if (z.avail_in == 0u) { - - // These two cases are similar. -// if (z.avail_out == 0u) { -// // Last time we used all the output, there is either something cached in Zlib, or no further source. -// } else { -// // We did not use all the inputs, meaning least time we used all avail_in. -// } - - // bot input and output are used - val flush = updateAvailIn() ?: return 0 - copyOutputsFromZlib(destination, offset, length, flush) - } else { - // Inputs not used up. - copyOutputsFromZlib(destination, offset, length, Z_NO_FLUSH) - } - - } catch (e: Throwable) { - // If you throw this error up, ktor will somehow kill the process. (Ktor 2.0.2) - debug { e.printStackTrace(); "" } - return 0 - } - check(filled in 0..length) { "Filled more than $length bytes: $filled" } - check(filled in 0..destination.size) { "Filled more than ${destination.size} bytes: $filled" } - return filled - } - - private fun copyOutputsFromZlib(memory: Memory, offset: Int, length: Int, flush: Int): Int { - debug { "copyOutputsFromZlib, memory.offset = $offset, memory.length=$length, memory.size=${memory.size}" } - - z.avail_out = length.convert() - z.next_out = (memory.pointer + offset)!!.reinterpret() - - // We still have input, no need to update. - debug { "Set z.avail_out=${z.avail_out}, z.next_out=(memory.pointer + offset)!!.reinterpret()" } - debug { "Calling zlib, flush = $flush" } - - val p = zlibProcess(z.ptr, flush) - when (p) { - Z_BUF_ERROR -> error("Zlib failed to process data. (Z_BUF_ERROR)") - Z_MEM_ERROR -> throw OutOfMemoryError("Insufficient native heap memory for Zlib. (Z_MEM_ERROR)") - Z_STREAM_ERROR -> error("Zlib failed to process data. (Z_STREAM_ERROR)") - Z_DATA_ERROR -> error("Zlib failed to process data. (Z_DATA_ERROR)") - Z_NEED_DICT -> error("Zlib failed to process data. (Z_NEED_DICT)") - else -> debug { "zlib: $p" } - } - val readSize = (length.toUInt() - z.avail_out).toInt() - - debug { "Zlib produced readSize=$readSize bytes" } -// debug { "Partial output: ${memory.readBytes(bufferReadableSize).toUHexString()}" } - debug { "Now z.avail_in=${z.avail_in}, z.avail_out=${z.avail_out}" } - - if (p == Z_FINISH) { - debug { "Zlib returned Z_FINISH. Ignoring result check." } - return readSize - } - - if (p == Z_STREAM_END) { - debug { "Zlib returned Z_STREAM_END. Ignoring result check." } - return readSize - } - - if (bufferReadableSize == 0L && (z.avail_in == 0u && source.endOfInput)) { - if (zlibHasPending?.invoke(z.ptr) == true) { - // has pending. So the data must be incomplete. - error("Failed to process data, possibly bad data inputted.") -// if (z.avail_in == 0u && source.endOfInput) { -// // no any input. -// } else { -// // there's some input, so we can still read. -// } - } else { - // no pending, but we should expect Z_FINISH in this case. - error("Zlib read 0 byte, but it should not happen.") - } - // can't read - } - return readSize - } - - private fun updateAvailIn(): Int? { - val read = source.readAvailable(inputBuffer, 0, ZLIB_BUFFER_SIZE) - if (read == 0L) { - debug { "updateAvailIn: endOfInput, closing" } - close() // automatically close - return null // no more source available - } - bufferReadableSize = read - z.avail_in = read.toUInt() - val flush = zlibFlushMode(read < ZLIB_BUFFER_SIZE || source.endOfInput) - debug { "inputBuffer content: " + inputBuffer.readBytes(read.toInt()).toUHexString() } - z.next_in = inputBuffer.reinterpret() - debug { "Updated availIn: z.avail_in=${z.avail_in}, z.next_in = inputBuffer.reinterpret()" } - return flush - } - - private companion object { - private fun getZlibError(it: Int): String { - return when (it) { - Z_DATA_ERROR -> "Z_DATA_ERROR" - Z_STREAM_ERROR -> "Z_STREAM_ERROR" - else -> "Unknown error $it" - } - } - - - private const val debugging = false - private inline fun debug(string: () -> String) { - if (debugging) println(string()) - } - - private inline fun debug() { - if (debugging) println() - } - } -} - - -//private fun ByteArray.callImpl( -// fn: (CValuesRef, UInt, CValuesRef) -> Boolean, -// offset: Int, -// length: Int -//): ByteArray { -// checkOffsetAndLength(offset, length) -// -// memScoped { -// val r = alloc() -// if (!fn(toCValues().ptr.reinterpret().plus(offset)!!, length.toUInt(), r.ptr)) { -// throw IllegalStateException("Failed platform implementation call") -// } -// try { -// return r.arr?.readBytes(r.size.toInt())!! -// } finally { -// free(r.arr) -// } -// } -//} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/Clock.kt b/mirai-core-utils/src/nativeMain/kotlin/Clock.kt deleted file mode 100644 index 5a15e11a4..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/Clock.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -public actual inline fun measureTimeMillis(block: () -> Unit): Long { - val start = currentTimeMillis() // getTimeMillis in stdlib doesn't work on some native targets. - block() - return currentTimeMillis() - start -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/Closeable.kt b/mirai-core-utils/src/nativeMain/kotlin/Closeable.kt deleted file mode 100644 index 2de8280bc..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/Closeable.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 io.ktor.utils.io.core.use as ktorUse - -public actual typealias Closeable = io.ktor.utils.io.core.Closeable - -@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -@kotlin.internal.LowPriorityInOverloadResolution -public actual inline fun C.use(block: (C) -> R): R = ktorUse(block) - -public actual fun Closeable.asKtorCloseable(): io.ktor.utils.io.core.Closeable = this -public actual fun io.ktor.utils.io.core.Closeable.asMiraiCloseable(): Closeable = this \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/Collections.kt b/mirai-core-utils/src/nativeMain/kotlin/Collections.kt deleted file mode 100644 index 1c2b70e2d..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/Collections.kt +++ /dev/null @@ -1,260 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import kotlinx.atomicfu.locks.ReentrantLock -import kotlinx.atomicfu.locks.reentrantLock -import kotlinx.atomicfu.locks.withLock -import kotlin.reflect.KClass - -@Suppress("FunctionName") -public actual fun ConcurrentHashMap(): MutableMap { - return LockedConcurrentHashMap(reentrantLock()) -} - -private class LockedConcurrentHashSet( - private val lock: ReentrantLock, - private val delegate: MutableSet = mutableSetOf() -) : MutableSet { - override fun add(element: E): Boolean = lock.withLock { - return delegate.add(element) - } - - override fun addAll(elements: Collection): Boolean = lock.withLock { - return delegate.addAll(elements) - } - - override val size: Int get() = lock.withLock { delegate.size } - - override fun clear() = lock.withLock { delegate.clear() } - - override fun isEmpty(): Boolean = lock.withLock { delegate.isEmpty() } - override fun containsAll(elements: Collection): Boolean = lock.withLock { delegate.containsAll(elements) } - override fun contains(element: E): Boolean = lock.withLock { delegate.contains(element) } - - override fun iterator(): MutableIterator = delegate.iterator() // no effect for locking - - @Suppress("ConvertArgumentToSet") - override fun retainAll(elements: Collection): Boolean = lock.withLock { delegate.retainAll(elements) } - - @Suppress("ConvertArgumentToSet") - override fun removeAll(elements: Collection): Boolean = lock.withLock { delegate.removeAll(elements) } - - override fun remove(element: E): Boolean = lock.withLock { delegate.remove(element) } - - - override fun equals(other: Any?): Boolean = delegate == other - override fun hashCode(): Int = delegate.hashCode() - override fun toString(): String = delegate.toString() -} - -private class LockedConcurrentCollection( - private val lock: ReentrantLock, - private val delegate: MutableCollection -) : MutableCollection { - override fun add(element: E): Boolean = lock.withLock { - return delegate.add(element) - } - - override fun addAll(elements: Collection): Boolean = lock.withLock { - return delegate.addAll(elements) - } - - override val size: Int get() = lock.withLock { delegate.size } - - override fun clear() = lock.withLock { delegate.clear() } - - override fun isEmpty(): Boolean = lock.withLock { delegate.isEmpty() } - override fun containsAll(elements: Collection): Boolean = lock.withLock { delegate.containsAll(elements) } - override fun contains(element: E): Boolean = lock.withLock { delegate.contains(element) } - - override fun iterator(): MutableIterator = delegate.iterator() // no effect for locking - - @Suppress("ConvertArgumentToSet") - override fun retainAll(elements: Collection): Boolean = lock.withLock { delegate.retainAll(elements) } - - @Suppress("ConvertArgumentToSet") - override fun removeAll(elements: Collection): Boolean = lock.withLock { delegate.removeAll(elements) } - - override fun remove(element: E): Boolean = lock.withLock { delegate.remove(element) } - - override fun equals(other: Any?): Boolean = delegate == other - override fun hashCode(): Int = delegate.hashCode() - override fun toString(): String = delegate.toString() -} - -private class LockedConcurrentHashMap( - private val lock: ReentrantLock, - private val delegate: MutableMap = mutableMapOf() -) : MutableMap { - override val entries: MutableSet> - get() = lock.withLock { LockedConcurrentHashSet(lock, delegate.entries) } - - override val keys: MutableSet get() = lock.withLock { LockedConcurrentHashSet(lock, delegate.keys) } - override val size: Int get() = lock.withLock { delegate.size } - override val values: MutableCollection - get() = lock.withLock { LockedConcurrentCollection(lock, delegate.values) } - - override fun clear() = lock.withLock { delegate.clear() } - override fun isEmpty(): Boolean = lock.withLock { delegate.isEmpty() } - override fun remove(key: K): V? = lock.withLock { delegate.remove(key) } - override fun putAll(from: Map) = lock.withLock { delegate.putAll(from) } - override fun put(key: K, value: V): V? = lock.withLock { delegate.put(key, value) } - override fun get(key: K): V? = lock.withLock { delegate.get(key) } - override fun containsValue(value: V): Boolean = lock.withLock { delegate.containsValue(value) } - override fun containsKey(key: K): Boolean = lock.withLock { delegate.containsKey(key) } - - override fun equals(other: Any?): Boolean = delegate == other - override fun hashCode(): Int = delegate.hashCode() - override fun toString(): String = delegate.toString() -} - -@Suppress("FunctionName") -public actual fun ConcurrentLinkedDeque(): MutableDeque { - return LockedConcurrentArrayDeque(reentrantLock()) -} - -private class LockedConcurrentArrayDeque( - private val lock: ReentrantLock, - private val delegate: ArrayDeque = ArrayDeque() -) : MutableDeque { - override fun addFirst(element: E) = lock.withLock { delegate.addFirst(element) } - - override fun add(element: E): Boolean { - lock.withLock { delegate.add(element) } - return true - } - - override fun poll(): E? = lock.withLock { delegate.removeFirstOrNull() } - - override fun offer(element: E): Boolean { - lock.withLock { delegate.addLast(element) } - return true - } - - override val size: Int - get() = lock.withLock { delegate.size } - - override fun clear() = lock.withLock { delegate.clear() } - override fun addAll(elements: Collection): Boolean = lock.withLock { delegate.addAll(elements) } - override fun isEmpty(): Boolean = lock.withLock { delegate.isEmpty() } - override fun iterator(): MutableIterator = delegate.iterator() - override fun retainAll(elements: Collection): Boolean = lock.withLock { delegate.retainAll(elements) } - override fun removeAll(elements: Collection): Boolean = lock.withLock { delegate.removeAll(elements) } - override fun remove(element: E): Boolean = lock.withLock { delegate.remove(element) } - override fun containsAll(elements: Collection): Boolean = lock.withLock { delegate.containsAll(elements) } - override fun contains(element: E): Boolean = lock.withLock { delegate.contains(element) } - - override fun equals(other: Any?): Boolean = delegate == other - override fun hashCode(): Int = delegate.hashCode() - override fun toString(): String = delegate.toString() -} - -internal class ArrayDequeAsMutableDeque( - private val delegate: ArrayDeque = ArrayDeque() -) : MutableDeque { - override fun addFirst(element: E) = delegate.addFirst(element) - - override fun add(element: E): Boolean { - delegate.add(element) - return true - } - - override fun poll(): E? = delegate.removeFirstOrNull() - - override fun offer(element: E): Boolean { - delegate.addLast(element) - return true - } - - override val size: Int - get() = delegate.size - - override fun clear() = delegate.clear() - override fun addAll(elements: Collection): Boolean = delegate.addAll(elements) - override fun isEmpty(): Boolean = delegate.isEmpty() - override fun iterator(): MutableIterator = delegate.iterator() - override fun retainAll(elements: Collection): Boolean = delegate.retainAll(elements) - override fun removeAll(elements: Collection): Boolean = delegate.removeAll(elements) - override fun remove(element: E): Boolean = delegate.remove(element) - override fun containsAll(elements: Collection): Boolean = delegate.containsAll(elements) - override fun contains(element: E): Boolean = delegate.contains(element) - - override fun equals(other: Any?): Boolean = delegate == other - override fun hashCode(): Int = delegate.hashCode() - override fun toString(): String = delegate.toString() -} - -@Suppress("FunctionName") -public actual fun , V> EnumMap(clazz: KClass): MutableMap = mutableMapOf() - -@Suppress("FunctionName") -public actual fun ConcurrentSet(): MutableSet { - return LockedConcurrentHashSet(reentrantLock()) -} - -public actual class LinkedList( - private val delegate: ArrayDeque -) : MutableList by delegate { - public actual constructor() : this(ArrayDeque()) - - public actual fun addLast(element: E) { - return delegate.addLast(element) - } -} - -public actual interface MutableDeque : MutableQueue { - public actual fun addFirst(element: E) -} - -public actual interface MutableQueue : MutableCollection { - /** - * Adds the specified element to the collection. - * - * @return `true` if the element has been added, `false` if the collection does not support duplicates - * and the element is already contained in the collection. - * @throws IllegalStateException if the queue is full. - */ - public actual override fun add(element: E): Boolean - - /** - * Removes and returns the head of the queue, `null` otherwise. - */ - public actual fun poll(): E? - - /** - * Adds an element into the queue. - * @return `true` if the element has been added, `false` if queue is full. - */ - public actual fun offer(element: E): Boolean - - -} - -/** - * Returns a [List] that cannot be cast to [MutableList] to modify it. - */ -public actual fun List.asImmutable(): List = ImmutableList(this) -public actual fun Collection.asImmutable(): Collection = ImmutableCollection(this) -public actual fun Set.asImmutable(): Set = ImmutableSet(this) - -internal class ImmutableList( - private val delegate: List -) : List by delegate - -internal class ImmutableCollection( - private val delegate: Collection -) : Collection by delegate - -internal class ImmutableSet( - private val delegate: Set -) : Set by delegate diff --git a/mirai-core-utils/src/nativeMain/kotlin/CommonDigest.kt b/mirai-core-utils/src/nativeMain/kotlin/CommonDigest.kt deleted file mode 100644 index 63562ca1a..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/CommonDigest.kt +++ /dev/null @@ -1,350 +0,0 @@ -/* - * 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.math.abs -import kotlin.math.min -import kotlin.math.sin - -/* - * Note: All the declarations in this file are copied from 'com.soywiz.korlibs.krypto'. - * - * The license is attached: - -MIT License - -Copyright (c) 2017 Carlos Ballesteros Velasco - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------- - -/** - * Based on CryptoJS v3.1.2 - * code.google.com/p/crypto-js - * (c) 2009-2013 by Jeff Mott. All rights reserved. - * https://github.com/brix/crypto-js/blob/develop/LICENSE - */ - */ - -internal inline fun Int.ext8(offset: Int) = (this ushr offset) and 0xFF - -internal fun Int.rotateRight(amount: Int): Int = (this ushr amount) or (this shl (32 - amount)) -internal fun Int.rotateLeft(bits: Int): Int = ((this shl bits) or (this ushr (32 - bits))) - -internal fun arraycopy(src: ByteArray, srcPos: Int, dst: ByteArray, dstPos: Int, count: Int) = - src.copyInto(dst, dstPos, srcPos, srcPos + count) - -internal fun arraycopy(src: IntArray, srcPos: Int, dst: IntArray, dstPos: Int, count: Int) = - src.copyInto(dst, dstPos, srcPos, srcPos + count) - -internal fun ByteArray.readU8(o: Int): Int = this[o].toInt() and 0xFF -internal fun ByteArray.readS32_be(o: Int): Int = - (readU8(o + 3) shl 0) or (readU8(o + 2) shl 8) or (readU8(o + 1) shl 16) or (readU8(o + 0) shl 24) - -internal abstract class Hasher(val chunkSize: Int, val digestSize: Int) { - private val chunk = ByteArray(chunkSize) - private var writtenInChunk = 0 - private var totalWritten = 0L - - fun reset(): Hasher { - coreReset() - writtenInChunk = 0 - totalWritten = 0L - return this - } - - fun update(data: ByteArray, offset: Int, count: Int): Hasher { - var curr = offset - var left = count - while (left > 0) { - val remainingInChunk = chunkSize - writtenInChunk - val toRead = min(remainingInChunk, left) - arraycopy(data, curr, chunk, writtenInChunk, toRead) - left -= toRead - curr += toRead - writtenInChunk += toRead - if (writtenInChunk >= chunkSize) { - writtenInChunk -= chunkSize - coreUpdate(chunk) - } - } - totalWritten += count - return this - } - - fun digestOut(out: ByteArray) { - val pad = corePadding(totalWritten) - var padPos = 0 - while (padPos < pad.size) { - val padSize = chunkSize - writtenInChunk - arraycopy(pad, padPos, chunk, writtenInChunk, padSize) - coreUpdate(chunk) - writtenInChunk = 0 - padPos += padSize - } - - coreDigest(out) - coreReset() - } - - protected abstract fun coreReset() - protected abstract fun corePadding(totalWritten: Long): ByteArray - protected abstract fun coreUpdate(chunk: ByteArray) - protected abstract fun coreDigest(out: ByteArray) - - fun update(data: ByteArray) = update(data, 0, data.size) - fun digest(): Hash = Hash(ByteArray(digestSize).also { digestOut(it) }) -} - -internal value class Hash(val bytes: ByteArray) - -internal open class HasherFactory(val create: () -> Hasher) { - fun digest(data: ByteArray) = create().also { it.update(data, 0, data.size) }.digest() - - inline fun digest(temp: ByteArray = ByteArray(0x1000), readBytes: (data: ByteArray) -> Int): Hash = - this.create().also { - while (true) { - val count = readBytes(temp) - if (count <= 0) break - it.update(temp, 0, count) - } - }.digest() -} - -internal class MD5 : Hasher(chunkSize = 64, digestSize = 16) { - companion object : HasherFactory({ MD5() }) { - private val S = intArrayOf(7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21) - private val T = IntArray(64) { ((1L shl 32) * abs(sin(1.0 + it))).toLong().toInt() } - } - - private val r = IntArray(4) - private val o = IntArray(4) - private val b = IntArray(16) - - init { - coreReset() - } - - override fun coreReset() { - r[0] = 0x67452301 - r[1] = 0xEFCDAB89.toInt() - r[2] = 0x98BADCFE.toInt() - r[3] = 0x10325476 - } - - override fun coreUpdate(chunk: ByteArray) { - for (j in 0 until 64) b[j ushr 2] = (chunk[j].toInt() shl 24) or (b[j ushr 2] ushr 8) - for (j in 0 until 4) o[j] = r[j] - for (j in 0 until 64) { - val d16 = j / 16 - val f = when (d16) { - 0 -> (r[1] and r[2]) or (r[1].inv() and r[3]) - 1 -> (r[1] and r[3]) or (r[2] and r[3].inv()) - 2 -> r[1] xor r[2] xor r[3] - 3 -> r[2] xor (r[1] or r[3].inv()) - else -> 0 - } - val bi = when (d16) { - 0 -> j - 1 -> (j * 5 + 1) and 0x0F - 2 -> (j * 3 + 5) and 0x0F - 3 -> (j * 7) and 0x0F - else -> 0 - } - val temp = r[1] + (r[0] + f + b[bi] + T[j]).rotateLeft(S[(d16 shl 2) or (j and 3)]) - r[0] = r[3] - r[3] = r[2] - r[2] = r[1] - r[1] = temp - } - for (j in 0 until 4) r[j] += o[j] - } - - override fun corePadding(totalWritten: Long): ByteArray { - val numberOfBlocks = ((totalWritten + 8) / chunkSize) + 1 - val totalWrittenBits = totalWritten * 8 - return ByteArray(((numberOfBlocks * chunkSize) - totalWritten).toInt()).apply { - this[0] = 0x80.toByte() - for (i in 0 until 8) this[this.size - 8 + i] = (totalWrittenBits ushr (8 * i)).toByte() - } - } - - override fun coreDigest(out: ByteArray) { - for (it in 0 until 16) out[it] = (r[it / 4] ushr ((it % 4) * 8)).toByte() - } -} - -internal abstract class SHA(chunkSize: Int, digestSize: Int) : Hasher(chunkSize, digestSize) { - override fun corePadding(totalWritten: Long): ByteArray { - val tail = totalWritten % 64 - val padding = (if (64 - tail >= 9) 64 - tail else 128 - tail) - val pad = ByteArray(padding.toInt()).apply { this[0] = 0x80.toByte() } - val bits = (totalWritten * 8) - for (i in 0 until 8) pad[pad.size - 1 - i] = ((bits ushr (8 * i)) and 0xFF).toByte() - return pad - } -} - -internal class SHA1 : SHA(chunkSize = 64, digestSize = 20) { - companion object : HasherFactory({ SHA1() }) { - private val H = intArrayOf( - 0x67452301L.toInt(), - 0xEFCDAB89L.toInt(), - 0x98BADCFEL.toInt(), - 0x10325476L.toInt(), - 0xC3D2E1F0L.toInt() - ) - - private const val K0020: Int = 0x5A827999L.toInt() - private const val K2040: Int = 0x6ED9EBA1L.toInt() - private const val K4060: Int = 0x8F1BBCDCL.toInt() - private const val K6080: Int = 0xCA62C1D6L.toInt() - } - - private val w = IntArray(80) - private val h = IntArray(5) - - override fun coreReset(): Unit { - arraycopy(H, 0, h, 0, 5) - } - - init { - coreReset() - } - - override fun coreUpdate(chunk: ByteArray) { - for (j in 0 until 16) w[j] = chunk.readS32_be(j * 4) - for (j in 16 until 80) w[j] = (w[j - 3] xor w[j - 8] xor w[j - 14] xor w[j - 16]).rotateLeft(1) - - var a = h[0] - var b = h[1] - var c = h[2] - var d = h[3] - var e = h[4] - - for (j in 0 until 80) { - val temp = a.rotateLeft(5) + e + w[j] + when (j / 20) { - 0 -> ((b and c) or ((b.inv()) and d)) + K0020 - 1 -> (b xor c xor d) + K2040 - 2 -> ((b and c) xor (b and d) xor (c and d)) + K4060 - else -> (b xor c xor d) + K6080 - } - - e = d - d = c - c = b.rotateLeft(30) - b = a - a = temp - } - - h[0] += a - h[1] += b - h[2] += c - h[3] += d - h[4] += e - } - - override fun coreDigest(out: ByteArray) { - for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte() - } -} - -internal class SHA256 : SHA(chunkSize = 64, digestSize = 32) { - companion object : HasherFactory({ SHA256() }) { - private val H = intArrayOf( - 0x6a09e667, -0x4498517b, 0x3c6ef372, -0x5ab00ac6, - 0x510e527f, -0x64fa9774, 0x1f83d9ab, 0x5be0cd19 - ) - - private val K = intArrayOf( - 0x428a2f98, 0x71374491, -0x4a3f0431, -0x164a245b, - 0x3956c25b, 0x59f111f1, -0x6dc07d5c, -0x54e3a12b, - -0x27f85568, 0x12835b01, 0x243185be, 0x550c7dc3, - 0x72be5d74, -0x7f214e02, -0x6423f959, -0x3e640e8c, - -0x1b64963f, -0x1041b87a, 0x0fc19dc6, 0x240ca1cc, - 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - -0x67c1aeae, -0x57ce3993, -0x4ffcd838, -0x40a68039, - -0x391ff40d, -0x2a586eb9, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, - 0x650a7354, 0x766a0abb, -0x7e3d36d2, -0x6d8dd37b, - -0x5d40175f, -0x57e599b5, -0x3db47490, -0x3893ae5d, - -0x2e6d17e7, -0x2966f9dc, -0xbf1ca7b, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, - 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, -0x7b3787ec, -0x7338fdf8, - -0x6f410006, -0x5baf9315, -0x41065c09, -0x398e870e - ) - } - - - private val h = IntArray(8) - private val r = IntArray(8) - private val w = IntArray(64) - - init { - coreReset() - } - - override fun coreReset() { - arraycopy(H, 0, h, 0, 8) - } - - override fun coreUpdate(chunk: ByteArray) { - arraycopy(h, 0, r, 0, 8) - - for (j in 0 until 16) w[j] = chunk.readS32_be(j * 4) - for (j in 16 until 64) { - val s0 = w[j - 15].rotateRight(7) xor w[j - 15].rotateRight(18) xor w[j - 15].ushr(3) - val s1 = w[j - 2].rotateRight(17) xor w[j - 2].rotateRight(19) xor w[j - 2].ushr(10) - w[j] = w[j - 16] + s0 + w[j - 7] + s1 - } - - for (j in 0 until 64) { - val s1 = r[4].rotateRight(6) xor r[4].rotateRight(11) xor r[4].rotateRight(25) - val ch = r[4] and r[5] xor (r[4].inv() and r[6]) - val t1 = r[7] + s1 + ch + K[j] + w[j] - val s0 = r[0].rotateRight(2) xor r[0].rotateRight(13) xor r[0].rotateRight(22) - val maj = r[0] and r[1] xor (r[0] and r[2]) xor (r[1] and r[2]) - val t2 = s0 + maj - r[7] = r[6] - r[6] = r[5] - r[5] = r[4] - r[4] = r[3] + t1 - r[3] = r[2] - r[2] = r[1] - r[1] = r[0] - r[0] = t1 + t2 - - } - for (j in 0 until 8) h[j] += r[j] - } - - override fun coreDigest(out: ByteArray) { - for (n in out.indices) out[n] = (h[n / 4] ushr (24 - 8 * (n % 4))).toByte() - } -} - diff --git a/mirai-core-utils/src/nativeMain/kotlin/CoroutineUtils.kt b/mirai-core-utils/src/nativeMain/kotlin/CoroutineUtils.kt deleted file mode 100644 index 6beaf0c77..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/CoroutineUtils.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -public actual suspend inline fun runBIO(noinline block: () -> R): R { - return block() -} - -public actual suspend inline fun T.runBIO(crossinline block: T.() -> R): R { - return block() -} - -/** - * 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 Throwable.unwrap(addSuppressed: Boolean): Throwable { - if (this !is E) return this - return this.findCause { it !is E } - ?.also { if (addSuppressed) it.addSuppressed(this) } - ?: this -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/ExceptionCollector.kt b/mirai-core-utils/src/nativeMain/kotlin/ExceptionCollector.kt deleted file mode 100644 index 38386cdaa..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/ExceptionCollector.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 { - var hashCode = 1L - val trace = e.getStackTraceAddresses() - for (stackTraceAddress in trace) { - hashCode = (hashCode xor stackTraceAddress).shl(1) - } - - // Somehow stacktrace analysis is on my own Windows machine but not on GitHub Actions. - // Hashing with a class to tentatively not filter out different types. - return hashCode xor e::class.hashCode().toLongUnsigned() -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt b/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt deleted file mode 100644 index 798037742..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/MiraiFile.kt +++ /dev/null @@ -1,225 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import io.ktor.utils.io.bits.* -import io.ktor.utils.io.core.* -import io.ktor.utils.io.errors.* -import kotlinx.cinterop.* -import platform.posix.* - -/** - * Multiplatform implementation of file operations. - */ -public actual interface MiraiFile { - /** - * Name of this file or directory. Can be '.' and '..' if created by - */ - public actual val name: String - - /** - * Parent of this file or directory. - */ - public actual val parent: MiraiFile? - - /** - * Input path from [create]. - */ - public actual val path: String - - /** - * Normalized absolute [path]. - */ - public actual val absolutePath: String - public actual val length: Long - public actual val isFile: Boolean - public actual val isDirectory: Boolean - public actual fun exists(): Boolean - - /** - * Resolves a [MiraiFile] representing the [path] based on this [MiraiFile]. Result path is not guaranteed to be normalized. - */ - public actual fun resolve(path: String): MiraiFile - public actual fun resolve(file: MiraiFile): MiraiFile - public actual fun createNewFile(): Boolean - public actual fun delete(): Boolean - public actual fun mkdir(): Boolean - public actual fun mkdirs(): Boolean - public actual fun input(): Input - public actual fun output(): Output - - public actual companion object { - public actual fun create(path: String): MiraiFile = MiraiFileImpl(path) - public actual fun getWorkingDir(): MiraiFile = MiraiFileImpl.getWorkingDir() - } -} - - -private val deleteFile = - staticCFunction>?, CPointer?, Int, CPointer?, Int> { pathPtr, _, _, _ -> - val path = pathPtr!!.toKString() - if (remove(path) < 0) { - -1 - } else { - 0 - } - } - -public actual fun MiraiFile.deleteRecursively(): Boolean { - return nftw(absolutePath, deleteFile, 10, FTW_DEPTH or FTW_MOUNT or FTW_PHYS) >= 0 -} - -internal expect class MiraiFileImpl(path: String) : MiraiFile { - companion object { - public fun getWorkingDir(): MiraiFile - } -} - - -/* - Data from https://man7.org/linux/man-pages/man2/lstat.2.html - - - st_dev This field describes the device on which this file - resides. (The major(3) and minor(3) macros may be useful - to decompose the device ID in this field.) - - st_ino This field contains the file's inode number. - - st_mode - This field contains the file type and mode. See inode(7) - for further information. - - S_IFMT 0170000 bit mask for the file type bit field - - S_IFSOCK 0140000 socket - S_IFLNK 0120000 symbolic link - S_IFREG 0100000 regular file - S_IFBLK 0060000 block device - S_IFDIR 0040000 directory - S_IFCHR 0020000 character device - S_IFIFO 0010000 FIFO - - - st_nlink - This field contains the number of hard links to the file. - - st_uid This field contains the user ID of the owner of the file. - - st_gid This field contains the ID of the group owner of the file. - - st_rdev - This field describes the device that this file (inode) - represents. - - st_size - This field gives the size of the file (if it is a regular - file or a symbolic link) in bytes. The size of a symbolic - link is the length of the pathname it contains, without a - terminating null byte. - - st_blksize - This field gives the "preferred" block size for efficient - filesystem I/O. - - st_blocks - This field indicates the number of blocks allocated to the - file, in 512-byte units. (This may be smaller than - st_size/512 when the file has holes.) - - st_atime - This is the time of the last access of file data. - - st_mtime - This is the time of last modification of file data. - - st_ctime - This is the file's last status change timestamp (time of - last change to the inode). - - */ -internal inline fun MiraiFileImpl.useStat(block: (stat) -> R): R? { - memScoped { - val stat = alloc() - val ret = stat(absolutePath, stat.ptr) - if (ret != 0) return null - return block(stat) - } -} - -internal class FileNotFoundException(message: String, cause: Throwable? = null) : - IOException(message, cause) - - -@Suppress("DEPRECATION") -internal class PosixFileInstanceOutput(val file: CPointer) : Output() { - private var closed = false - - override fun flush(source: Memory, offset: Int, length: Int) { - val end = offset + length - var currentOffset = offset - - while (currentOffset < end) { - val result = fwrite( - source.pointer + currentOffset.convert(), - sizeOf().convert(), - (end - currentOffset).convert(), - file.cast() - ).convert() - if (result == 0) { - throw PosixException.forErrno(posixFunctionName = "fwrite()").wrapIO() - } - currentOffset += result - } - } - - override fun closeDestination() { - if (closed) return - closed = true - - if (fclose(file) != 0) { - throw PosixException.forErrno(posixFunctionName = "fclose").wrapIO() - } - } -} - -@Suppress("DEPRECATION") -internal class PosixInputForFile(val file: CPointer) : Input() { - private var closed = false - - override fun fill(destination: Memory, offset: Int, length: Int): Int { - val size = fread( - destination.pointer + offset.convert(), - sizeOf().convert(), - length.convert(), - file.cast() - ).toInt() - if (size == 0) { - if (feof(file) != 0) return 0 - throw PosixException.forErrno(posixFunctionName = "read()").wrapIO() - } - - return size - } - - override fun closeSource() { - if (closed) return - closed = true - - if (fclose(file) != 0) { - throw PosixException.forErrno(posixFunctionName = "fclose()").wrapIO() - } - } -} - -public fun PosixException.wrapIO(): IOException = - IOException("I/O operation failed due to posix error code $errno", this) diff --git a/mirai-core-utils/src/nativeMain/kotlin/NativePlatformSupport.kt b/mirai-core-utils/src/nativeMain/kotlin/NativePlatformSupport.kt deleted file mode 100644 index 9c930c234..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/NativePlatformSupport.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.cinterop.* - -public inline infix fun UShort.flag(flag: UShort): Boolean = this and flag != 0u.toUShort() -public inline infix fun UInt.flag(flag: UInt): Boolean = this and flag != 0u -public inline infix fun UInt.flag(flag: Int): Boolean = this and flag.toUInt() != 0u -public inline infix fun Int.flag(flag: UInt): Boolean = this.toUInt() and flag != 0u -public inline infix fun ULong.flag(flag: ULong): Boolean = this and flag != 0uL - -public val NULL_PTR: COpaquePointerVar = nativeHeap.alloc() -public inline fun nullPtr(): T = NULL_PTR.reinterpret() \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/SecretsProtection.kt b/mirai-core-utils/src/nativeMain/kotlin/SecretsProtection.kt deleted file mode 100644 index a83b31818..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/SecretsProtection.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2019-2023 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.KSerializer -import kotlinx.serialization.builtins.ByteArraySerializer -import kotlinx.serialization.builtins.serializer - -internal actual object SecretsProtectionPlatform { - actual fun impl_asString(data: Any): String { - return (data as ByteArray).decodeToString() - } - - actual fun impl_asByteArray(data: Any): ByteArray { - return data as ByteArray - } - - actual fun impl_getSize(data: Any): Int { - return data.cast().size - } - - actual fun escape(data: ByteArray): Any { - return data - } - - actual object EscapedStringSerializer : KSerializer by String.serializer().map( - String.serializer().descriptor.copy("EscapedString"), - deserialize = { SecretsProtection.EscapedString(it.encodeToByteArray()) }, - serialize = { it.data.cast().decodeToString() } - ) - - actual object EscapedByteBufferSerializer : - KSerializer by ByteArraySerializer().map( - ByteArraySerializer().descriptor.copy("EscapedByteBuffer"), - deserialize = { SecretsProtection.EscapedByteBuffer(it) }, - serialize = { it.data.cast() } - ) - - -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/Service.kt b/mirai-core-utils/src/nativeMain/kotlin/Service.kt deleted file mode 100644 index c74f7e495..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/Service.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import net.mamoe.mirai.utils.Services.qualifiedNameOrFail -import kotlin.reflect.KClass - -@Suppress("UNCHECKED_CAST") -public actual fun loadServiceOrNull( - clazz: KClass, - fallbackImplementation: String? -): T? = - Services.firstImplementationOrNull(qualifiedNameOrFail(clazz)) as T? - -public actual fun loadService( - clazz: KClass, - fallbackImplementation: String? -): T = loadServiceOrNull(clazz, fallbackImplementation) - ?: error("Could not load service '${clazz.qualifiedName ?: clazz}'. Current services: ${Services.print()}") - -public actual fun loadServices(clazz: KClass): Sequence = - Services.implementations(qualifiedNameOrFail(clazz)).orEmpty().map { it.value }.castUp() diff --git a/mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt b/mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt deleted file mode 100644 index a8ab13b3d..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/StandardUtils.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 localIpAddress(): String = "192.168.1.123" - -internal actual fun isSameClassPlatform(object1: Any, object2: Any): Boolean { - return object1::class == object2::class -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/StructureToStringTransformer.kt b/mirai-core-utils/src/nativeMain/kotlin/StructureToStringTransformer.kt deleted file mode 100644 index b1bb3d47f..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/StructureToStringTransformer.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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 getPlatformDefaultStructureToStringTransformer(): StructureToStringTransformer? { - return null -} diff --git a/mirai-core-utils/src/nativeMain/kotlin/TimeUtils.kt b/mirai-core-utils/src/nativeMain/kotlin/TimeUtils.kt deleted file mode 100644 index 83fd24a4a..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/TimeUtils.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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:Suppress("RedundantVisibilityModifier") - -package net.mamoe.mirai.utils - -import kotlinx.atomicfu.locks.ReentrantLock -import kotlinx.atomicfu.locks.withLock -import kotlinx.cinterop.* -import platform.posix.* - -/** - * 时间戳 - */ -@OptIn(UnsafeNumber::class) -public actual fun currentTimeMillis(): Long { - // Do not use getTimeMillis from stdlib, it doesn't support iosSimulatorArm64 - memScoped { - val spec = alloc() - clock_gettime(CLOCK_REALTIME.convert(), spec.ptr) - return (spec.tv_sec * 1000 + spec.tv_nsec.convert() / 1e6).toLong() - } -} - - -private val timeLock = ReentrantLock() - -public actual fun formatTime(epochTimeMillis: Long, format: String?): String = timeLock.withLock { - val strftimeFormat = format - ?.replace("yyyy", "%Y") - ?.replace("MM", "%m") - ?.replace("dd", "%d") - ?.replace("HH", "%H") - ?.replace("mm", "%M") - ?.replace("ss", "%S") - ?: "%Y-%m-%d %H:%M:%S" - memScoped { - val timeT = alloc() - timeT.value = epochTimeMillis / 1000 - - // http://www.cplusplus.com/reference/clibrary/ctime/localtime/ - // tm returns a static pointer which doesn't need to free - val tm = localtime(timeT.ptr) // localtime is not thread-safe - - val bb = allocArray(40) - - strftime(bb, 40, strftimeFormat, tm); - - bb.toKString() - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMain/kotlin/cipher.rs b/mirai-core-utils/src/nativeMain/kotlin/cipher.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/mirai-core-utils/src/nativeMain/kotlin/getProperty.kt b/mirai-core-utils/src/nativeMain/kotlin/getProperty.kt deleted file mode 100644 index 1ee367d81..000000000 --- a/mirai-core-utils/src/nativeMain/kotlin/getProperty.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 - -private val properties: MutableMap = ConcurrentHashMap() - -internal actual fun getProperty(name: String, default: String): String? { - return properties.getOrElse(name) { default } -} - -internal actual fun setProperty(name: String, value: String) { - properties[name] = value -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMainInterop/.gitignore b/mirai-core-utils/src/nativeMainInterop/.gitignore deleted file mode 100644 index 683119ebf..000000000 --- a/mirai-core-utils/src/nativeMainInterop/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/target -Cargo.lock -myrust.h - -*.iml - -src/bindings.rs -/*.h \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMainInterop/Cargo.toml b/mirai-core-utils/src/nativeMainInterop/Cargo.toml deleted file mode 100644 index 4e35d2e0a..000000000 --- a/mirai-core-utils/src/nativeMainInterop/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "mirai_core_utils_i" -version = "0.1.0" - -[dependencies] -md5 = "0.7.0" -sha1 = "0.10.1" -flate2 = "1.0.23" -libc = "0.2.126" -#chashmap = "2.2.2" - -[lib] -name = "mirai_core_utils_i" -crate-type = ["cdylib"] # Creates dynamic lib -# crate-type = ["staticlib"] # Creates static lib - -[build-dependencies] -bindgen = "0.53.1" -cbindgen = "0.20.0" diff --git a/mirai-core-utils/src/nativeMainInterop/build.rs b/mirai-core-utils/src/nativeMainInterop/build.rs deleted file mode 100644 index 669efe88f..000000000 --- a/mirai-core-utils/src/nativeMainInterop/build.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 - */ - -extern crate bindgen; -extern crate cbindgen; - -use std::env; -use std::path::PathBuf; - -use cbindgen::Config; -use cbindgen::Language::C; - -fn main() { - // let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); - - // cbindgen::Builder::new() - // .with_crate(crate_dir) - // .with_language(C) - // .generate() - // .expect("Unable to generate bindings") - // .write_to_file("nativeInterop.h"); - - - println!("cargo:rustc-link-search=../../build/bin/native/debugShared"); - println!("cargo:rustc-link-lib=mirai_core_utils"); -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeMainInterop/cbindgen.toml b/mirai-core-utils/src/nativeMainInterop/cbindgen.toml deleted file mode 100644 index 4aa4b4903..000000000 --- a/mirai-core-utils/src/nativeMainInterop/cbindgen.toml +++ /dev/null @@ -1,10 +0,0 @@ -# This is a template cbindgen.toml file with all of the default values. -# Some values are commented out because their absence is the real default. -# -# See https://github.com/eqrion/cbindgen/blob/master/docs.md#cbindgentoml -# for detailed documentation of every option here. - - - -language = "C" - diff --git a/mirai-core-utils/src/nativeMainInterop/interop.def b/mirai-core-utils/src/nativeMainInterop/interop.def deleted file mode 100644 index e69de29bb..000000000 diff --git a/mirai-core-utils/src/nativeMainInterop/src/chmap.rs b/mirai-core-utils/src/nativeMainInterop/src/chmap.rs deleted file mode 100644 index 8293ac703..000000000 --- a/mirai-core-utils/src/nativeMainInterop/src/chmap.rs +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 - */ - -// use std::ops::DerefMut; -// use std::ptr::{null, null_mut}; -// -// use chashmap::CHashMap; -// use libc::c_void; -// // -// #[no_mangle] -// pub extern "C" fn mirai_chmap_create() -> *mut c_void { -// let map = CHashMap::<*mut c_void, *mut c_void>::new(); -// // Box::into_raw(Box::new(map)) -// return Box::into_raw(Box::new(map)) as *mut c_void; -// } -// -// #[no_mangle] -// pub unsafe extern "C" fn mirai_chmap_put(map: *const c_void, key: *const c_void, value: *const c_void) -> *const c_void { -// let chmap = Box::from_raw(map as *mut CHashMap::<*const c_void, *const c_void>); -// return chmap.insert(key, value).unwrap_or(null()); -// } diff --git a/mirai-core-utils/src/nativeMainInterop/src/crypto.rs b/mirai-core-utils/src/nativeMainInterop/src/crypto.rs deleted file mode 100644 index 6efd52b6e..000000000 --- a/mirai-core-utils/src/nativeMainInterop/src/crypto.rs +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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 - */ - -use std::io::{BufReader, Read, Write}; - -use flate2::Compression; -use flate2::write::{DeflateDecoder, DeflateEncoder, GzDecoder, GzEncoder, ZlibDecoder, ZlibEncoder}; -use libc::{malloc, read, size_t}; -use sha1::{Digest, Sha1}; -use sha1::digest::{Output, OutputSizeUser}; -use sha1::digest::generic_array::GenericArray; - -#[no_mangle] -#[repr(C)] -pub struct SizedByteArray { - arr: *mut u8, - size: u32, -} - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_md5(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let result = md5::compute(data); - let size = 16; - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_sha1(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let mut hasher = Sha1::new(); - hasher.update(data); - let result = hasher.finalize(); - let size = 16; - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} - - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_gzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); - - let result = encoder.write_all(data).and_then(|_| { encoder.finish() }); - if result.is_err() { return false; } - let result = result.unwrap(); - - let size = result.len(); - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_ungzip(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let mut encoder = GzDecoder::new(Vec::new()); - - let result = encoder.write_all(data).and_then(|_| { encoder.finish() }); - if result.is_err() { return false; } - let result = result.unwrap(); - - let size = result.len(); - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_deflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); - - let result = encoder.write_all(data).and_then(|_| { encoder.finish() }); - if result.is_err() { return false; } - let result = result.unwrap(); - - let size = result.len(); - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} - -#[no_mangle] -pub unsafe extern "C" fn mirai_crypto_inflate(data: *const u8, len: u32, ret: &mut SizedByteArray) -> bool { - let data = unsafe { std::slice::from_raw_parts(data, len as usize) }; - let mut encoder = ZlibDecoder::new(Vec::new()); - - let result = encoder.write_all(data).and_then(|_| { encoder.finish() }); - if result.is_err() { return false; } - let result = result.unwrap(); - - let size = result.len(); - let mut memory = malloc(size).cast(); - memory.copy_from(result.as_ptr(), size); - - ret.arr = memory; - ret.size = size as u32; - return true; -} diff --git a/mirai-core-utils/src/nativeMainInterop/src/lib.rs b/mirai-core-utils/src/nativeMainInterop/src/lib.rs deleted file mode 100644 index 592b7953c..000000000 --- a/mirai-core-utils/src/nativeMainInterop/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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 - */ - -// extern crate chashmap; -extern crate core; -extern crate flate2; -extern crate libc; -extern crate sha1; - -/// cbindgen:ignore -mod bindings; -mod crypto; -mod chmap; - diff --git a/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt b/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt deleted file mode 100644 index 2c94a6236..000000000 --- a/mirai-core-utils/src/nativeTest/kotlin/AbstractNativeMiraiFileImplTest.kt +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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 io.ktor.utils.io.errors.* -import kotlin.test.* - -internal abstract class AbstractNativeMiraiFileImplTest { - protected abstract val baseTempDir: MiraiFile // MiraiFile.create("/Users/Shared/mirai_test") - protected abstract val tempPath: String - protected val tempDir by lazy { - MiraiFile.create(tempPath).apply { - assertTrue("Failed to make temp directory: ${this.absolutePath}") { mkdirs() } - } - } - - @AfterTest - fun afterTest() { - println("Cleaning up...") - println("deleteRecursively:" + baseTempDir.deleteRecursively()) - } - - @BeforeTest - fun init() { - println("Test start") - assertTrue { tempDir.exists() } - } - - @Test - fun `canonical paths for canonical input`() { - assertPathEquals(tempPath, tempDir.path) - assertPathEquals(tempPath, tempDir.absolutePath) - } - - @Test - protected open fun parent() { - assertEquals(tempDir, tempDir.resolve("s").parent) - assertEquals(tempDir.parent, tempDir.resolve("..")) - } - - @Test - open fun `canonical paths for non-canonical input`() { - // extra / - MiraiFile.create("$tempPath/").resolve("test").let { - assertPathEquals("${tempPath}/test", it.path) - assertPathEquals("${tempPath}/test", it.absolutePath) - } - // extra // - MiraiFile.create("$tempPath//").resolve("test").let { - assertPathEquals("${tempPath}/test", it.path) - assertPathEquals("${tempPath}/test", it.absolutePath) - } - // extra /. - MiraiFile.create("$tempPath/.").resolve("test").let { - assertPathEquals("${tempPath}/test", it.path) - assertPathEquals("${tempPath}/test", it.absolutePath) - } - // extra /./. - MiraiFile.create("$tempPath/./.").resolve("test").let { - assertPathEquals("${tempPath}/test", it.path) - assertPathEquals("${tempPath}/test", it.absolutePath) - } - } - - @Test - abstract fun `resolve absolute`() - - @Test - fun `exits createNewFile mkdir length`() { - assertTrue { tempDir.exists() } - - assertFalse { tempDir.resolve("not_existing_file.txt").exists() } - assertEquals(0L, tempDir.resolve("not_existing_file.txt").length) - assertTrue { tempDir.resolve("not_existing_file.txt").createNewFile() } - assertEquals(0L, tempDir.resolve("not_existing_file.txt").length) - assertTrue { tempDir.resolve("not_existing_file.txt").exists() } - - assertFalse { tempDir.resolve("not_existing_dir").exists() } - assertEquals(0L, tempDir.resolve("not_existing_dir").length) - assertTrue { tempDir.resolve("not_existing_dir").mkdir() } -// assertNotEquals(0L, tempDir.resolve("not_existing_dir").length) // length is platform-dependent, on Windows it is 0 but on unix it is not - assertTrue { tempDir.resolve("not_existing_dir").exists() } - } - - @Test - fun `isFile isDirectory`() { - assertTrue { tempDir.exists() } - - println("1") - assertFalse { tempDir.resolve("not_existing_file.txt").exists() } - assertEquals(false, tempDir.resolve("not_existing_file.txt").isFile) - println("1") - assertEquals(false, tempDir.resolve("not_existing_file.txt").isDirectory) - println("1") - assertTrue { tempDir.resolve("not_existing_file.txt").createNewFile() } - assertEquals(true, tempDir.resolve("not_existing_file.txt").isFile) - assertEquals(false, tempDir.resolve("not_existing_file.txt").isDirectory) - println("1") - assertTrue { tempDir.resolve("not_existing_file.txt").exists() } - - println("1") - assertFalse { tempDir.resolve("not_existing_dir").exists() } - assertEquals(false, tempDir.resolve("not_existing_dir").isFile) - assertEquals(false, tempDir.resolve("not_existing_dir").isDirectory) - println("1") - assertTrue { tempDir.resolve("not_existing_dir").mkdir() } - assertEquals(false, tempDir.resolve("not_existing_dir").isFile) - assertEquals(true, tempDir.resolve("not_existing_dir").isDirectory) - println("1") - assertTrue { tempDir.resolve("not_existing_dir").exists() } - } - - @Test - fun writeText() { - // new file - tempDir.resolve("writeText1.txt").let { file -> - val text = "some text" - file.writeText(text) - assertEquals(text.length, file.length.toInt()) - } - - // override - tempDir.resolve("writeText1.txt").let { file -> - val text = "some other text" - file.writeText(text) - assertEquals(text.length, file.length.toInt()) - } - } - - @Test - fun readText() { - tempDir.resolve("readText2.txt").let { file -> - assertTrue { !file.exists() } - assertFailsWith { file.readText() } - - val text = "some text" - file.writeText(text) - assertEquals(text, file.readText()) - } - } - - private val bigText = "some text".repeat(10000) - - @Test - fun writeBigText() { - // new file - tempDir.resolve("writeText3.txt").let { file -> - file.writeText(bigText) - assertEquals(bigText.length, file.length.toInt()) - } - - // override - tempDir.resolve("writeText4.txt").let { file -> - file.writeText(bigText) - assertEquals(bigText.length, file.length.toInt()) - } - } - - @Test - fun readBigText() { - tempDir.resolve("readText4.txt").let { file -> - assertTrue { !file.exists() } - assertFailsWith { file.readText() } - - file.writeText(bigText) - println("reading text") - val read = file.readText() - assertEquals(bigText.length, read.length) - assertEquals(bigText, read) - } - } - - protected fun assertPathEquals(expected: String, actual: String, message: String? = null) { - asserter.assertEquals(message, expected.replace("\\", "/"), actual.replace("\\", "/")) - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeTest/kotlin/ByteArrayOpTest.kt b/mirai-core-utils/src/nativeTest/kotlin/ByteArrayOpTest.kt deleted file mode 100644 index 58c63fdb1..000000000 --- a/mirai-core-utils/src/nativeTest/kotlin/ByteArrayOpTest.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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:OptIn(TestOnly::class) - -package net.mamoe.mirai.utils - -import io.ktor.utils.io.core.* -import kotlin.test.Test -import kotlin.test.assertEquals - -internal actual class ByteArrayOpTest : CommonByteArrayOpTest() { - - - private fun withZlibBufferSize(size: Long, block: () -> R): R { - val o = ZLIB_BUFFER_SIZE - ZLIB_BUFFER_SIZE = size - try { - return block() - } finally { - ZLIB_BUFFER_SIZE = o - } - } - - @Test - fun testDeflateBig() { - withZlibBufferSize(8192) { // use smaller buffer to check. - val str = sampleLongText.repeat(8) // 4000+ chars - println("Input size: ${str.length}") - println("Deflating") - println() - val bytes = str.toByteArray().deflate() - println() - println("Deflated, size = ${bytes.size}, content = ${bytes.toUHexString()}") - println() - println("Inflating") - println() - val inflated = bytes.inflate() - println() - println("Inflated, size = ${inflated.size}, content = ${inflated.toUHexString()}") - println() - assertEquals(str, inflated.decodeToString()) - } - } - - - @Test - fun testInflateBigDataFromJvm() { - withZlibBufferSize(8192) { // use smaller buffer to check. - val input = - "78 9C ED 92 31 8E 1B 31 0C 45 AF C2 2E CD C2 B0 8B 5D 20 65 4A 03 0E B0 57 E0 68 68 0F 61 89 12 44 CA B3 73 FB E5 C8 09 E2 23 A4 50 27 41 E4 E7 E7 D7 BB E4 4A 09 CE 45 5B 02 56 50 4E 25 6E 30 B7 94 36 30 FA 32 C8 57 B0 85 A0 54 16 63 B9 01 CA 0C B6 15 52 B2 7E 67 99 9B 5A DD 0E 70 79 91 5A 50 61 22 92 DE FB B7 E4 87 EB 9B F7 63 9D 5F 27 D0 83 AA 0F 96 40 BD FA F4 7E 3C EA 1B AC 8B 77 A3 40 93 BB E4 55 9E 06 BC D0 72 BE 03 C2 0D 63 A4 AD BB 73 33 DD 95 86 8A 69 8A 34 03 9B 97 41 C2 BB 3F 3C DF B5 50 E0 E4 8A 93 B7 1F E0 6C DD A1 B6 FA E0 87 37 48 F6 45 C5 17 BF FA 15 02 89 B5 CA E4 2E A6 66 80 51 73 77 16 09 8B 2F E3 D2 14 29 58 CD C2 E1 35 8B 37 F0 00 90 65 8F 85 54 5D 85 DD E5 E6 2B 84 05 E5 46 73 1F BC FA E0 92 4B 8B 58 59 77 B3 CF 90 4E 3F 3F 8E 0A 2B DB D2 AF D5 47 A0 D2 BE E0 85 AC FA D1 40 17 22 53 08 59 EC CF 94 D7 C8 0B AA E2 6D 37 BD 87 91 FC C5 45 F6 55 DC 41 97 9D 49 EF 96 0B 94 36 45 D6 65 EF D7 7C B5 15 BD 32 B2 67 F5 2B FA 3F C1 A7 8B FC F6 E8 AA 3B 0B B1 CD 7B 9D FF 90 72 16 ED 76 FE CD 3C 5C 06 3D 83 9E 41 CF A0 67 D0 33 E8 19 F4 0C 7A 06 3D 83 9E 41 CF A0 67 D0 33 E8 19 F4 FC 87 F4 7C 03 ED CB 93 EB" - .hexToBytes() - println() - val bytes = input.inflate() - println("Inflated, size = ${bytes.size}, content = ${bytes.toUHexString()}") - println() - val expected = sampleLongText.repeat(8) - val actual = bytes.decodeToString() - println(expected) - println(actual) - assertEquals(expected.length, actual.length) - assertEquals(expected, actual) - } - } - -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeTest/kotlin/CollectionsTest.kt b/mirai-core-utils/src/nativeTest/kotlin/CollectionsTest.kt deleted file mode 100644 index f31e36291..000000000 --- a/mirai-core-utils/src/nativeTest/kotlin/CollectionsTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFails -import kotlin.test.assertFalse - -internal sealed class MapTest( - private val map: MutableMap -) { - class ConcurrentMapTest : MapTest(ConcurrentHashMap()) - - @Test - fun `initial state test`() { - assertEquals(0, map.size) - assertEquals(null, map[1]) - assertFalse(map.iterator().hasNext()) - assertFails { map.iterator().next() } - } - - @Test - fun `get set size`() { - assertEquals(0, map.size) - assertEquals(null, map[1]) - map[1] = 2 - assertEquals(2, map[1]) - assertEquals(1, map.size) - map[2] = 2 - assertEquals(2, map[2]) - assertEquals(2, map.size) - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeTest/kotlin/TimeUtilsTest.kt b/mirai-core-utils/src/nativeTest/kotlin/TimeUtilsTest.kt deleted file mode 100644 index e356175e4..000000000 --- a/mirai-core-utils/src/nativeTest/kotlin/TimeUtilsTest.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - -internal class TimeUtilsTest { - - @Test - fun `can get currentTimeMillis`() { - val time = currentTimeMillis() - assertTrue(time.toString()) { time > 1654209523269 } - } - - @Test - fun `can get currentTimeFormatted`() { - // 2022-28-26 18:28:28 - assertTrue { currentTimeFormatted().matches(Regex("""^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$""")) } - } - - @Test - fun `can parse explicit timestamp`() { - val epochMilli = 1681174590123 // 2023-04-11 00:56:30 GMT - val regex = Regex("""^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$""") - - val formatted = regex.find(formatTime(epochMilli, null)) - assertNotNull(formatted) - - formatted.groupValues.run { - assertEquals(get(1), "2023") - assertEquals(get(2), "04") - assertTrue { get(3) == "11" || get(3) == "10" } - assertTrue { get(4).toInt() in 0..23 } - assertEquals(get(5), "56") - assertEquals(get(6), "30") - } - } - - @Test - fun `can format with custom formatter`() { - fun formatTimeAndPrint(formatter: String?): String { - return formatTime(currentTimeMillis(), formatter).also { println("custom formatted time: $it") } - } - - assertTrue { - formatTimeAndPrint("MmMm").matches(Regex("""^MmMm$""")) - } - assertTrue { - formatTimeAndPrint("MM-mm").matches(Regex("""^\d{2}-\d{2}$""")) - } - assertTrue { - formatTimeAndPrint("yyyyMMddHHmmss").matches(Regex("""^\d{14}$""")) - } - assertTrue { - formatTimeAndPrint("yyyyMMddHHmmSS").matches(Regex("""^\d{12}SS$""")) - } - assertTrue { - formatTimeAndPrint(null).matches(Regex("""^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$""")) - } - assertTrue { - formatTimeAndPrint("yyyy-MM-dd 114514").matches(Regex("""^\d{4}-\d{2}-\d{2} 114514$""")) - } - assertTrue { - formatTimeAndPrint("yyyyMM-114 514--mm-SS").matches(Regex("""^\d{4}\d{2}-114 514--\d{2}-SS$""")) - } - assertTrue { - formatTimeAndPrint("yyyy-MM-dd HH-mm-ss").matches(Regex("""^\d{4}-\d{2}-\d{2} \d{2}-\d{2}-\d{2}$""")) - } - assertTrue { - formatTimeAndPrint("yyyy/MM\\dd HH:mm-ss").matches(Regex("""^\d{4}/\d{2}\\\d{2} \d{2}:\d{2}-\d{2}$""")) - } - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/nativeTest/kotlin/package.kt b/mirai-core-utils/src/nativeTest/kotlin/package.kt deleted file mode 100644 index f699501a9..000000000 --- a/mirai-core-utils/src/nativeTest/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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 \ No newline at end of file diff --git a/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt b/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt deleted file mode 100644 index 8fdbebe64..000000000 --- a/mirai-core-utils/src/unixMain/kotlin/MiraiFileImpl.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* - * 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 io.ktor.utils.io.core.* -import io.ktor.utils.io.errors.* -import kotlinx.cinterop.* -import platform.posix.* - -private fun readlink(path: String): String = memScoped { - val len = realpath(path, null) - if (len != null) { - try { - return len.toKString() - } finally { - free(len) - } - } else { - when (val errno = errno) { - ENOTDIR -> return@memScoped path - EACCES -> return@memScoped path // permission denied - ENOENT -> return@memScoped path // no such file - else -> throw IllegalArgumentException( - "Invalid path($errno): $path", - cause = PosixException.forErrno(posixFunctionName = "realpath()") - ) - } - } -} - -internal actual class MiraiFileImpl actual constructor( - override val path: String, -) : MiraiFile { - actual companion object { - private const val SEPARATOR = '/' - private val ROOT by lazy { MiraiFileImpl("/") } - - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(UnsafeNumber::class) - actual fun getWorkingDir(): MiraiFile { - val path = memScoped { - ByteArray(PATH_MAX).usePinned { - getcwd(it.addressOf(0), it.get().size.convert()) - it.get().toKString() - } - } - return MiraiFile.create(path) - } - } - - override val absolutePath: String by lazy { kotlin.run { readlink(path) } } - - override val parent: MiraiFile? by lazy { - val absolutePath = absolutePath - val p = absolutePath.substringBeforeLast(SEPARATOR, "") - if (p.isEmpty()) { - if (absolutePath.singleOrNull() == SEPARATOR) return@lazy null // root - else return@lazy ROOT - } - MiraiFileImpl(p) - } - - override val name: String - get() = absolutePath.substringAfterLast('/', "").ifEmpty { absolutePath } - - init { - absolutePath.split('/').forEach { checkName(it) } - } - - private fun checkName(name: String) { - name.forEach { c -> - if (c in """\/:?*"><|""") { - throw IllegalArgumentException("'${name}' contains illegal character '$c'.") - } - } - } - - override val length: Long - get() = useStat { it.st_size.convert() } ?: 0 - - @OptIn(UnsafeNumber::class) - override val isFile: Boolean - get() = useStat { it.st_mode.convert() flag S_IFREG } ?: false - - @OptIn(UnsafeNumber::class) - override val isDirectory: Boolean - get() = useStat { it.st_mode.convert() flag S_IFDIR } ?: false - - override fun exists(): Boolean = useStat { true } ?: false - - override fun resolve(path: String): MiraiFile { - when (path) { - "." -> return this - ".." -> return parent ?: this // root - } - - if (path.startsWith(SEPARATOR)) { - return MiraiFileImpl(path) - } - - return MiraiFileImpl("$absolutePath/$path") - } - - override fun resolve(file: MiraiFile): MiraiFile { - val parent = file.parent ?: return resolve(file.name) - return resolve(parent).resolve(file.name) - } - - override fun createNewFile(): Boolean { - memScoped { - val fp = fopen(absolutePath, "w") - fwrite(fp, 0, 0, fp) - fclose(fp) - return true - } - } - - override fun delete(): Boolean { - return if (isFile) { - remove(absolutePath) == 0 - } else { - rmdir(absolutePath) == 0 - } - } - - override fun mkdir(): Boolean { - @Suppress("UnnecessaryOptInAnnotation") // bug - @OptIn(UnsafeNumber::class) - return (mkdir("$absolutePath/", "755".toUShort(8).convert()).convert() == 0) - } - - @OptIn(UnsafeNumber::class) - override fun mkdirs(): Boolean { - val flags = useStat { it.st_mode.convert() } - return when { - flags == null -> { - this.parent?.mkdirs() - mkdir() - } - flags flag S_IFDIR -> { - false // already exists - } - else -> { - mkdir() - } - } - } - - override fun input(): Input { - val handle = fopen(absolutePath, "rb") - ?: throw IOException( - "Failed to open file '$absolutePath'", - PosixException.forErrno(posixFunctionName = "fopen()") - ) - return PosixInputForFile(handle) - } - - override fun output(): Output { - val handle = fopen(absolutePath, "wb") - ?: throw IOException( - "Failed to open file '$absolutePath'", - PosixException.forErrno(posixFunctionName = "fopen()") - ) - return PosixFileInstanceOutput(handle) - } - - override fun hashCode(): Int { - return this.path.hashCode() - } - - override fun equals(other: Any?): Boolean { - if (other == null) return false - if (!isSameType(this, other)) return false - return this.path == other.path - } - - override fun toString(): String { - return "MiraiFileImpl($path)" - } -} \ No newline at end of file diff --git a/mirai-core-utils/src/unixMain/kotlin/StandardUtils.kt b/mirai-core-utils/src/unixMain/kotlin/StandardUtils.kt deleted file mode 100644 index 56bf10284..000000000 --- a/mirai-core-utils/src/unixMain/kotlin/StandardUtils.kt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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.cinterop.UnsafeNumber -import kotlinx.cinterop.convert -import platform.posix._SC_NPROCESSORS_ONLN -import platform.posix.sysconf - -@OptIn(UnsafeNumber::class) -public actual fun availableProcessors(): Int = sysconf(_SC_NPROCESSORS_ONLN).convert() diff --git a/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt b/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt deleted file mode 100644 index 41e0ed03e..000000000 --- a/mirai-core-utils/src/unixTest/kotlin/UnixMiraiFileImplTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.math.absoluteValue -import kotlin.random.Random -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class UnixMiraiFileImplTest : AbstractNativeMiraiFileImplTest() { - private val rand = Random.nextInt().absoluteValue - override val baseTempDir: MiraiFile by lazy { MiraiFile.create(MiraiFile.getWorkingDir().absolutePath + "/mirai_unit_tests") } - override val tempPath by lazy { "${baseTempDir.absolutePath}/temp$rand" } - - @Test - override fun parent() { - assertEquals(baseTempDir.absolutePath, tempDir.parent!!.absolutePath) - assertEquals(null, MiraiFile.create("/").parent) - assertEquals("/", MiraiFile.create("/dev").parent?.path) - assertEquals("/", MiraiFile.create("/dev").parent?.absolutePath) - super.parent() - } - - @Test - override fun `canonical paths for non-canonical input`() { - super.`canonical paths for non-canonical input`() - - // extra /sss/.. - MiraiFile.create("$tempPath/sss/..").resolve("test").let { - assertPathEquals("${tempPath}/sss/../test", it.path) // because file is not found - assertPathEquals("${tempPath}/sss/../test", it.absolutePath) - } - } - - @Test - override fun `resolve absolute`() { - MiraiFile.create("$tempPath/").resolve("/Users").let { - assertEquals("/Users", it.path) - assertEquals("/Users", it.absolutePath) - } - } -} \ No newline at end of file diff --git a/mirai-core/build.gradle.kts b/mirai-core/build.gradle.kts index 1d5057af2..757d2dc8b 100644 --- a/mirai-core/build.gradle.kts +++ b/mirai-core/build.gradle.kts @@ -10,8 +10,6 @@ @file:Suppress("UNUSED_VARIABLE") import BinaryCompatibilityConfigurator.configureBinaryValidators -import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractNativeLibrary -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget import shadow.relocateCompileOnly import shadow.relocateImplementation @@ -32,8 +30,6 @@ kotlin { apply(plugin = "explicit-api") configureJvmTargetsHierarchical("net.mamoe.mirai.internal") - configureNativeTargetsHierarchical(project) - configureNativeTargetBinaries(project) // register native binaries for mirai-core only optInForAllSourceSets("net.mamoe.mirai.utils.MiraiExperimentalApi") optInForAllSourceSets("net.mamoe.mirai.utils.MiraiInternalApi") @@ -122,11 +118,6 @@ kotlin { } } - findByName("nativeMain")?.apply { - dependencies { - } - } - // Kt bignum findByName("jvmBaseMain")?.apply { @@ -150,75 +141,12 @@ kotlin { relocateImplementation(`ktor-client-core_relocated`) } } - configure(NATIVE_TARGETS.map { getByName(it + "Main") } - + NATIVE_TARGETS.map { getByName(it + "Test") }) { - // no relocation in native, include binaries - dependencies { - api(`ktor-io`) { - exclude(ExcludeProperties.`slf4j-api`) - } - } - } findByName("jvmBaseMain")?.apply { dependencies { relocateImplementation(`ktor-client-okhttp_relocated`) } } - configure(WIN_TARGETS.map { getByName(it + "Main") }) { - dependencies { - implementation(`ktor-client-curl`) - } - } - configure(LINUX_TARGETS.map { getByName(it + "Main") }) { - dependencies { - implementation(`ktor-client-cio`) - } - } - findByName("darwinMain")?.apply { - dependencies { - implementation(`ktor-client-darwin`) - } - } - - // Linkage - NATIVE_TARGETS.forEach { targetName -> - val defFile = projectDir.resolve("src/nativeMain/cinterop/OpenSSL.def") - val target = targets.getByName(targetName) as KotlinNativeTarget - target.compilations.getByName("main").cinterops.create("OpenSSL") - .apply { - this.defFile = defFile - packageName("openssl") - } - - configure(target.binaries.filterIsInstance()) { - export(project(":mirai-core-api")) - export(project(":mirai-core-utils")) - } - } - - UNIX_LIKE_TARGETS.forEach { target -> - (targets.getByName(target) as KotlinNativeTarget).compilations.getByName("main").cinterops.create("Socket") - .apply { - defFile = projectDir.resolve("src/unixMain/cinterop/Socket.def") - packageName("sockets") - } - } - - WIN_TARGETS.forEach { target -> - (targets.getByName(target) as KotlinNativeTarget).compilations.getByName("main").cinterops.create("Socket") - .apply { - defFile = projectDir.resolve("src/mingwX64Main/cinterop/Socket.def") - packageName("sockets") - } - } - - disableCrossCompile() -// val unixMain by getting { -// dependencies { -// implementation(`ktor-client-cio`) -// } -// } } } @@ -226,28 +154,6 @@ atomicfu { transformJvm = false } -afterEvaluate { - val main = projectDir.resolve("src/nativeTest/kotlin/local/TestMain.kt") - if (!main.exists()) { - main.writeText( - """ - /* - * 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.internal.local - - fun main() {} - """.trimIndent() - ) - } -} - if (tasks.findByName("androidMainClasses") != null) { tasks.register("checkAndroidApiLevel") { doFirst { diff --git a/mirai-core/src/commonMain/kotlin/network/components/QRCodeLoginProcessor.kt b/mirai-core/src/commonMain/kotlin/network/components/QRCodeLoginProcessor.kt index da11eae22..a3ded7fb6 100644 --- a/mirai-core/src/commonMain/kotlin/network/components/QRCodeLoginProcessor.kt +++ b/mirai-core/src/commonMain/kotlin/network/components/QRCodeLoginProcessor.kt @@ -84,7 +84,6 @@ internal class QRCodeLoginProcessorImpl( margin = qrCodeLoginListener.qrCodeMargin, ecLevel = qrCodeLoginListener.qrCodeEcLevel, ), - attempts = 1 ) check(resp is WtLogin.TransEmp.Response.FetchQRCode) { "Cannot fetch qrcode, resp=$resp" } qrCodeLoginListener.onFetchQRCode(handler.context.bot, resp.imageData) diff --git a/mirai-core/src/commonTest/kotlin/test/NativeTestWrapper.kt b/mirai-core/src/commonTest/kotlin/test/NativeTestWrapper.kt deleted file mode 100644 index 2d29a7dac..000000000 --- a/mirai-core/src/commonTest/kotlin/test/NativeTestWrapper.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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:JvmName("NativeTestWrapperKt") - -package net.mamoe.mirai.internal.test - -import kotlin.jvm.JvmName -import kotlin.test.Test - -internal class NativeTestWrapper { - @Test - fun test() { - startNativeTestIfNeeded() - } -} - -internal expect fun startNativeTestIfNeeded() \ No newline at end of file diff --git a/mirai-core/src/commonTest/kotlin/testFramework/Platform.kt b/mirai-core/src/commonTest/kotlin/testFramework/Platform.kt index 843faa39f..ed5524966 100644 --- a/mirai-core/src/commonTest/kotlin/testFramework/Platform.kt +++ b/mirai-core/src/commonTest/kotlin/testFramework/Platform.kt @@ -15,7 +15,6 @@ expect fun currentPlatform(): Platform enum class PlatformRuntime { JVM, DALVIK, - NATIVE, } // see `@DisabledOnPlatform` @@ -33,19 +32,5 @@ sealed class Platform( object AndroidInstrumentedTest : Android(PlatformRuntime.DALVIK) object Jvm : JvmLike(PlatformRuntime.JVM) - - sealed class Native : Platform(PlatformRuntime.NATIVE) - - sealed class Windows : Native() - object MingwX64 : Windows() - - sealed class UnixLike : Native() - - sealed class Linux : UnixLike() - object LinuxX64 : Linux() - - sealed class Macos : UnixLike() - object MacosX64 : Macos() - object MacosArm64 : Macos() } diff --git a/mirai-core/src/darwinMain/kotlin/MiraiImpl.kt b/mirai-core/src/darwinMain/kotlin/MiraiImpl.kt deleted file mode 100644 index 07f8cd43a..000000000 --- a/mirai-core/src/darwinMain/kotlin/MiraiImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.internal - -import io.ktor.client.* -import io.ktor.client.engine.darwin.* -import io.ktor.client.plugins.* - -internal actual fun createDefaultHttpClient(): HttpClient { - return HttpClient(Darwin) { - install(HttpTimeout) { - this.requestTimeoutMillis = 30_0000 - this.connectTimeoutMillis = 30_0000 - this.socketTimeoutMillis = 30_0000 - } - } -} diff --git a/mirai-core/src/darwinMain/kotlin/package.kt b/mirai-core/src/darwinMain/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/darwinMain/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/darwinTest/kotlin/package.kt b/mirai-core/src/darwinTest/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/darwinTest/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/jvmBaseTest/kotlin/test/NativeTestWrapper.kt b/mirai-core/src/jvmBaseTest/kotlin/test/NativeTestWrapper.kt index a448d7241..e5eb9da80 100644 --- a/mirai-core/src/jvmBaseTest/kotlin/test/NativeTestWrapper.kt +++ b/mirai-core/src/jvmBaseTest/kotlin/test/NativeTestWrapper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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,4 +9,3 @@ package net.mamoe.mirai.internal.test -internal actual fun startNativeTestIfNeeded() {} \ No newline at end of file diff --git a/mirai-core/src/linuxX64Main/kotlin/MiraiImpl.kt b/mirai-core/src/linuxX64Main/kotlin/MiraiImpl.kt deleted file mode 100644 index 841be8763..000000000 --- a/mirai-core/src/linuxX64Main/kotlin/MiraiImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.internal - -import io.ktor.client.* -import io.ktor.client.engine.cio.* -import io.ktor.client.plugins.* - -internal actual fun createDefaultHttpClient(): HttpClient { - return HttpClient(CIO) { - install(HttpTimeout) { - this.requestTimeoutMillis = 30_0000 - this.connectTimeoutMillis = 30_0000 - this.socketTimeoutMillis = 30_0000 - } - } -} diff --git a/mirai-core/src/linuxX64Main/kotlin/package.kt b/mirai-core/src/linuxX64Main/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/linuxX64Main/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/linuxX64Test/kotlin/package.kt b/mirai-core/src/linuxX64Test/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/linuxX64Test/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/linuxX64Test/kotlin/testFramework/currentPlatform.kt b/mirai-core/src/linuxX64Test/kotlin/testFramework/currentPlatform.kt deleted file mode 100644 index 20fc1db67..000000000 --- a/mirai-core/src/linuxX64Test/kotlin/testFramework/currentPlatform.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.testFramework - -actual fun currentPlatform(): Platform = Platform.LinuxX64 \ No newline at end of file diff --git a/mirai-core/src/macosArm64Test/kotlin/package.kt b/mirai-core/src/macosArm64Test/kotlin/package.kt deleted file mode 100644 index 20b5b6a1b..000000000 --- a/mirai-core/src/macosArm64Test/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2019-2023 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.internal \ No newline at end of file diff --git a/mirai-core/src/macosArm64Test/kotlin/testFramework/currentPlatform.kt b/mirai-core/src/macosArm64Test/kotlin/testFramework/currentPlatform.kt deleted file mode 100644 index 1f61af5f3..000000000 --- a/mirai-core/src/macosArm64Test/kotlin/testFramework/currentPlatform.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.testFramework - -actual fun currentPlatform(): Platform = Platform.MacosArm64 \ No newline at end of file diff --git a/mirai-core/src/macosX64Test/kotlin/package.kt b/mirai-core/src/macosX64Test/kotlin/package.kt deleted file mode 100644 index a56b88234..000000000 --- a/mirai-core/src/macosX64Test/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2019-2023 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.internal diff --git a/mirai-core/src/macosX64Test/kotlin/testFramework/currentPlatform.kt b/mirai-core/src/macosX64Test/kotlin/testFramework/currentPlatform.kt deleted file mode 100644 index 62ef384b5..000000000 --- a/mirai-core/src/macosX64Test/kotlin/testFramework/currentPlatform.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.testFramework - -actual fun currentPlatform(): Platform = Platform.MacosX64 \ No newline at end of file diff --git a/mirai-core/src/mingwX64Main/cinterop/Socket.def b/mirai-core/src/mingwX64Main/cinterop/Socket.def deleted file mode 100644 index debd8e44c..000000000 --- a/mirai-core/src/mingwX64Main/cinterop/Socket.def +++ /dev/null @@ -1,38 +0,0 @@ -headers = winsock.h - ---- -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -static SOCKET socket_create_connect(char *host, unsigned short port) { - SOCKADDR_STORAGE local_addr = {0}; - SOCKADDR_STORAGE remote_addr = {0}; - DWORD local_addr_size = sizeof(local_addr); - DWORD remote_addr_size = sizeof(remote_addr); - char port_name[6]; - int sockfd; - - sprintf(port_name, "%d", (int)port); - - if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) == INVALID_SOCKET) { - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { - return INVALID_SOCKET; - } - } else { - int ipv6only = 0; - setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)); - } - if (!WSAConnectByNameA(sockfd, host, port_name, &local_addr_size, (SOCKADDR*)&local_addr, &remote_addr_size, (SOCKADDR*)&remote_addr, NULL, NULL)) { - closesocket(sockfd); - return INVALID_SOCKET; - } - if (setsockopt(sockfd, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == SOCKET_ERROR) { - closesocket(sockfd); - return INVALID_SOCKET; - } - return sockfd; -} \ No newline at end of file diff --git a/mirai-core/src/mingwX64Main/kotlin/MiraiImpl.kt b/mirai-core/src/mingwX64Main/kotlin/MiraiImpl.kt deleted file mode 100644 index 62a9aa7db..000000000 --- a/mirai-core/src/mingwX64Main/kotlin/MiraiImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.internal - -import io.ktor.client.* -import io.ktor.client.engine.curl.* -import io.ktor.client.plugins.* - -internal actual fun createDefaultHttpClient(): HttpClient { - return HttpClient(Curl) { - install(HttpTimeout) { - this.requestTimeoutMillis = 30_0000 - this.connectTimeoutMillis = 30_0000 - this.socketTimeoutMillis = 30_0000 - } - } -} diff --git a/mirai-core/src/mingwX64Main/kotlin/package.kt b/mirai-core/src/mingwX64Main/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/mingwX64Main/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/mingwX64Main/kotlin/utils/PlatformSocket.kt b/mirai-core/src/mingwX64Main/kotlin/utils/PlatformSocket.kt deleted file mode 100644 index c58420297..000000000 --- a/mirai-core/src/mingwX64Main/kotlin/utils/PlatformSocket.kt +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.internal.utils - -import io.ktor.utils.io.core.* -import io.ktor.utils.io.core.EOFException -import io.ktor.utils.io.errors.* -import kotlinx.cinterop.* -import kotlinx.coroutines.* -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import net.mamoe.mirai.internal.network.highway.HighwayProtocolChannel -import net.mamoe.mirai.utils.ByteArrayPool -import net.mamoe.mirai.utils.DEFAULT_BUFFER_SIZE -import net.mamoe.mirai.utils.toReadPacket -import platform.posix.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - -/** - * TCP Socket. - */ -internal actual class PlatformSocket( - private val socket: SOCKET -) : Closeable, HighwayProtocolChannel { - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) - private val readDispatcher: CoroutineDispatcher = newSingleThreadContext("PlatformSocket#$socket.readDispatcher") - - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) - private val sendDispatcher: CoroutineDispatcher = newSingleThreadContext("PlatformSocket#$socket.sendDispatcher") - - private val writeLock = Mutex() - private val writeBuffer = ByteArray(DEFAULT_BUFFER_SIZE).pin() - - actual val isOpen: Boolean - get() = send(socket, null, 0, 0).convert() != 0L - - actual override fun close() { - closesocket(socket) - (readDispatcher as? CloseableCoroutineDispatcher)?.close() - (sendDispatcher as? CloseableCoroutineDispatcher)?.close() - writeBuffer.unpin() - } - - actual suspend fun send(packet: ByteArray, offset: Int, length: Int): Unit = writeLock.withLock { - withContext(sendDispatcher) { - require(offset >= 0) { "offset must >= 0" } - require(length >= 0) { "length must >= 0" } - require(offset + length <= packet.size) { "It must follows offset + length <= packet.size" } - packet.usePinned { pin -> - if (send(socket, pin.addressOf(offset), length.convert(), 0).convert() < 0L) { - @Suppress("INVISIBLE_MEMBER") - throw PosixException.forErrno(posixFunctionName = "send()").wrapIO() - } - } - } - } - - - actual override suspend fun send(packet: ByteReadPacket): Unit = writeLock.withLock { - withContext(sendDispatcher) { - val writeBuffer = writeBuffer - while (packet.remaining != 0L) { - val length = packet.readAvailable(writeBuffer.get()) - if (send(socket, writeBuffer.addressOf(0), length.convert(), 0).convert() < 0L) { - @Suppress("INVISIBLE_MEMBER") - throw PosixException.forErrno(posixFunctionName = "send()").wrapIO() - } - } - } - } - - /** - * @throws EOFException - */ - actual override suspend fun read(): ByteReadPacket = withContext(readDispatcher) { - val readBuffer = ByteArrayPool.borrow() - try { - val length = readBuffer.usePinned { pinned -> - recv(socket, pinned.addressOf(0), pinned.get().size.convert(), 0).convert() - } - if (length <= 0L) throw EOFException("recv: $length, errno=$errno") - // [toReadPacket] 后的 readBuffer 会被其内部直接使用,而不是 copy 一份 - // 在 release 前不能被复用 - readBuffer.toReadPacket(length = length.toInt()) { ByteArrayPool.recycle(it) } - } catch (e: Throwable) { - ByteArrayPool.recycle(readBuffer) - throw e - } - } - - actual companion object { - - actual suspend fun connect( - serverIp: String, - serverPort: Int - ): PlatformSocket { - val r = sockets.socket_create_connect(serverIp.cstr, serverPort.toUShort()) - if (r == INVALID_SOCKET) error("Failed socket_create_connect: $r") - return PlatformSocket(r) - } - - actual suspend inline fun withConnection( - serverIp: String, - serverPort: Int, - block: PlatformSocket.() -> R - ): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return connect(serverIp, serverPort).use(block) - } - } - -} diff --git a/mirai-core/src/mingwX64Test/kotlin/package.kt b/mirai-core/src/mingwX64Test/kotlin/package.kt deleted file mode 100644 index a56b88234..000000000 --- a/mirai-core/src/mingwX64Test/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright 2019-2023 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.internal diff --git a/mirai-core/src/mingwX64Test/kotlin/testFramework/currentPlatform.kt b/mirai-core/src/mingwX64Test/kotlin/testFramework/currentPlatform.kt deleted file mode 100644 index e685766e3..000000000 --- a/mirai-core/src/mingwX64Test/kotlin/testFramework/currentPlatform.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.testFramework - -actual fun currentPlatform(): Platform = Platform.MingwX64 \ No newline at end of file diff --git a/mirai-core/src/nativeMain/cinterop/OpenSSL.def b/mirai-core/src/nativeMain/cinterop/OpenSSL.def deleted file mode 100644 index bdadd3671..000000000 --- a/mirai-core/src/nativeMain/cinterop/OpenSSL.def +++ /dev/null @@ -1,73 +0,0 @@ -headers = openssl/ec.h \ - openssl/ecdh.h \ - openssl/evp.h \ - openssl/rsa.h \ - openssl/pem.h \ - openssl/x509.h \ - openssl/err.h - -# -L/usr/local/opt/openssl@1.1/1.1.1o/lib is for GitHub actions. See https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md - -# For GitHub Actions macos-12 20223-4-15: -#find: /Library/Application Support/Apple/ParentalControls/Users: Permission denied -#/usr/local/Cellar/openssl@3/3.1.0/include/openssl/ecdh.h -#find: /Library/Application Support/Apple/AssetCache/Data: Permission denied -#/usr/local/Cellar/openssl@1.1/1.1.1t/include/openssl/ecdh.h -##find: /Library/Application Support/Apple/Remote Desktop/Task Server: Permission denied -#/usr/local/miniconda/include/openssl/ecdh.h -#/usr/local/miniconda/pkgs/openssl-1.1.1s-hca72f7f_0/include/openssl/ecdh.h - -linkerOpts = -lcrypto \ - -lssl \ - -L/opt/openssl/lib64 \ - -L/opt/openssl/lib \ - -L/usr/local/opt/openssl@1.1/1.1.1o/lib \ - -L/usr/local/Cellar/openssl@3/3.1.0/lib \ - -L/usr/lib/openssl@1.1/1.1.1o/lib \ - -L/opt/homebrew/Cellar/openssl@1.1/1.1.1o/lib \ - -L/opt/homebrew/Cellar/openssl@3/3.0.3/lib \ - -L/opt/homebrew/opt/openssl@3/lib \ - -L/usr/local/miniconda/lib \ - -L/usr/lib/ \ - -LC:/openssl/lib \ - -LC:/vcpkg/installed/x64-windows/lib \ - -L/usr/lib64 \ - -L/usr/lib/x86_64-linux-gnu \ - -L/opt/local/lib \ - -L/usr/local/opt/curl/lib \ - -L/opt/homebrew/opt/curl/lib - - -compilerOpts = -I/opt/openssl/include \ - -I/usr/local/include/openssl@3 \ - -I/usr/local/opt/openssl@1.1/1.1.1o/include \ - -I/usr/local/Cellar/openssl@3/3.1.0/include \ - -I/opt/homebrew/Cellar/openssl@1.1/1.1.1o/include \ - -I/opt/homebrew/Cellar/openssl@3/3.0.3/include \ - -I/usr/include/openssl@3 \ - -I/opt/homebrew/opt/openssl@3/include \ - -I/usr/local/miniconda/include \ - -I/usr/include/ \ - -I/usr/include/x86_64-linux-gnu/ \ - -I/usr/local/include/ \ - -IC:/openssl/include/ \ - -IC:/vcpkg/installed/x64-windows/include \ - ---- - -#include -#include - -static int _evpCipherCtxGetBlockSize(const EVP_CIPHER_CTX *ctx) { -#ifdef EVP_CIPHER_CTX_block_size - return EVP_CIPHER_CTX_get_block_size(ctx); -#endif - return EVP_CIPHER_CTX_block_size(ctx); -} - -static int _evpPkeyCtxSetRSAKeygenBits(EVP_PKEY_CTX *ctx, int bits) { -#ifdef EVP_PKEY_CTX_set_rsa_keygen_bits - return RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL); -#endif - return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits); -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/MiraiImpl.kt b/mirai-core/src/nativeMain/kotlin/MiraiImpl.kt deleted file mode 100644 index 70de74f4a..000000000 --- a/mirai-core/src/nativeMain/kotlin/MiraiImpl.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.internal - -import kotlinx.atomicfu.atomic -import net.mamoe.mirai.internal.message.protocol.MessageProtocolFacade -import net.mamoe.mirai.internal.utils.MiraiCoreServices - - -/** - * 初始化 Mirai Native 平台. 必须先调用此 API, 其他 API 才能正常工作. - */ -@CName("mirai_init") -public fun initMirai() { - initRuntimeIfNeeded() - _MiraiImpl_static_init() -} - - -private val initialized = atomic(false) - -@Suppress("FunctionName") -internal actual fun _MiraiImpl_static_init() { - if (!initialized.compareAndSet(expect = false, update = true)) return - MiraiCoreServices.registerAll() - MessageProtocolFacade.INSTANCE // register serializers -} diff --git a/mirai-core/src/nativeMain/kotlin/contact/GroupImpl.kt b/mirai-core/src/nativeMain/kotlin/contact/GroupImpl.kt deleted file mode 100644 index 40246af70..000000000 --- a/mirai-core/src/nativeMain/kotlin/contact/GroupImpl.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.contact - -import net.mamoe.mirai.contact.ContactList -import net.mamoe.mirai.contact.Group -import net.mamoe.mirai.data.GroupInfo -import net.mamoe.mirai.internal.QQAndroidBot -import kotlin.coroutines.CoroutineContext - -internal actual class GroupImpl actual constructor( - bot: QQAndroidBot, - parentCoroutineContext: CoroutineContext, - id: Long, - groupInfo: GroupInfo, - members: ContactList, -) : Group, CommonGroupImpl(bot, parentCoroutineContext, id, groupInfo, members) { - actual companion object -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/contact/active/GroupActiveImpl.kt b/mirai-core/src/nativeMain/kotlin/contact/active/GroupActiveImpl.kt deleted file mode 100644 index e496c3aac..000000000 --- a/mirai-core/src/nativeMain/kotlin/contact/active/GroupActiveImpl.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.internal.contact.active - -import net.mamoe.mirai.data.GroupInfo -import net.mamoe.mirai.internal.contact.GroupImpl -import net.mamoe.mirai.utils.MiraiLogger - -internal actual class GroupActiveImpl actual constructor( - group: GroupImpl, - logger: MiraiLogger, - groupInfo: GroupInfo, -) : CommonGroupActiveImpl(group, logger, groupInfo) \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/contact/file/AbsoluteFolderImpl.kt b/mirai-core/src/nativeMain/kotlin/contact/file/AbsoluteFolderImpl.kt deleted file mode 100644 index 8088e2c0b..000000000 --- a/mirai-core/src/nativeMain/kotlin/contact/file/AbsoluteFolderImpl.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.internal.contact.file - -import net.mamoe.mirai.contact.FileSupported -import net.mamoe.mirai.contact.file.AbsoluteFolder - -internal actual class AbsoluteFolderImpl actual constructor( - contact: FileSupported, - parent: AbsoluteFolder?, - id: String, - name: String, - uploadTime: Long, - uploaderId: Long, - lastModifiedTime: Long, - contentsCount: Int -) : CommonAbsoluteFolderImpl(contact, parent, id, name, uploadTime, uploaderId, lastModifiedTime, contentsCount) \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/message/protocol/impl/getEmojiPatternResource.kt b/mirai-core/src/nativeMain/kotlin/message/protocol/impl/getEmojiPatternResource.kt deleted file mode 100644 index 8c3766f13..000000000 --- a/mirai-core/src/nativeMain/kotlin/message/protocol/impl/getEmojiPatternResource.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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.internal.message.protocol.impl - -internal actual fun getEmojiPatternResourceOrNull(): String? { - return """\x{1F3F4}\x{E0067}\x{E0062}(?:\x{E0077}\x{E006C}\x{E0073}|\x{E0073}\x{E0063}\x{E0074}|\x{E0065}\x{E006E}\x{E0067})\x{E007F}|(?:\x{1F9D1}\x{1F3FF}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F9D1}|\x{1F469}\x{1F3FF}\x{200D}\x{1F91D}\x{200D}[\x{1F468}\x{1F469}]|\x{1FAF1}\x{1F3FF}\x{200D}\x{1FAF2})[\x{1F3FB}-\x{1F3FE}]|(?:\x{1F9D1}\x{1F3FE}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F9D1}|\x{1F469}\x{1F3FE}\x{200D}\x{1F91D}\x{200D}[\x{1F468}\x{1F469}]|\x{1FAF1}\x{1F3FE}\x{200D}\x{1FAF2})[\x{1F3FB}-\x{1F3FD}\x{1F3FF}]|(?:\x{1F9D1}\x{1F3FD}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F9D1}|\x{1F469}\x{1F3FD}\x{200D}\x{1F91D}\x{200D}[\x{1F468}\x{1F469}]|\x{1FAF1}\x{1F3FD}\x{200D}\x{1FAF2})[\x{1F3FB}\x{1F3FC}\x{1F3FE}\x{1F3FF}]|(?:\x{1F9D1}\x{1F3FC}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F9D1}|\x{1F469}\x{1F3FC}\x{200D}\x{1F91D}\x{200D}[\x{1F468}\x{1F469}]|\x{1FAF1}\x{1F3FC}\x{200D}\x{1FAF2})[\x{1F3FB}\x{1F3FD}-\x{1F3FF}]|(?:\x{1F9D1}\x{1F3FB}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F9D1}|\x{1F469}\x{1F3FB}\x{200D}\x{1F91D}\x{200D}[\x{1F468}\x{1F469}]|\x{1FAF1}\x{1F3FB}\x{200D}\x{1FAF2})[\x{1F3FC}-\x{1F3FF}]|\x{1F468}(?:\x{1F3FB}(?:\x{200D}(?:\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FF}]|\x{1F468}[\x{1F3FB}-\x{1F3FF}])|\x{200D}(?:\x{1F48B}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FF}]|\x{1F468}[\x{1F3FB}-\x{1F3FF}]))|\x{1F91D}\x{200D}\x{1F468}[\x{1F3FC}-\x{1F3FF}]|[\x{2695}\x{2696}\x{2708}]\x{FE0F}|[\x{2695}\x{2696}\x{2708}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]))?|[\x{1F3FC}-\x{1F3FF}]\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FF}]|\x{1F468}[\x{1F3FB}-\x{1F3FF}])|\x{200D}(?:\x{1F48B}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FF}]|\x{1F468}[\x{1F3FB}-\x{1F3FF}]))|\x{200D}(?:\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D})?|\x{200D}(?:\x{1F48B}\x{200D})?)\x{1F468}|[\x{1F468}\x{1F469}]\x{200D}(?:\x{1F466}\x{200D}\x{1F466}|\x{1F467}\x{200D}[\x{1F466}\x{1F467}])|\x{1F466}\x{200D}\x{1F466}|\x{1F467}\x{200D}[\x{1F466}\x{1F467}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FF}\x{200D}(?:\x{1F91D}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FE}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FE}\x{200D}(?:\x{1F91D}\x{200D}\x{1F468}[\x{1F3FB}-\x{1F3FD}\x{1F3FF}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FD}\x{200D}(?:\x{1F91D}\x{200D}\x{1F468}[\x{1F3FB}\x{1F3FC}\x{1F3FE}\x{1F3FF}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FC}\x{200D}(?:\x{1F91D}\x{200D}\x{1F468}[\x{1F3FB}\x{1F3FD}-\x{1F3FF}]|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|(?:\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{200D}[\x{2695}\x{2696}\x{2708}])\x{FE0F}|\x{200D}(?:[\x{1F468}\x{1F469}]\x{200D}[\x{1F466}\x{1F467}]|[\x{1F466}\x{1F467}])|\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FF}|\x{1F3FE}|\x{1F3FD}|\x{1F3FC}|\x{200D}[\x{2695}\x{2696}\x{2708}])?|(?:\x{1F469}(?:\x{1F3FB}\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}])|\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}]))|[\x{1F3FC}-\x{1F3FF}]\x{200D}\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}])|\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}])))|\x{1F9D1}[\x{1F3FB}-\x{1F3FF}]\x{200D}\x{1F91D}\x{200D}\x{1F9D1})[\x{1F3FB}-\x{1F3FF}]|\x{1F469}\x{200D}\x{1F469}\x{200D}(?:\x{1F466}\x{200D}\x{1F466}|\x{1F467}\x{200D}[\x{1F466}\x{1F467}])|\x{1F469}(?:\x{200D}(?:\x{2764}(?:\x{FE0F}\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}])|\x{200D}(?:\x{1F48B}\x{200D}[\x{1F468}\x{1F469}]|[\x{1F468}\x{1F469}]))|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FF}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FE}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FD}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FC}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FB}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F9D1}(?:\x{200D}(?:\x{1F91D}\x{200D}\x{1F9D1}|[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F3FF}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FE}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FD}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FC}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}]|\x{1F3FB}\x{200D}[\x{1F33E}\x{1F373}\x{1F37C}\x{1F384}\x{1F393}\x{1F3A4}\x{1F3A8}\x{1F3EB}\x{1F3ED}\x{1F4BB}\x{1F4BC}\x{1F527}\x{1F52C}\x{1F680}\x{1F692}\x{1F9AF}-\x{1F9B3}\x{1F9BC}\x{1F9BD}])|\x{1F469}\x{200D}\x{1F466}\x{200D}\x{1F466}|\x{1F469}\x{200D}\x{1F469}\x{200D}[\x{1F466}\x{1F467}]|\x{1F469}\x{200D}\x{1F467}\x{200D}[\x{1F466}\x{1F467}]|(?:\x{1F441}\x{FE0F}?\x{200D}\x{1F5E8}|\x{1F9D1}(?:\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FB}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{200D}[\x{2695}\x{2696}\x{2708}])|\x{1F469}(?:\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FB}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{200D}[\x{2695}\x{2696}\x{2708}])|\x{1F636}\x{200D}\x{1F32B}|\x{1F3F3}\x{FE0F}?\x{200D}\x{26A7}|\x{1F43B}\x{200D}\x{2744}|(?:[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93D}\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}][\x{1F3FB}-\x{1F3FF}]|[\x{1F46F}\x{1F9DE}\x{1F9DF}])\x{200D}[\x{2640}\x{2642}]|[\x{26F9}\x{1F3CB}\x{1F3CC}\x{1F575}](?:[\x{FE0F}\x{1F3FB}-\x{1F3FF}]\x{200D}[\x{2640}\x{2642}]|\x{200D}[\x{2640}\x{2642}])|\x{1F3F4}\x{200D}\x{2620}|[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93C}-\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}]\x{200D}[\x{2640}\x{2642}]|[\xA9\xAE\x{203C}\x{2049}\x{2122}\x{2139}\x{2194}-\x{2199}\x{21A9}\x{21AA}\x{231A}\x{231B}\x{2328}\x{23CF}\x{23ED}-\x{23EF}\x{23F1}\x{23F2}\x{23F8}-\x{23FA}\x{24C2}\x{25AA}\x{25AB}\x{25B6}\x{25C0}\x{25FB}\x{25FC}\x{25FE}\x{2600}-\x{2604}\x{260E}\x{2611}\x{2614}\x{2615}\x{2618}\x{2620}\x{2622}\x{2623}\x{2626}\x{262A}\x{262E}\x{262F}\x{2638}-\x{263A}\x{2640}\x{2642}\x{2648}-\x{2653}\x{265F}\x{2660}\x{2663}\x{2665}\x{2666}\x{2668}\x{267B}\x{267E}\x{267F}\x{2692}\x{2694}-\x{2697}\x{2699}\x{269B}\x{269C}\x{26A0}\x{26A7}\x{26AA}\x{26B0}\x{26B1}\x{26BD}\x{26BE}\x{26C4}\x{26C8}\x{26CF}\x{26D1}\x{26D3}\x{26E9}\x{26F0}-\x{26F5}\x{26F7}\x{26F8}\x{26FA}\x{2702}\x{2708}\x{2709}\x{270F}\x{2712}\x{2714}\x{2716}\x{271D}\x{2721}\x{2733}\x{2734}\x{2744}\x{2747}\x{2757}\x{2763}\x{27A1}\x{2934}\x{2935}\x{2B05}-\x{2B07}\x{2B1B}\x{2B1C}\x{2B55}\x{3030}\x{303D}\x{3297}\x{3299}\x{1F004}\x{1F170}\x{1F171}\x{1F17E}\x{1F17F}\x{1F202}\x{1F237}\x{1F321}\x{1F324}-\x{1F32C}\x{1F336}\x{1F37D}\x{1F396}\x{1F397}\x{1F399}-\x{1F39B}\x{1F39E}\x{1F39F}\x{1F3CD}\x{1F3CE}\x{1F3D4}-\x{1F3DF}\x{1F3F5}\x{1F3F7}\x{1F43F}\x{1F4FD}\x{1F549}\x{1F54A}\x{1F56F}\x{1F570}\x{1F573}\x{1F576}-\x{1F579}\x{1F587}\x{1F58A}-\x{1F58D}\x{1F5A5}\x{1F5A8}\x{1F5B1}\x{1F5B2}\x{1F5BC}\x{1F5C2}-\x{1F5C4}\x{1F5D1}-\x{1F5D3}\x{1F5DC}-\x{1F5DE}\x{1F5E1}\x{1F5E3}\x{1F5E8}\x{1F5EF}\x{1F5F3}\x{1F5FA}\x{1F6CB}\x{1F6CD}-\x{1F6CF}\x{1F6E0}-\x{1F6E5}\x{1F6E9}\x{1F6F0}\x{1F6F3}])\x{FE0F}|\x{1F441}\x{FE0F}?\x{200D}\x{1F5E8}|\x{1F9D1}(?:\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FB}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{200D}[\x{2695}\x{2696}\x{2708}])|\x{1F469}(?:\x{1F3FF}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FE}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FD}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FC}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{1F3FB}\x{200D}[\x{2695}\x{2696}\x{2708}]|\x{200D}[\x{2695}\x{2696}\x{2708}])|\x{1F3F3}\x{FE0F}?\x{200D}\x{1F308}|\x{1F469}\x{200D}\x{1F467}|\x{1F469}\x{200D}\x{1F466}|\x{1F636}\x{200D}\x{1F32B}|\x{1F3F3}\x{FE0F}?\x{200D}\x{26A7}|\x{1F635}\x{200D}\x{1F4AB}|\x{1F62E}\x{200D}\x{1F4A8}|\x{1F415}\x{200D}\x{1F9BA}|\x{1FAF1}(?:\x{1F3FF}|\x{1F3FE}|\x{1F3FD}|\x{1F3FC}|\x{1F3FB})?|\x{1F9D1}(?:\x{1F3FF}|\x{1F3FE}|\x{1F3FD}|\x{1F3FC}|\x{1F3FB})?|\x{1F469}(?:\x{1F3FF}|\x{1F3FE}|\x{1F3FD}|\x{1F3FC}|\x{1F3FB})?|\x{1F43B}\x{200D}\x{2744}|(?:[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93D}\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}][\x{1F3FB}-\x{1F3FF}]|[\x{1F46F}\x{1F9DE}\x{1F9DF}])\x{200D}[\x{2640}\x{2642}]|[\x{26F9}\x{1F3CB}\x{1F3CC}\x{1F575}](?:[\x{FE0F}\x{1F3FB}-\x{1F3FF}]\x{200D}[\x{2640}\x{2642}]|\x{200D}[\x{2640}\x{2642}])|\x{1F3F4}\x{200D}\x{2620}|\x{1F1FD}\x{1F1F0}|\x{1F1F6}\x{1F1E6}|\x{1F1F4}\x{1F1F2}|\x{1F408}\x{200D}\x{2B1B}|\x{2764}(?:\x{FE0F}\x{200D}[\x{1F525}\x{1FA79}]|\x{200D}[\x{1F525}\x{1FA79}])|\x{1F441}\x{FE0F}?|\x{1F3F3}\x{FE0F}?|[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93C}-\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}]\x{200D}[\x{2640}\x{2642}]|\x{1F1FF}[\x{1F1E6}\x{1F1F2}\x{1F1FC}]|\x{1F1FE}[\x{1F1EA}\x{1F1F9}]|\x{1F1FC}[\x{1F1EB}\x{1F1F8}]|\x{1F1FB}[\x{1F1E6}\x{1F1E8}\x{1F1EA}\x{1F1EC}\x{1F1EE}\x{1F1F3}\x{1F1FA}]|\x{1F1FA}[\x{1F1E6}\x{1F1EC}\x{1F1F2}\x{1F1F3}\x{1F1F8}\x{1F1FE}\x{1F1FF}]|\x{1F1F9}[\x{1F1E6}\x{1F1E8}\x{1F1E9}\x{1F1EB}-\x{1F1ED}\x{1F1EF}-\x{1F1F4}\x{1F1F7}\x{1F1F9}\x{1F1FB}\x{1F1FC}\x{1F1FF}]|\x{1F1F8}[\x{1F1E6}-\x{1F1EA}\x{1F1EC}-\x{1F1F4}\x{1F1F7}-\x{1F1F9}\x{1F1FB}\x{1F1FD}-\x{1F1FF}]|\x{1F1F7}[\x{1F1EA}\x{1F1F4}\x{1F1F8}\x{1F1FA}\x{1F1FC}]|\x{1F1F5}[\x{1F1E6}\x{1F1EA}-\x{1F1ED}\x{1F1F0}-\x{1F1F3}\x{1F1F7}-\x{1F1F9}\x{1F1FC}\x{1F1FE}]|\x{1F1F3}[\x{1F1E6}\x{1F1E8}\x{1F1EA}-\x{1F1EC}\x{1F1EE}\x{1F1F1}\x{1F1F4}\x{1F1F5}\x{1F1F7}\x{1F1FA}\x{1F1FF}]|\x{1F1F2}[\x{1F1E6}\x{1F1E8}-\x{1F1ED}\x{1F1F0}-\x{1F1FF}]|\x{1F1F1}[\x{1F1E6}-\x{1F1E8}\x{1F1EE}\x{1F1F0}\x{1F1F7}-\x{1F1FB}\x{1F1FE}]|\x{1F1F0}[\x{1F1EA}\x{1F1EC}-\x{1F1EE}\x{1F1F2}\x{1F1F3}\x{1F1F5}\x{1F1F7}\x{1F1FC}\x{1F1FE}\x{1F1FF}]|\x{1F1EF}[\x{1F1EA}\x{1F1F2}\x{1F1F4}\x{1F1F5}]|\x{1F1EE}[\x{1F1E8}-\x{1F1EA}\x{1F1F1}-\x{1F1F4}\x{1F1F6}-\x{1F1F9}]|\x{1F1ED}[\x{1F1F0}\x{1F1F2}\x{1F1F3}\x{1F1F7}\x{1F1F9}\x{1F1FA}]|\x{1F1EC}[\x{1F1E6}\x{1F1E7}\x{1F1E9}-\x{1F1EE}\x{1F1F1}-\x{1F1F3}\x{1F1F5}-\x{1F1FA}\x{1F1FC}\x{1F1FE}]|\x{1F1EB}[\x{1F1EE}-\x{1F1F0}\x{1F1F2}\x{1F1F4}\x{1F1F7}]|\x{1F1EA}[\x{1F1E6}\x{1F1E8}\x{1F1EA}\x{1F1EC}\x{1F1ED}\x{1F1F7}-\x{1F1FA}]|\x{1F1E9}[\x{1F1EA}\x{1F1EC}\x{1F1EF}\x{1F1F0}\x{1F1F2}\x{1F1F4}\x{1F1FF}]|\x{1F1E8}[\x{1F1E6}\x{1F1E8}\x{1F1E9}\x{1F1EB}-\x{1F1EE}\x{1F1F0}-\x{1F1F5}\x{1F1F7}\x{1F1FA}-\x{1F1FF}]|\x{1F1E7}[\x{1F1E6}\x{1F1E7}\x{1F1E9}-\x{1F1EF}\x{1F1F1}-\x{1F1F4}\x{1F1F6}-\x{1F1F9}\x{1F1FB}\x{1F1FC}\x{1F1FE}\x{1F1FF}]|\x{1F1E6}[\x{1F1E8}-\x{1F1EC}\x{1F1EE}\x{1F1F1}\x{1F1F2}\x{1F1F4}\x{1F1F6}-\x{1F1FA}\x{1F1FC}\x{1F1FD}\x{1F1FF}]|[#\*0-9]\x{FE0F}?\x{20E3}|\x{1F93C}[\x{1F3FB}-\x{1F3FF}]|\x{2764}\x{FE0F}?|[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93D}\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}][\x{1F3FB}-\x{1F3FF}]|[\x{26F9}\x{1F3CB}\x{1F3CC}\x{1F575}][\x{FE0F}\x{1F3FB}-\x{1F3FF}]?|\x{1F3F4}|[\x{270A}\x{270B}\x{1F385}\x{1F3C2}\x{1F3C7}\x{1F442}\x{1F443}\x{1F446}-\x{1F450}\x{1F466}\x{1F467}\x{1F46B}-\x{1F46D}\x{1F472}\x{1F474}-\x{1F476}\x{1F478}\x{1F47C}\x{1F483}\x{1F485}\x{1F48F}\x{1F491}\x{1F4AA}\x{1F57A}\x{1F595}\x{1F596}\x{1F64C}\x{1F64F}\x{1F6C0}\x{1F6CC}\x{1F90C}\x{1F90F}\x{1F918}-\x{1F91F}\x{1F930}-\x{1F934}\x{1F936}\x{1F977}\x{1F9B5}\x{1F9B6}\x{1F9BB}\x{1F9D2}\x{1F9D3}\x{1F9D5}\x{1FAC3}-\x{1FAC5}\x{1FAF0}\x{1FAF2}-\x{1FAF6}][\x{1F3FB}-\x{1F3FF}]|[\x{261D}\x{270C}\x{270D}\x{1F574}\x{1F590}][\x{FE0F}\x{1F3FB}-\x{1F3FF}]|[\x{261D}\x{270A}-\x{270D}\x{1F385}\x{1F3C2}\x{1F3C7}\x{1F408}\x{1F415}\x{1F43B}\x{1F442}\x{1F443}\x{1F446}-\x{1F450}\x{1F466}\x{1F467}\x{1F46B}-\x{1F46D}\x{1F472}\x{1F474}-\x{1F476}\x{1F478}\x{1F47C}\x{1F483}\x{1F485}\x{1F48F}\x{1F491}\x{1F4AA}\x{1F574}\x{1F57A}\x{1F590}\x{1F595}\x{1F596}\x{1F62E}\x{1F635}\x{1F636}\x{1F64C}\x{1F64F}\x{1F6C0}\x{1F6CC}\x{1F90C}\x{1F90F}\x{1F918}-\x{1F91F}\x{1F930}-\x{1F934}\x{1F936}\x{1F93C}\x{1F977}\x{1F9B5}\x{1F9B6}\x{1F9BB}\x{1F9D2}\x{1F9D3}\x{1F9D5}\x{1FAC3}-\x{1FAC5}\x{1FAF0}\x{1FAF2}-\x{1FAF6}]|[\x{1F3C3}\x{1F3C4}\x{1F3CA}\x{1F46E}\x{1F470}\x{1F471}\x{1F473}\x{1F477}\x{1F481}\x{1F482}\x{1F486}\x{1F487}\x{1F645}-\x{1F647}\x{1F64B}\x{1F64D}\x{1F64E}\x{1F6A3}\x{1F6B4}-\x{1F6B6}\x{1F926}\x{1F935}\x{1F937}-\x{1F939}\x{1F93D}\x{1F93E}\x{1F9B8}\x{1F9B9}\x{1F9CD}-\x{1F9CF}\x{1F9D4}\x{1F9D6}-\x{1F9DD}]|[\x{1F46F}\x{1F9DE}\x{1F9DF}]|[\xA9\xAE\x{203C}\x{2049}\x{2122}\x{2139}\x{2194}-\x{2199}\x{21A9}\x{21AA}\x{231A}\x{231B}\x{2328}\x{23CF}\x{23ED}-\x{23EF}\x{23F1}\x{23F2}\x{23F8}-\x{23FA}\x{24C2}\x{25AA}\x{25AB}\x{25B6}\x{25C0}\x{25FB}\x{25FC}\x{25FE}\x{2600}-\x{2604}\x{260E}\x{2611}\x{2614}\x{2615}\x{2618}\x{2620}\x{2622}\x{2623}\x{2626}\x{262A}\x{262E}\x{262F}\x{2638}-\x{263A}\x{2640}\x{2642}\x{2648}-\x{2653}\x{265F}\x{2660}\x{2663}\x{2665}\x{2666}\x{2668}\x{267B}\x{267E}\x{267F}\x{2692}\x{2694}-\x{2697}\x{2699}\x{269B}\x{269C}\x{26A0}\x{26A7}\x{26AA}\x{26B0}\x{26B1}\x{26BD}\x{26BE}\x{26C4}\x{26C8}\x{26CF}\x{26D1}\x{26D3}\x{26E9}\x{26F0}-\x{26F5}\x{26F7}\x{26F8}\x{26FA}\x{2702}\x{2708}\x{2709}\x{270F}\x{2712}\x{2714}\x{2716}\x{271D}\x{2721}\x{2733}\x{2734}\x{2744}\x{2747}\x{2757}\x{2763}\x{27A1}\x{2934}\x{2935}\x{2B05}-\x{2B07}\x{2B1B}\x{2B1C}\x{2B55}\x{3030}\x{303D}\x{3297}\x{3299}\x{1F004}\x{1F170}\x{1F171}\x{1F17E}\x{1F17F}\x{1F202}\x{1F237}\x{1F321}\x{1F324}-\x{1F32C}\x{1F336}\x{1F37D}\x{1F396}\x{1F397}\x{1F399}-\x{1F39B}\x{1F39E}\x{1F39F}\x{1F3CD}\x{1F3CE}\x{1F3D4}-\x{1F3DF}\x{1F3F5}\x{1F3F7}\x{1F43F}\x{1F4FD}\x{1F549}\x{1F54A}\x{1F56F}\x{1F570}\x{1F573}\x{1F576}-\x{1F579}\x{1F587}\x{1F58A}-\x{1F58D}\x{1F5A5}\x{1F5A8}\x{1F5B1}\x{1F5B2}\x{1F5BC}\x{1F5C2}-\x{1F5C4}\x{1F5D1}-\x{1F5D3}\x{1F5DC}-\x{1F5DE}\x{1F5E1}\x{1F5E3}\x{1F5E8}\x{1F5EF}\x{1F5F3}\x{1F5FA}\x{1F6CB}\x{1F6CD}-\x{1F6CF}\x{1F6E0}-\x{1F6E5}\x{1F6E9}\x{1F6F0}\x{1F6F3}]|[\x{23E9}-\x{23EC}\x{23F0}\x{23F3}\x{25FD}\x{2693}\x{26A1}\x{26AB}\x{26C5}\x{26CE}\x{26D4}\x{26EA}\x{26FD}\x{2705}\x{2728}\x{274C}\x{274E}\x{2753}-\x{2755}\x{2795}-\x{2797}\x{27B0}\x{27BF}\x{2B50}\x{1F0CF}\x{1F18E}\x{1F191}-\x{1F19A}\x{1F201}\x{1F21A}\x{1F22F}\x{1F232}-\x{1F236}\x{1F238}-\x{1F23A}\x{1F250}\x{1F251}\x{1F300}-\x{1F320}\x{1F32D}-\x{1F335}\x{1F337}-\x{1F37C}\x{1F37E}-\x{1F384}\x{1F386}-\x{1F393}\x{1F3A0}-\x{1F3C1}\x{1F3C5}\x{1F3C6}\x{1F3C8}\x{1F3C9}\x{1F3CF}-\x{1F3D3}\x{1F3E0}-\x{1F3F0}\x{1F3F8}-\x{1F407}\x{1F409}-\x{1F414}\x{1F416}-\x{1F43A}\x{1F43C}-\x{1F43E}\x{1F440}\x{1F444}\x{1F445}\x{1F451}-\x{1F465}\x{1F46A}\x{1F479}-\x{1F47B}\x{1F47D}-\x{1F480}\x{1F484}\x{1F488}-\x{1F48E}\x{1F490}\x{1F492}-\x{1F4A9}\x{1F4AB}-\x{1F4FC}\x{1F4FF}-\x{1F53D}\x{1F54B}-\x{1F54E}\x{1F550}-\x{1F567}\x{1F5A4}\x{1F5FB}-\x{1F62D}\x{1F62F}-\x{1F634}\x{1F637}-\x{1F644}\x{1F648}-\x{1F64A}\x{1F680}-\x{1F6A2}\x{1F6A4}-\x{1F6B3}\x{1F6B7}-\x{1F6BF}\x{1F6C1}-\x{1F6C5}\x{1F6D0}-\x{1F6D2}\x{1F6D5}-\x{1F6D7}\x{1F6DD}-\x{1F6DF}\x{1F6EB}\x{1F6EC}\x{1F6F4}-\x{1F6FC}\x{1F7E0}-\x{1F7EB}\x{1F7F0}\x{1F90D}\x{1F90E}\x{1F910}-\x{1F917}\x{1F920}-\x{1F925}\x{1F927}-\x{1F92F}\x{1F93A}\x{1F93F}-\x{1F945}\x{1F947}-\x{1F976}\x{1F978}-\x{1F9B4}\x{1F9B7}\x{1F9BA}\x{1F9BC}-\x{1F9CC}\x{1F9D0}\x{1F9E0}-\x{1F9FF}\x{1FA70}-\x{1FA74}\x{1FA78}-\x{1FA7C}\x{1FA80}-\x{1FA86}\x{1FA90}-\x{1FAAC}\x{1FAB0}-\x{1FABA}\x{1FAC0}-\x{1FAC2}\x{1FAD0}-\x{1FAD9}\x{1FAE0}-\x{1FAE7}]""" -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/network/component/getComponentTypeArgument.kt b/mirai-core/src/nativeMain/kotlin/network/component/getComponentTypeArgument.kt deleted file mode 100644 index 82435478a..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/component/getComponentTypeArgument.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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.internal.network.component - -import kotlin.reflect.KTypeProjection - -internal actual fun ComponentKey<*>.getComponentTypeArgument(): KTypeProjection? = null \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/network/handler/LengthDelimitedPacketReader.kt b/mirai-core/src/nativeMain/kotlin/network/handler/LengthDelimitedPacketReader.kt deleted file mode 100644 index cc7c854c3..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/handler/LengthDelimitedPacketReader.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.internal.network.handler - -import io.ktor.utils.io.core.* -import net.mamoe.mirai.utils.* -import net.mamoe.mirai.utils.Closeable - -private val debugLogger: MiraiLogger by lazy { - MiraiLogger.Factory.create( - LengthDelimitedPacketReader::class, "LengthDelimitedPacketReader" - ).withSwitch(systemProp("mirai.network.handler.length.delimited.packet.reader.debug", false)) -} - -/** - * Not thread-safe - */ -internal class LengthDelimitedPacketReader( - private val sendDecode: (combined: ByteReadPacket) -> Unit -) : Closeable { - private var missingLength: Long = 0 - set(value) { - field = value - debugLogger.info { "missingLength = $field" } - } - private val bufferedParts: MutableList = ArrayList(10) - - @TestOnly - fun getMissingLength() = missingLength - - @TestOnly - fun getBufferedPackets() = bufferedParts.toList() - - fun offer(packet: ByteReadPacket) { - if (missingLength == 0L) { - // initial - debugLogger.info { "initial length == 0" } - missingLength = packet.readInt().toLongUnsigned() - 4 - } - debugLogger.info { "Offering packet len = ${packet.remaining}" } - missingLength -= packet.remaining - bufferedParts.add(packet) - if (missingLength <= 0) { - emit() - } - } - - private fun emit() { - debugLogger.info { "Emitting, buffered = ${bufferedParts.map { it.remaining }}" } - when (bufferedParts.size) { - 0 -> {} - 1 -> { - val part = bufferedParts.first() - if (missingLength == 0L) { - debugLogger.info { "Single packet length perfectly matched." } - sendDecode(part) - - bufferedParts.clear() - } else { - check(missingLength < 0L) { "Failed check: remainingLength < 0L" } - - val previousPacketLength = missingLength + part.remaining - debugLogger.info { "Got extra packets, previousPacketLength = $previousPacketLength" } - sendDecode(part.readPacketExact(previousPacketLength.toInt())) - - bufferedParts.clear() - - // now packet contain new part. - missingLength = part.readInt().toLongUnsigned() - 4 - offer(part) - } - } - else -> { - if (missingLength == 0L) { - debugLogger.info { "Multiple packets length perfectly matched." } - sendDecode(buildPacket { - bufferedParts.forEach { writePacket(it) } - }) - - bufferedParts.clear() - } else { - val lastPart = bufferedParts.last() - val previousPacketPartLength = missingLength + lastPart.remaining - debugLogger.debug { "previousPacketPartLength = $previousPacketPartLength" } - val combinedLength = - (bufferedParts.sumOf { it.remaining } - lastPart.remaining // buffered length without last part - + previousPacketPartLength).toInt() - debugLogger.debug { "combinedLength = $combinedLength" } - - if (combinedLength < 0) return // not enough, still more parts missing. - - sendDecode(buildPacket { - repeat(bufferedParts.size - 1) { i -> - writePacket(bufferedParts[i]) - } - writePacket(lastPart, previousPacketPartLength) - }) - - bufferedParts.clear() - - // now packet contain new part. - missingLength = lastPart.readInt().toLongUnsigned() - 4 - offer(lastPart) - } - - } - } - } - - override fun close() { - bufferedParts.forEach { it.close() } - } -} diff --git a/mirai-core/src/nativeMain/kotlin/network/handler/NativeNetworkHandler.kt b/mirai-core/src/nativeMain/kotlin/network/handler/NativeNetworkHandler.kt deleted file mode 100644 index 599d40711..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/handler/NativeNetworkHandler.kt +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.internal.network.handler - -import io.ktor.utils.io.* -import io.ktor.utils.io.core.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.cancel -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.channels.onFailure -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import net.mamoe.mirai.internal.network.components.PacketCodec -import net.mamoe.mirai.internal.network.components.SsoProcessor -import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket -import net.mamoe.mirai.internal.utils.PlatformSocket -import net.mamoe.mirai.internal.utils.connect -import net.mamoe.mirai.utils.childScope -import net.mamoe.mirai.utils.info - -internal class NativeNetworkHandler( - context: NetworkHandlerContext, - address: SocketAddress -) : CommonNetworkHandler(context, address) { - internal object Factory : NetworkHandlerFactory { - override fun create(context: NetworkHandlerContext, address: SocketAddress): NativeNetworkHandler { - return NativeNetworkHandler(context, address) - } - } - - internal inner class NativeConn( - private val socket: PlatformSocket, - ) : Closeable, CoroutineScope by coroutineContext.childScope("NativeConn") { - private val decodePipeline: PacketDecodePipeline = PacketDecodePipeline(this.coroutineContext) - - private val packetCodec: PacketCodec by lazy { context[PacketCodec] } - private val ssoProcessor: SsoProcessor by lazy { context[SsoProcessor] } - - private val sendQueue: Channel = Channel(Channel.BUFFERED) { undelivered -> - launch { write(undelivered) } - } - - private val lengthDelimitedPacketReader = LengthDelimitedPacketReader(decodePipeline::send) - - init { - launch { - while (isActive) { - val result = sendQueue.receiveCatching() - logger.info { "Native sender: $result" } - result.onFailure { if (it is CancellationException) return@launch } - - result.getOrNull()?.let { packet -> - try { - socket.send(packet.delegate, 0, packet.delegate.size) - } catch (e: Throwable) { - if (e is CancellationException) return@launch - logger.error("Error while sending packet '${packet.commandName}'", e) - } - } - } - } - - launch { - while (isActive) { - try { - val packet = socket.read() - - lengthDelimitedPacketReader.offer(packet) - } catch (e: Throwable) { - if (e is CancellationException) return@launch - logger.error("Error while reading packet.", e) - setState { StateClosed(e) } - } - } - } - } - - fun write(packet: OutgoingPacket) { - sendQueue.trySend(packet).onFailure { - throw it - ?: throw IllegalStateException("Internal error: Failed to send packet '${packet.commandName}' without reason.") - } - } - - override fun close() { - cancel() - sendQueue.close() - } - } - - override suspend fun createConnection(): NativeConn { - logger.info { "Connecting to $address" } - return NativeConn(PlatformSocket.connect(address)).also { - logger.info { "Connected to server $address" } - } - } - - @Suppress("EXTENSION_SHADOWED_BY_MEMBER") - override fun NativeConn.close() { - this.close() - } - - override fun NativeConn.writeAndFlushOrCloseAsync(packet: OutgoingPacket) { - write(packet) - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/network/handler/NetworkHandlerFactory.kt b/mirai-core/src/nativeMain/kotlin/network/handler/NetworkHandlerFactory.kt deleted file mode 100644 index 4eb675111..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/handler/NetworkHandlerFactory.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.internal.network.handler - -/** - * Factory for a specific [NetworkHandler] implementation. - */ -internal actual fun interface NetworkHandlerFactory { - actual fun create( - context: NetworkHandlerContext, - host: String, - port: Int - ): H = create(context, SocketAddressImpl(host, port)) - - /** - * Create an instance of [H]. The returning [H] has [NetworkHandler.state] of [State.INITIALIZED] - */ - actual fun create( - context: NetworkHandlerContext, - address: SocketAddress - ): H - - actual companion object { - actual fun getPlatformDefault(): NetworkHandlerFactory<*> = NativeNetworkHandler.Factory - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/network/handler/SocketAddress.kt b/mirai-core/src/nativeMain/kotlin/network/handler/SocketAddress.kt deleted file mode 100644 index 2baca8668..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/handler/SocketAddress.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.internal.network.handler - -internal actual abstract class SocketAddress( - val host: String, - val port: Int, - @Suppress("UNUSED_PARAMETER") constructorMarker: Unit?, // avoid ambiguity with function SocketAddress -) - -internal actual fun SocketAddress.getHost(): String = host -internal actual fun SocketAddress.getPort(): Int = port - - -internal class SocketAddressImpl(host: String, port: Int) : SocketAddress(host, port, null) { - override fun toString(): String { - return "$host:$port" - } -} - -internal actual fun createSocketAddress(host: String, port: Int): SocketAddress { - return SocketAddressImpl(host, port) -} - diff --git a/mirai-core/src/nativeMain/kotlin/network/handler/selector/SelectorRequireReconnectException.kt b/mirai-core/src/nativeMain/kotlin/network/handler/selector/SelectorRequireReconnectException.kt deleted file mode 100644 index 040bd49dc..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/handler/selector/SelectorRequireReconnectException.kt +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.network.handler.selector - -internal actual class SelectorRequireReconnectException : NetworkException(true) diff --git a/mirai-core/src/nativeMain/kotlin/network/protocol/data/richstatus/parseRichStatusImpl.kt b/mirai-core/src/nativeMain/kotlin/network/protocol/data/richstatus/parseRichStatusImpl.kt deleted file mode 100644 index 632bbcc95..000000000 --- a/mirai-core/src/nativeMain/kotlin/network/protocol/data/richstatus/parseRichStatusImpl.kt +++ /dev/null @@ -1,14 +0,0 @@ -/* - * 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.internal.network.protocol.data.richstatus - -internal actual fun parseRichStatusImpl(rawData: ByteArray?): RichStatus { - return RichStatus() -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/package.kt b/mirai-core/src/nativeMain/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/nativeMain/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/PlatformSocket.kt b/mirai-core/src/nativeMain/kotlin/utils/PlatformSocket.kt deleted file mode 100644 index e32e0fbb9..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/PlatformSocket.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.internal.utils - -import io.ktor.utils.io.errors.* - -internal actual class SocketException : IOException { - actual constructor() : super("", null) - - actual constructor(message: String) : super(message) -} - -internal actual class NoRouteToHostException : IOException { - actual constructor() : super("") - actual constructor(message: String) : super(message) -} - -internal actual class UnknownHostException : IOException { - actual constructor() : super("") - actual constructor(message: String) : super(message) -} diff --git a/mirai-core/src/nativeMain/kotlin/utils/crypto/AESNative.kt b/mirai-core/src/nativeMain/kotlin/utils/crypto/AESNative.kt deleted file mode 100644 index b9b52d465..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/crypto/AESNative.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils.crypto - -import kotlinx.cinterop.* -import net.mamoe.mirai.internal.utils.free -import net.mamoe.mirai.internal.utils.getOpenSSLError -import openssl.* - -private val aes256CBC by lazy { EVP_aes_256_cbc() } - -internal actual fun aesEncrypt(input: ByteArray, iv: ByteArray, key: ByteArray): ByteArray { - return doAES(input, iv, key, true) -} - -internal actual fun aesDecrypt(input: ByteArray, iv: ByteArray, key: ByteArray): ByteArray { - return doAES(input, iv, key, false) -} - -/** - * reference: - * - https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption - */ -private fun doAES(input: ByteArray, iv: ByteArray, key: ByteArray, doEncrypt: Boolean): ByteArray { - memScoped { - val evpCipherCtx = EVP_CIPHER_CTX_new() ?: error("Failed to create evp cipher context: ${getOpenSSLError()}") - - val pinnedKey = key.pin() - val pinnedIv = iv.pin() - val pinnedInput = input.pin() - - if (1 != EVP_CipherInit( - ctx = evpCipherCtx, - cipher = aes256CBC, - key = pinnedKey.addressOf(0).reinterpret(), - iv = pinnedIv.addressOf(0).reinterpret(), - enc = if (doEncrypt) 1 else 0 - ) - ) { - pinnedKey.unpin() - pinnedIv.unpin() - pinnedInput.unpin() - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to init aes-256-cbc cipher: ${getOpenSSLError()}") - } - - pinnedKey.unpin() - pinnedIv.unpin() - - val blockSize = _evpCipherCtxGetBlockSize(evpCipherCtx) - val cipherBufferSize = pinnedInput.get().size + blockSize - (pinnedInput.get().size % blockSize) - val pinnedCipherBuffer = ByteArray(cipherBufferSize.convert()).pin() - - - val tempLen = alloc() - val cipherSize = alloc() - - if (1 != EVP_CipherUpdate( - ctx = evpCipherCtx, - out = pinnedCipherBuffer.addressOf(0).reinterpret(), - outl = tempLen.ptr, - `in` = pinnedInput.addressOf(0).reinterpret(), - inl = pinnedInput.get().size.convert() - ) - ) { - pinnedInput.unpin() - pinnedCipherBuffer.unpin() - free(tempLen.ptr, cipherSize.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed do aes-256-cbc cipher update: ${getOpenSSLError()}") - } - cipherSize.value = tempLen.value - - if (1 != EVP_CipherFinal( - ctx = evpCipherCtx, - outm = pinnedCipherBuffer.addressOf(tempLen.value).reinterpret(), - outl = tempLen.ptr - ) - ) { - pinnedInput.unpin() - pinnedCipherBuffer.unpin() - free(tempLen.ptr, cipherSize.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed do aes-256-cbc cipher final: ${getOpenSSLError()}") - } - cipherSize.value += tempLen.value - - return pinnedCipherBuffer.get().copyOf(cipherSize.value).also { - pinnedInput.unpin() - pinnedCipherBuffer.unpin() - EVP_CIPHER_CTX_free(evpCipherCtx) - } - } -} diff --git a/mirai-core/src/nativeMain/kotlin/utils/crypto/EcdhNative.kt b/mirai-core/src/nativeMain/kotlin/utils/crypto/EcdhNative.kt deleted file mode 100644 index 84c6c1bc7..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/crypto/EcdhNative.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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.internal.utils.crypto - - -internal actual fun Ecdh.Companion.create(): Ecdh<*, *> = OpenSslEcdh() \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/crypto/OpenSslEcdh.kt b/mirai-core/src/nativeMain/kotlin/utils/crypto/OpenSslEcdh.kt deleted file mode 100644 index 9802129f8..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/crypto/OpenSslEcdh.kt +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.internal.utils.crypto - -import kotlinx.cinterop.* -import openssl.* -import platform.posix.errno -import kotlin.native.internal.createCleaner - -private const val curveId = NID_X9_62_prime256v1 -private val group by lazy { EC_GROUP_new_by_curve_name(curveId) ?: error("Failed to get EC_GROUP") } -private val convForm by lazy { EC_GROUP_get_point_conversion_form(group) } -private val bnCtx by lazy { BN_CTX_new() } - - -internal class OpenSslECPublicKey private constructor(val point: CPointer) { - @Suppress("unused") - @OptIn(ExperimentalStdlibApi::class) - private val cleaner = createCleaner(point) { - EC_POINT_free(it) - } - - fun export(): ByteArray { - val len = EC_POINT_point2oct(group, point, convForm, null, 0, null) - val bytes = ByteArray(len.convert()) - bytes.usePinned { - EC_POINT_point2oct(group, point, convForm, it.addressOf(0).reinterpret(), len, bnCtx) - } - return bytes - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - return (other as? OpenSslECPublicKey)?.let { - EC_POINT_cmp(group, point, it.point, bnCtx) == 0 - } ?: false - } - - override fun hashCode(): Int { - return export().hashCode() - } - - companion object { - fun copyFrom(source: CPointer): OpenSslECPublicKey { - return OpenSslECPublicKey(EC_POINT_dup(source, group) ?: error("Failed to dup a EC_POINT")) - } - - fun import(encoded: ByteArray): OpenSslECPublicKey { - val point = EC_POINT_new(group) ?: error("Failed to create EC_POINT") - encoded.usePinned { - EC_POINT_oct2point(group, point, it.addressOf(0).reinterpret(), it.get().size.convert(), bnCtx) - } - return OpenSslECPublicKey(point) - } - } -} - -internal class OpenSslECPrivateKey private constructor(val bn: CPointer) { - @Suppress("unused") - @OptIn(ExperimentalStdlibApi::class) - private val cleaner = createCleaner(bn) { - BN_free(it) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - return (other as? OpenSslECPrivateKey)?.let { - BN_cmp(bn, other.bn) == 0 - } ?: false - } - - fun export(): ByteArray { - val len = (BN_num_bits(bn)+7)/8 - val bytes = ByteArray(len) - bytes.usePinned { - BN_bn2bin(bn, it.addressOf(0).reinterpret()) - } - return bytes - } - - override fun hashCode(): Int { - return export().hashCode() - } - - companion object { - fun copyFrom(source: CPointer): OpenSslECPrivateKey { - return OpenSslECPrivateKey(BN_dup(source) ?: error("Failed to dup a BIGNUM")) - } - } -} - -internal class OpenSslEcdh : Ecdh { - override fun generateKeyPair(): EcdhKeyPair { - val key: CPointer = EC_KEY_new_by_curve_name(curveId) - ?: throw IllegalStateException("Failed to create key curve, $errno") - try { - if (1 != EC_KEY_generate_key(key)) { - throw IllegalStateException("Failed to generate key, $errno") - } - val public = - OpenSslECPublicKey.copyFrom(EC_KEY_get0_public_key(key) ?: error("Failed EC_key_get0_public_key")) - val private = - OpenSslECPrivateKey.copyFrom(EC_KEY_get0_private_key(key) ?: error("Failed EC_KEY_get0_private_key")) - return EcdhKeyPair(public, private) - } finally { - EC_KEY_free(key) - } - } - - override fun calculateShareKey(peerKey: OpenSslECPublicKey, privateKey: OpenSslECPrivateKey): ByteArray { - val k = EC_KEY_new_by_curve_name(curveId) ?: error("Failed to create EC key") - try { - EC_KEY_set_private_key(k, privateKey.bn).let { r -> - if (r != 1) error("Failed EC_KEY_set_private_key: $r") - } - val fieldSize = EC_GROUP_get_degree(group) - if (fieldSize <= 0) { - error("Failed EC_GROUP_get_degree: $fieldSize") - } - var secretLen = (fieldSize + 7) / 8 - ByteArray(secretLen.convert()).usePinned { pin -> - secretLen = ECDH_compute_key(pin.addressOf(0), secretLen.convert(), peerKey.point, k, null) - if (secretLen <= 0) { - error("Failed to compute secret") - } - return pin.get().copyOf(secretLen) - } - } finally { - EC_KEY_free(k) - } - } - - override fun importPublicKey(encoded: ByteArray): OpenSslECPublicKey { - return OpenSslECPublicKey.import(encoded) - } - - override fun exportPublicKey(key: OpenSslECPublicKey): ByteArray { - return key.export() - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/crypto/QQEcdhNative.kt b/mirai-core/src/nativeMain/kotlin/utils/crypto/QQEcdhNative.kt deleted file mode 100644 index 750612f23..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/crypto/QQEcdhNative.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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.internal.utils.crypto - -internal actual fun QQEcdhInitialPublicKey.verify(sign: String): Boolean { - // FIXME - return true -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/crypto/RSANative.kt b/mirai-core/src/nativeMain/kotlin/utils/crypto/RSANative.kt deleted file mode 100644 index 10568dbfc..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/crypto/RSANative.kt +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils.crypto - -import kotlinx.cinterop.* -import net.mamoe.mirai.internal.utils.getOpenSSLError -import net.mamoe.mirai.internal.utils.ref -import openssl.* - -/** - * reference: - * - https://stackoverflow.com/questions/70535625/openssl-rsa-encryption-decryption-with-evp-methods - * - https://www.openssl.org/docs/man3.1/man3/ - */ - -/** - * Generate RSA key pair with size of [keySize]. - * The public key pair is encoded with x.509, and the private key pair is encoded with PKCS8 - */ -internal actual fun generateRSAKeyPair(keySize: Int): RSAKeyPair { - memScoped { - val evpPkeyCtx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, null) - ?: error("Failed to create evp pkey context: ${getOpenSSLError()}") - - if (EVP_PKEY_keygen_init(evpPkeyCtx) <= 0) { - error("Failed to init evp pkey context: ${getOpenSSLError()}") - } - - // libcrypto 3 move EVP_PKEY_CTX_set_rsa_keygen_bits from macro to function - if (_evpPkeyCtxSetRSAKeygenBits(evpPkeyCtx, keySize) <= 0) { - EVP_PKEY_CTX_free(evpPkeyCtx) - error("Failed to set key bit for rsa evp pkey: ${getOpenSSLError()}") - } - - val evpPKey = EVP_PKEY_new() ?: kotlin.run { - EVP_PKEY_CTX_free(evpPkeyCtx) - error("Failed to create evp pkey: ${getOpenSSLError()}") - } - - if (EVP_PKEY_keygen(evpPkeyCtx, ref(evpPKey)) <= 0) { - EVP_PKEY_free(evpPKey) - EVP_PKEY_CTX_free(evpPkeyCtx) - error("Failed to generate rsa key pair: ${getOpenSSLError()}") - } - - val publicPemKey = dumpPKey(evpPKey) { b, k -> PEM_write_bio_PUBKEY(b, k) } - ?: kotlin.run { - EVP_PKEY_free(evpPKey) - EVP_PKEY_CTX_free(evpPkeyCtx) - error("Failed to dump rsa public key: ${getOpenSSLError()}") - } - val privatePemKey = dumpPKey(evpPKey) { b, k -> - PEM_write_bio_PKCS8PrivateKey(b, k, null, null, 0, null, null) - } ?: kotlin.run { - EVP_PKEY_free(evpPKey) - EVP_PKEY_CTX_free(evpPkeyCtx) - error("Failed to dump rsa public key: ${getOpenSSLError()}") - } - - EVP_PKEY_free(evpPKey) - EVP_PKEY_CTX_free(evpPkeyCtx) - - return RSAKeyPair(publicPemKey, privatePemKey) - } -} - -@OptIn(UnsafeNumber::class) -private inline fun MemScope.dumpPKey( - evpPKey: CPointer, - dumper: (CPointer, CPointer) -> Unit -): String? { - val bio = BIO_new(BIO_s_mem()) ?: error("Failed to init mem BIO: ${getOpenSSLError()}") - - dumper(bio, evpPKey) - BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, null) - - val pKeyBuf = allocPointerTo() - BIO_ctrl(bio, BIO_CTRL_INFO, 0, pKeyBuf.ptr) - - return pKeyBuf.value?.toKString().also { BIO_free(bio) } -} - -private fun MemScope.loadPKey( - plainPemKey: String, - reader: (CPointer) -> CPointer? -): CPointer? { - val bio = BIO_new(BIO_s_mem()) ?: error("Failed to init mem BIO: ${getOpenSSLError()}") - - return plainPemKey.encodeToByteArray().usePinned { - BIO_write(bio, it.addressOf(0), it.get().size) - reader(bio) - } -} - -internal actual fun rsaEncryptWithX509PubKey(input: ByteArray, plainPubPemKey: String, seed: Long): ByteArray { - memScoped { - val pubPKey = loadPKey(plainPubPemKey) { - PEM_read_bio_RSA_PUBKEY(it, null, null, null) - } ?: error("Failed to read pem key from BIO: ${getOpenSSLError()}") - - val pinnedInput = input.pin() - val encMsg = ByteArray(4096).pin() - - val encMsgLen = RSA_public_encrypt( - flen = pinnedInput.get().size, - from = pinnedInput.addressOf(0).reinterpret(), - to = encMsg.addressOf(0).reinterpret(), - rsa = pubPKey, - padding = RSA_PKCS1_PADDING - ) - if (encMsgLen <= 0) { - pinnedInput.unpin() - encMsg.unpin() - RSA_free(pubPKey) - error("Failed to do rsa decrypt: ${getOpenSSLError()}") - } - - return encMsg.get().copyOf(encMsgLen).also { - pinnedInput.unpin() - encMsg.unpin() - RSA_free(pubPKey) - } - - /*if (1 != EVP_SealInit( - ctx = evpCipherCtx, - type = aes256CBC, - ek = encKey.ptr, - ekl = encKeyLen.ptr, - pubk = ref(pubPKey), - iv = iv.ptr, - npubk = 1, - ) - ) { - free(encKey.ptr, encKeyLen.ptr, iv.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to init evp seal: ${getOpenSSLError()}") - } - println("total size: ${pinnedInput.get().size + 1 + EVP_MAX_IV_LENGTH}") - val encMsgLen = alloc().apply { value = 0u } - val blockSize = alloc().apply { value = 0u } - - if (1 != EVP_EncryptUpdate( - ctx = evpCipherCtx, - out = encMsg.addressOf(encMsgLen.value.convert()).reinterpret(), - outl = blockSize.ptr.reinterpret(), - `in` = pinnedInput.addressOf(0).reinterpret(), - inl = pinnedInput.get().size - ) - ) { - pinnedInput.unpin() - encMsg.unpin() - free(encMsgLen.ptr, blockSize.ptr, encKey.ptr, encKeyLen.ptr, iv.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to update evp seal: ${getOpenSSLError()}") - } - println("${encMsgLen.value}, ${blockSize.value}") - encMsgLen.value += blockSize.value - println("${encMsg.addressOf(0)}, ${encMsg.addressOf(encMsgLen.value.convert())}") - - if (1 != EVP_SealFinal( - ctx = evpCipherCtx, - out = encMsg.addressOf(encMsgLen.value.convert()).reinterpret(), - outl = blockSize.ptr.reinterpret() - ) - ) { - pinnedInput.unpin() - encMsg.unpin() - free(encMsgLen.ptr, blockSize.ptr, encKey.ptr, encKeyLen.ptr, iv.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to do final evp seal: ${getOpenSSLError()}") - } - println("${encMsgLen.value}, ${blockSize.value}") - encMsgLen.value += blockSize.value - - return encMsg.get().copyOf(encMsgLen.value.convert()).also { - encMsg.unpin() - pinnedInput.unpin() - EVP_CIPHER_CTX_free(evpCipherCtx) - }.toByteArray()*/ - } -} - -internal actual fun rsaDecryptWithPKCS8PrivKey(input: ByteArray, plainPrivPemKey: String, seed: Long): ByteArray { - memScoped { - val evpCipherCtx = EVP_CIPHER_CTX_new() - ?: error("Failed to create evp cipher context: ${getOpenSSLError()}") - - val privKey = loadPKey(plainPrivPemKey) { - PEM_read_bio_RSAPrivateKey(it, null, null, null) - } ?: kotlin.run { - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to read pem key from BIO: ${getOpenSSLError()}") - } - - val pinnedInput = input.pin() - val encMsg = UByteArray(4096).pin() - - val encMsgLen = RSA_private_decrypt( - flen = pinnedInput.get().size, - from = pinnedInput.addressOf(0).reinterpret(), - to = encMsg.addressOf(0).reinterpret(), - rsa = privKey, - padding = RSA_PKCS1_PADDING - ) - if (encMsgLen <= 0) { - pinnedInput.unpin() - encMsg.unpin() - RSA_free(privKey) - error("Failed to do rsa decrypt: ${getOpenSSLError()}") - } - - return encMsg.get().copyOf(encMsgLen).toByteArray().also { - pinnedInput.unpin() - encMsg.unpin() - RSA_free(privKey) - } - - /*println(dumpPKey(privKey) { b, k -> PEM_write_bio_PKCS8PrivateKey(b, k, null, null, 0, null, null) }) - - val decKeyLen = EVP_PKEY_get_size(privKey) - println("evp_pkey_size: $decKeyLen") - val decKey = ByteArray(decKeyLen).pin() - val pinnedIv = ByteArray(16).pin() - - if (1 != EVP_OpenInit( - ctx = evpCipherCtx, - type = aes256CBC, - ek = decKey.addressOf(0).reinterpret(), - ekl = decKeyLen, - iv = pinnedIv.addressOf(0).reinterpret(), - priv = privKey - ) - ) { - pinnedIv.unpin() - decKey.unpin() - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to init evp open: ${getOpenSSLError()}") - } - println("init") - - val pinnedInput = input.pin() - val decMsg = ByteArray( - pinnedInput.get().size + EVP_CIPHER_CTX_get_block_size(evpCipherCtx) - ).pin() - val decMsgLen = alloc().apply { value = 0u } - val blockSize = alloc().apply { value = 0u } - - if (1 != EVP_DecryptUpdate( - ctx = evpCipherCtx, - out = decMsg.addressOf(0).reinterpret(), - outl = blockSize.ptr.reinterpret(), - `in` = pinnedInput.addressOf(0).reinterpret(), - inl = pinnedInput.get().size - ) - ) { - pinnedInput.unpin() - decMsg.unpin() - pinnedIv.unpin() - decKey.unpin() - free(decMsgLen.ptr, blockSize.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to update evp open: ${getOpenSSLError()}") - } - decMsgLen.value += blockSize.value - println("update") - - if (1 != EVP_OpenFinal( - ctx = evpCipherCtx, - out = decMsg.addressOf(decMsgLen.value.convert()).reinterpret(), - outl = blockSize.ptr.reinterpret() - ) - ) { - pinnedInput.unpin() - decMsg.unpin() - pinnedIv.unpin() - decKey.unpin() - free(decMsgLen.ptr, blockSize.ptr) - EVP_CIPHER_CTX_free(evpCipherCtx) - error("Failed to do final evp open: ${getOpenSSLError()}") - } - decMsgLen.value += blockSize.value - println("final") - - return decMsg.get().copyOf(decMsgLen.value.convert()).also { - decMsg.unpin() - pinnedInput.unpin() - pinnedIv.unpin() - decKey.unpin() - EVP_CIPHER_CTX_free(evpCipherCtx) - }*/ - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/freePointer.kt b/mirai-core/src/nativeMain/kotlin/utils/freePointer.kt deleted file mode 100644 index ce78b70b9..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/freePointer.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils - -import kotlinx.cinterop.CValuesRef -import platform.posix.free - -internal fun free( - vararg refs: CValuesRef<*> -) { - refs.forEach(::free) -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/getOpenSSLError.kt b/mirai-core/src/nativeMain/kotlin/utils/getOpenSSLError.kt deleted file mode 100644 index d129d52b1..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/getOpenSSLError.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils - -import kotlinx.cinterop.* -import openssl.* - -@OptIn(UnsafeNumber::class) -internal fun getOpenSSLError(): String { - memScoped { - val bio = BIO_new(BIO_s_mem()) - val errBuffer = allocPointerTo() - - ERR_print_errors(bio) - BIO_ctrl(bio, BIO_CTRL_FLUSH, 0, null) - BIO_ctrl(bio, BIO_CTRL_INFO, 0, errBuffer.ptr) - - return errBuffer.value?.toKString()?.also { BIO_free(bio) } ?: "openssl error: no message" - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/ref.kt b/mirai-core/src/nativeMain/kotlin/utils/ref.kt deleted file mode 100644 index b774b17c1..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/ref.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.utils - -import kotlinx.cinterop.* - -/** - * returns reference to a pointer(**variable), equivalent to `my_type **a = &myTypePtr` - */ -internal inline fun NativePlacement.ref(ptr: CPointer): CPointer> { - return allocPointerTo().apply { value = ptr }.ptr -} \ No newline at end of file diff --git a/mirai-core/src/nativeMain/kotlin/utils/workingDirPath.kt b/mirai-core/src/nativeMain/kotlin/utils/workingDirPath.kt deleted file mode 100644 index 9ee23ec19..000000000 --- a/mirai-core/src/nativeMain/kotlin/utils/workingDirPath.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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.internal.utils - -import net.mamoe.mirai.utils.BotConfiguration - -internal actual val BotConfiguration.workingDirPath: String - get() = this.workingDir -internal actual val BotConfiguration.cacheDirPath: String - get() = this.cacheDir \ No newline at end of file diff --git a/mirai-core/src/nativeTest/.gitignore b/mirai-core/src/nativeTest/.gitignore deleted file mode 100644 index bcedc2a03..000000000 --- a/mirai-core/src/nativeTest/.gitignore +++ /dev/null @@ -1 +0,0 @@ -kotlin/local \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/local/README.md b/mirai-core/src/nativeTest/kotlin/local/README.md deleted file mode 100644 index bc144fe45..000000000 --- a/mirai-core/src/nativeTest/kotlin/local/README.md +++ /dev/null @@ -1,8 +0,0 @@ -### Native local test - -这里可以在 Native 启动自定义 main 入口. 使用方法: - -- 复制 `TestMain.kt.template` 为 `TestMain.kt`; -- 修改其登录信息; -- 在 IDEA Run Configuration 的 'Run Native Main' 中找到适合你的主机平台的配置, 启动运行. - 注意不要使用 Debug 方式运行, 可能会无法启动. \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/local/TestMain.kt.template b/mirai-core/src/nativeTest/kotlin/local/TestMain.kt.template deleted file mode 100644 index 0c6abb05a..000000000 --- a/mirai-core/src/nativeTest/kotlin/local/TestMain.kt.template +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.internal.local - -import net.mamoe.mirai.BotFactory -import net.mamoe.mirai.internal.initMirai -import net.mamoe.mirai.utils.BotConfiguration - -/** - * This test can be started - */ -suspend fun main() { - initMirai() - - val bot = BotFactory.newBot(12346, "") { - enableContactCache() - protocol = BotConfiguration.MiraiProtocol.ANDROID_PAD - workingDir = "test-sandbox/native-run" // Will be based on $rootProject/mirai-core - fileBasedDeviceInfo("local.device.json") - } - - bot.login() - - bot.join() -} - diff --git a/mirai-core/src/nativeTest/kotlin/network/LengthDelimitedPacketReaderTest.kt b/mirai-core/src/nativeTest/kotlin/network/LengthDelimitedPacketReaderTest.kt deleted file mode 100644 index 01b43f296..000000000 --- a/mirai-core/src/nativeTest/kotlin/network/LengthDelimitedPacketReaderTest.kt +++ /dev/null @@ -1,538 +0,0 @@ -/* - * 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:OptIn(TestOnly::class) - -package net.mamoe.mirai.internal.network - -import io.ktor.utils.io.core.* -import net.mamoe.mirai.internal.network.handler.LengthDelimitedPacketReader -import net.mamoe.mirai.internal.test.AbstractTest -import net.mamoe.mirai.internal.utils.io.writeIntLVPacket -import net.mamoe.mirai.internal.utils.io.writeShortLVString -import net.mamoe.mirai.utils.* -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.test.Test -import kotlin.test.assertEquals - -internal class LengthDelimitedPacketReaderTest : AbstractTest() { - init { - setSystemProp("mirai.network.handler.length.delimited.packet.reader.debug", "true") - } - - private val received = mutableListOf() - private val reader = LengthDelimitedPacketReader { received.add(it.readBytes()) } - - /* - * All these tests cases can happen in the real time, and even before logon is complete. - */ - - @Test - fun `can read exact packet`() { - val original = buildLVPacket { - writeShortLVString("some strings") - writeInt(123) - } - val originalLength = original.remaining - reader.offer(original) - - assertEquals(1, received.size) - received.single().read { - assertEquals(originalLength - 4, this.remaining) - assertEquals("some strings", readUShortLVString()) - assertEquals(123, readInt()) - assertEquals(0, remaining) - } - - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - } - - @Test - fun `can read 2 part packets`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(123) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(123) - }.readBytes() - - reader.offer(buildPacket { - writeInt(part1.size + part2.size + 4) - writeFully(part1) - }) - assertEquals(0, received.size) - - reader.offer(part2.toReadPacket()) - assertEquals(1, received.size) - - received.single().read { - assertEquals(part1.size + part2.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(123, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(123, readInt()) - assertEquals(0, remaining) - } - - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - } - - @Test - fun `can read 3 part packets`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(111) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - val part3 = buildPacket { - writeShortLVString("some strings") - writeInt(333) - }.readBytes() - - reader.offer(buildPacket { - writeInt(part1.size + part2.size + part3.size + 4) - writeFully(part1) - - // part2 and part3 missing - }) - assertEquals(0, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part2.size + part3.size, reader.getMissingLength().toInt()) - - reader.offer(part2.toReadPacket()) - - assertEquals(0, received.size) - assertEquals(2, reader.getBufferedPackets().size) - assertEquals(part3.size, reader.getMissingLength().toInt()) - - reader.offer(part3.toReadPacket()) - - assertEquals(1, received.size) - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - - received.single().read { - assertEquals(part1.size + part2.size + part3.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(111, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(333, readInt()) - assertEquals(0, remaining) - } - } - - @Test - fun `can read 3 part packets with a combined`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(111) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - val part3 = buildPacket { - writeShortLVString("some strings") - writeInt(333) - }.readBytes() - - val part4 = buildPacket { - writeShortLVString("some strings") - writeInt(444) - }.readBytes() - - reader.offer(buildPacket { - writeInt(part1.size + part2.size + part3.size + 4) - writeFully(part1) - - // part2 and part3 missing - }) - assertEquals(0, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part2.size + part3.size, reader.getMissingLength().toInt()) - - reader.offer(part2.toReadPacket()) - - assertEquals(0, received.size) - assertEquals(2, reader.getBufferedPackets().size) - assertEquals(part3.size, reader.getMissingLength().toInt()) - - reader.offer(buildPacket { - writeFully(part3) - writePacket(buildLVPacket { writeFully(part4) }) - }) - - assertEquals(2, received.size) - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - - received[0].read { - assertEquals(part1.size + part2.size + part3.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(111, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(333, readInt()) - assertEquals(0, remaining) - } - - received[1].read { - assertEquals(part4.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(444, readInt()) - assertEquals(0, remaining) - } - } - - @Test - fun `can read 3 part packets from combined with a combined`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(111) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - val part3 = buildPacket { - writeShortLVString("some strings") - writeInt(333) - }.readBytes() - - val part4 = buildPacket { - writeShortLVString("some strings") - writeInt(444) - }.readBytes() - - val part5 = buildPacket { - writeShortLVString("some strings") - writeInt(555) - }.readBytes() - - reader.offer(buildPacket { - writeInt(part1.size + part2.size + part3.size + 4) - writeFully(part1) - - // part2 and part3 missing - }) - - assertEquals(0, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part2.size + part3.size, reader.getMissingLength().toInt()) - - reader.offer(part2.toReadPacket()) - - assertEquals(0, received.size) - assertEquals(2, reader.getBufferedPackets().size) - assertEquals(part3.size, reader.getMissingLength().toInt()) - - reader.offer(buildPacket { - writeFully(part3) - writePacket(buildPacket { - writeInt(part4.size + part5.size + 4) - writeFully(part4) - - // part5 missing - }) - }) - - assertEquals(1, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part5.size, reader.getMissingLength().toInt()) - - reader.offer(part5.toReadPacket()) - - assertEquals(2, received.size) - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength().toInt()) - - received[0].read { - assertEquals(part1.size + part2.size + part3.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(111, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(333, readInt()) - assertEquals(0, remaining) - } - - received[1].read { - assertEquals(part4.size + part5.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(444, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(555, readInt()) - assertEquals(0, remaining) - } - } - - // Ensures it will not emit without any length check if received a missing part. - @Test - fun `can read 4 part packets`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(111) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - val part3 = buildPacket { - writeShortLVString("some strings") - writeInt(333) - }.readBytes() - - val part4 = buildPacket { - writeShortLVString("some strings") - writeInt(444) - }.readBytes() - - reader.offer(buildPacket { - writeInt(part1.size + part2.size + part3.size + part4.size + 4) - writeFully(part1) - - // part2, part3 and part4 missing - }) - assertEquals(0, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part2.size + part3.size + part4.size, reader.getMissingLength().toInt()) - - reader.offer(part2.toReadPacket()) - - assertEquals(0, received.size) - assertEquals(2, reader.getBufferedPackets().size) - assertEquals(part3.size + part4.size, reader.getMissingLength().toInt()) - - reader.offer(part3.toReadPacket()) - - assertEquals(0, received.size) - assertEquals(3, reader.getBufferedPackets().size) - assertEquals(part4.size, reader.getMissingLength().toInt()) - - reader.offer(part4.toReadPacket()) - - assertEquals(1, received.size) - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - - received.single().read { - assertEquals(part1.size + part2.size + part3.size + part4.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(111, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(333, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(444, readInt()) - assertEquals(0, remaining) - } - } - - - @Test - fun `can read 2 combined packets`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(123) - }.readBytes() - - println("part1.size = ${part1.size}") - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - println("part2.size = ${part2.size}") - - reader.offer(buildPacket { - writePacket(buildLVPacket { writeFully(part1) }) - writePacket(buildLVPacket { writeFully(part2) }) - }) - - assertEquals(2, received.size) - - received[0].read { - assertEquals(part1.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(123, readInt()) - assertEquals(0, remaining) - } - - received[1].read { - assertEquals(part2.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals(0, remaining) - } - - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - } - - @Test - fun `can emit 2 combined packets with another part`() { - val part1 = buildPacket { - writeShortLVString("some strings") - writeInt(111) - }.readBytes() - - val part2 = buildPacket { - writeShortLVString("some strings") - writeInt(222) - }.readBytes() - - val part3 = buildPacket { - writeShortLVString("some strings") - writeInt(333) - }.readBytes() - - val part4 = buildPacket { - writeShortLVString("some strings") - writeInt(444) - }.readBytes() - - - println("part1.size = ${part1.size}") - println("part2.size = ${part2.size}") - println("part3.size = ${part3.size}") - println("part4.size = ${part4.size}") - - reader.offer(buildPacket { - // should emit two packets - writePacket(buildLVPacket { writeFully(part1) }) - writePacket(buildLVPacket { writeFully(part2) }) - - // and process this part - writePacket(buildPacket { - writeInt(part3.size + part4.size + 4) - writeFully(part3) - // part4 missing - }) - }) - - assertEquals(2, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(part4.size, reader.getMissingLength().toInt()) - - received[0].read { - assertEquals(part1.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(111, readInt()) - assertEquals(0, remaining) - } - - received[1].read { - assertEquals(part2.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(222, readInt()) - assertEquals(0, remaining) - } - - // part4, here you are - reader.offer(buildPacket { - writePacket(buildPacket { writeFully(part4) }) - }) - - received[2].read { - assertEquals(part3.size + part4.size, this.remaining.toInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(333, readInt()) - assertEquals("some strings", readUShortLVString()) - assertEquals(444, readInt()) - assertEquals(0, remaining) - } - - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength()) - } - - @Test - fun `real case test 1`() { - // 5696 - val part1 = - """00 00 02 F0 00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 6D A0 E3 2B 65 53 C5 AE 22 D0 7B AC 3D DD 3C 6E FF 24 84 38 F0 B7 A3 DE 5F 3A 15 DE 7E 6D 08 D1 8C 18 A9 F2 89 03 03 43 15 C6 32 01 74 5B DD A4 33 49 47 78 E0 5B 83 2C E7 3A E1 CC 50 9C A8 8C 5C 88 06 A0 90 04 6E 23 6F AD 84 D8 6B 10 64 AD 33 5B 3F B5 3C C3 24 6C BB 28 8C BC A2 BD 5E 91 EA FA FE 5C 3B C3 F4 3B 59 24 37 1C E2 13 DB 75 C1 7C D5 8B 2F 57 AD C0 16 13 97 12 60 D5 4C 21 E8 13 72 B3 F6 98 05 89 BA 49 60 F1 1C D9 6A 82 F6 A1 AE 78 82 48 60 A9 24 3C A7 7A 93 79 96 8B AA E2 FA DE 5F E9 12 FE 51 27 47 CB 6A 20 DB 64 22 B4 3A B4 C8 5E D0 45 31 9F 63 9B 61 A4 F9 56 CB 0B BF 27 21 55 99 2A 53 EA E4 DC EA D3 7E 62 B9 1D 2A 48 54 C3 6B D8 E0 CD A5 CC 84 AF A8 91 05 2D AC C3 64 82 5F 56 EA FB 13 5B A7 78 ED B1 E1 ED 25 74 1D EE 5D A3 5F 2E FA 0B 5C 65 69 EB DE 4E DD 63 08 83 2C 10 40 D0 44 49 F9 AE 48 B7 D1 75 8D B7 45 EC 08 DA B1 B2 EE EF CF F1 A3 75 93 21 AA C1 50 5C 9B FA CF CD 99 34 26 9C D2 E9 AA 1C 13 8A 8A 0A 5E EE 62 D1 89 31 32 44 88 40 6D C6 BF CF 3B 36 FE BB FC 7F 2D 62 E1 0D 06 0C BD 79 2F 0D 8C 9D 16 44 FB EE 84 AF 39 67 5C BD A6 C1 BD 77 C6 78 81 AF F4 DB C7 3D E9 2D 2F 5F 6C 5F BD 7C D5 A6 E8 96 D4 F0 8E F4 0F 5C 34 E1 DD A5 F9 AB 0A 70 54 1C D8 B5 2E 9B A9 11 9E B7 F8 27 40 04 A1 1A 9B B7 29 99 CD E0 13 9E 5C C5 FD E5 3B DE C5 85 48 DE 21 5D D7 10 AD 77 81 B3 90 9E B2 A1 70 C0 45 AA E4 06 0F DB E4 F7 0B CB 25 28 C9 C1 EA 0B 23 E9 EC 16 45 2F 3B 07 2E 05 15 EA E8 89 C9 CE D7 BE 2B 2D 0F C1 BC 16 8A 4B 79 22 78 4C 70 50 46 86 78 C2 6E DB A2 A9 FA 93 F8 B4 3F 32 50 EF FE 42 EC F6 99 AD 5E 9A F0 E8 B5 F3 96 5C 0B A9 93 DC F2 D9 EB 1C D9 B1 38 E1 87 73 B8 48 DF 3E 35 74 68 E7 C7 94 D4 05 83 C2 08 90 9E 7C ED 61 1A 5A B7 32 5F 09 36 37 6F D3 7B 6F 67 38 D2 EB FD 6A 60 98 87 DE A7 61 88 74 99 80 C4 4E A9 9B 9F CA 4D AB 20 E3 FA 37 07 57 BF E5 A2 9D C5 CB F7 BA 56 E0 38 1B 3D AC DC 51 36 7C 60 E7 BA 00 FB 67 BC 48 6D 17 C6 EB E2 93 F3 2D 5B 16 AF 6B 83 CC 27 15 23 76 5A 73 64 21 C6 21 8D C8 9F 5C 3B 61 47 6F 96 3D EA 7B EE 12 FF 20 F3 20 09 AE 60 C0 86 47 D2 45 18 BC 73 1B 21 AF DA 02 28 4C 05 A9 69 52 31 F8 75 B4 47 A5 A9 49 70 A6 5D 33 F2 07 2A 20 AD 5E 31 6A FC F6 96 11 48 F5 9D 85 CD 97 A6 BF D0 28 C3 51 AA 62 90 98 AD 7E 94 73 53 2F 00 00 13 E0 - |00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 4F 05 F9 A5 25 DD A9 68 1B 80 60 1C D5 63 2F 8D 04 46 D2 7F 20 C1 F4 91 99 FF 90 BD E6 81 8E 24 ED 86 12 2D A4 41 C9 99 4C 70 70 75 29 A7 7A 6C 8C 51 9A CE 2B 43 A1 3E C8 97 CD AB AE 25 21 1A C5 D2 6E 3B 1D F6 3A DF EA 4B 43 C9 5D 1F 16 B3 04 DC BF 6C B8 78 60 A1 56 C9 E9 13 23 77 A3 33 8B B6 88 BD E0 16 74 DE F5 CA BF 50 5E 7F 74 66 29 5D 00 56 E0 AD 04 EF 07 A6 FB E0 A1 85 0F 11 C8 BF F2 E7 C1 21 DA 71 B3 D6 42 A7 0D 8B BB 38 8F BF 2C 54 C8 24 14 0D E3 DB 77 FC 25 C3 D9 3A 12 10 12 E2 A7 E2 81 61 F7 88 BD 2E 05 C4 AC 84 DE 33 6B 9B 8A 9C 78 97 AB 15 4C AE F2 FB AF 93 94 45 69 69 66 8E 46 59 78 53 6A 12 CA 4C E6 AF B7 CB D7 CD C2 47 A6 71 2C 66 D8 76 4D 13 3D 8F B1 33 E9 D4 F1 2B 6B B9 E7 DD 37 E1 91 C0 19 C5 4F 73 C8 89 AC 71 CE BD 3C 64 25 5F FF 00 67 C7 5D 22 CA B1 53 D4 05 22 1A 05 FA 3E BD 13 A6 F9 4B 08 C9 68 4D C0 43 1B 84 AC 2B C2 EA D6 82 8B 28 A2 32 C4 E9 87 36 C0 E7 13 3E B3 CD D6 70 0C 2C 4F E6 F4 D4 5E 32 80 04 D1 CA 4F E6 A1 D3 C3 71 5D 57 18 8B 6A E4 B2 54 47 FA 95 8E BB 3B 92 99 94 33 86 D2 EC 36 69 78 67 BB 17 DB 58 C7 6C 2F 95 0F D8 E5 B0 B5 6F ED 90 88 46 2D 46 BE 23 BE F5 3C 89 AE FB 63 BC F8 C5 E2 5B 96 F4 58 7D 60 FB F8 4F B8 F0 66 3C 89 EF 16 4E 51 30 76 B0 6A 73 DE 95 D2 AA 26 B4 DC BA AB E1 18 17 A2 91 68 FC E0 C3 CE 74 EC F8 5A AE AB E4 4C 6D 66 C3 EF 73 A3 C2 8B 3B C0 32 37 DE 05 A5 EF 7B 2A FB 40 E5 1F E2 FE 0B 95 76 1C 41 87 FC 34 3C 84 B0 63 4D 5B C2 DA 57 08 68 69 3C CC AB CB 66 09 BA 6A 18 25 80 76 E2 20 B8 AC 9F 84 A1 EC D4 21 75 80 0E C1 3C 6B 19 6E BF D6 6A 38 83 C1 21 64 8E 09 CC DF C2 01 D6 68 6A F9 38 8A 6F B2 74 32 EA 8C 90 88 9E 8B CC 21 66 82 76 2D A5 09 27 AC 3F C9 71 BC 0C 86 57 14 37 BC 87 50 A1 F3 9D 9F 27 C2 2E F0 01 10 D6 7F A8 78 AC DB 93 A7 40 42 84 74 8D 15 08 6D 6F EA 02 E2 68 20 BE 3E 70 18 5D A8 08 BA 93 7C D7 0B 8C 76 C3 6C EB 2C 2D BD 59 70 63 83 3D 26 A6 76 D8 11 A7 A8 E9 AA BF D5 EA 99 F1 08 10 9E 31 58 F1 59 99 ED 94 EB 53 64 49 0E 0F 1D 7A 10 3C FA 19 06 AB 49 A8 EE A9 21 2A 29 86 87 C7 8C 31 C0 E9 CA 57 99 E3 DC 32 F7 89 21 C7 72 5B 58 85 B8 65 6B D6 56 D6 C2 9F E5 03 6E BB B4 9D 09 FE 34 A2 DE 3E 86 8F FD A9 6D 8C 86 BC 4F B6 0F 1B 16 1E C4 36 CD F4 80 63 13 36 A7 2F 49 22 42 3E E9 FD 8B 0B BC E0 BA 2A 28 B8 7B 05 A9 72 23 17 51 30 BE CC CB A3 0B 7F 73 A4 9A E7 DA E6 D3 B1 92 0A CF 43 F3 6D D6 16 01 F5 0F 69 2C 67 72 39 BB 1B 87 F8 52 B7 AD 2D 47 D0 82 FB 1F EB 36 CC CC 19 40 F5 EA C1 B2 76 C3 3B E9 0D 8C 3C 1A 05 91 B4 E9 AA 9B FF 40 EF E7 36 D8 94 B2 76 99 B6 27 4E E9 01 A3 E5 A3 CE F1 7B 4E 6D F2 53 05 33 9D 1A C5 3C BC F3 E8 BF 84 0F A8 21 C0 10 CD D1 26 1B 34 80 AE 7B 48 97 45 F6 DF 8F 79 C3 4E C6 47 34 E4 FD 0D F9 20 D2 62 20 FE 96 32 73 69 04 6F 44 8B 68 AA A6 30 4C 28 BB C1 B4 0B 6B BC EF CD DA CA 45 C2 5D 71 C2 53 DD B0 92 3D 0F 80 37 C2 A9 8D 89 E3 D9 11 1C 98 F2 7E 4A 9A EE 6D 50 E0 04 E3 97 71 F2 AC 8D 5D 8A FE 75 F0 B5 E8 AD 3A 25 4D 2F 0C 82 1D 94 5A 7C 63 32 3E E3 82 95 80 2A 6F BB BA 51 38 1C EF 9E DC 1D B2 31 A9 F9 AA 05 27 EB A9 4A 58 D1 21 DE 1C 55 88 3F A5 EB 27 F4 CF DA DF 67 7E 24 5C A0 B6 BC 1F 4E E1 3F 70 86 62 DB A1 BE 5A 88 C6 20 22 B3 F3 DD 9D 08 1B 78 15 55 EC 47 76 AB E6 4C 77 35 D3 08 9F 52 9B 9F 42 58 28 A4 8D 96 F0 BF C1 42 90 1C 18 A2 98 25 86 B0 9B 3B DE 75 C1 87 4F 9A 7E FD 03 9F 0F 95 E4 39 04 FE F4 B7 DA 57 BE F0 D8 09 B6 42 F4 CD CF 8E 38 98 6B 29 77 D3 19 63 03 2D CC DB 6C 54 85 18 5D FA AB FE CE 46 6A 1F 8B 63 0F 67 27 55 E7 F4 03 7F B1 52 7F 2E 01 F7 8C B9 9F F6 03 4F DD 05 D2 3A D7 2D C9 1C 3D A1 2E 60 7A 0A E5 7B 72 C7 8D 18 9A FA 4B 3F 16 23 17 21 6B BF 32 9B A2 E9 64 F2 E4 F9 B2 65 81 8A 99 F7 23 36 8D 57 E7 A6 26 26 1F 7F 19 F7 5C 5B C3 08 A1 D8 27 C3 BE 98 26 B3 50 63 F0 05 6A 29 19 05 CA 4A 12 CF 33 95 27 53 14 A2 5F D0 37 B6 03 0E 0C 72 44 E4 DB 89 B3 E0 D6 0D AA 3F 1F DF E8 86 E1 55 D2 6B 15 AA 98 A2 92 E9 1B 2E 20 8A 6B C8 6B 0F 22 37 FD F5 36 06 BB 3F 03 23 9F 40 08 1C 58 DE 20 74 BB C2 7B 0A 81 FB 6F D8 89 DB 03 DA 89 86 B1 40 A3 AB 8D A8 CD 2D 9B 97 98 20 6D 73 8F 35 F2 26 F2 8B A1 47 35 27 9D 85 BC 65 4E 7A 42 FC 39 1D 62 24 7C 1A B1 01 CC FA 40 15 FC 4B 2F CE 1B 9B 0B EB 07 F7 12 55 BD 7C B1 5C BC AC 53 16 DB 34 CF D3 91 6A 92 9E FA E8 A2 6B 4D 49 36 3F 33 79 49 4D 52 EC 1A 3F 0A EB 9E 61 E8 8D FA A2 D4 A2 E4 26 1B 2A A2 CA 6A 94 35 8D 77 CE 0A 7F 99 7D D8 53 61 28 F7 27 43 38 99 05 9E B9 7E 9C B5 61 84 AE 0D 9C 44 EF D1 54 B8 3F B0 E8 D4 FE EB 42 A5 DA 24 07 28 F5 21 93 A2 53 30 18 26 AB 3C 99 88 EB 0A C8 D4 6E 76 25 A7 65 13 59 16 FE C0 E7 23 BD 6D 4D 5B DC 4C 02 8A 93 56 B5 3D B0 ED 2A 09 CD 01 9A 5A A0 62 FF 4C 23 7E 1C 2B 33 AD 29 B8 7B 4F A6 71 7B 1A C1 3E 2D B9 2F 78 56 CF D2 65 EA 02 E9 1D 4A 27 CD 94 B0 67 79 E3 9B 2B 9C 50 1B 78 ED 06 3C 06 C0 07 6E 53 49 73 2C 74 59 AF A7 92 16 A3 DA 35 B7 B9 B8 D8 CF 58 3E BF 43 BF 43 E8 C5 B7 36 B0 7E 65 AF 6F 75 89 C5 76 87 40 19 9C 4F 30 54 18 B2 09 74 4B D6 A5 29 22 76 E8 19 7C A5 A9 B0 98 12 06 0A 9E 87 F3 1F 75 44 32 CD 47 FE 56 7F 84 4E 73 EF 28 A3 C6 78 08 94 1D 6A D2 E4 31 20 99 63 D4 F7 A8 84 CE C8 5E 43 45 01 3F BC 9A D3 0C B7 FF B0 A8 3D C7 EE D7 74 76 50 9C 61 67 E3 E2 19 BA DD CB AF 8F A2 CD 55 56 1C 32 5F 16 AA AE 24 2B 10 D4 A1 F9 2D 91 93 1F C5 BE 7D 5F EC 4B F4 E5 3D FF 10 3B F7 2D 27 F1 97 FF 46 BF 6E 48 1C 7B 49 BE 1F 7A F8 79 0A A4 C4 2D 73 C2 FA 1A 71 56 6E A7 6B 1A 46 83 DA 80 47 1D E7 FD 03 3A 98 51 E5 3D 30 71 05 41 D5 F5 8F 7E BC F1 47 6E D2 2E 9B 6C 18 30 D0 92 F1 BD 5F 67 D4 5D BA 75 2F C2 5F 98 64 5F 2C 7B 72 8F 77 F9 7D 07 F9 66 9B 21 6F B1 ED F0 22 B4 0E 4D 3B 79 42 CD 84 66 F7 6F 57 B4 CD EE 22 B0 DB 31 74 12 DC D8 B3 54 07 04 18 77 D8 80 D4 FD 33 AE 57 64 E1 23 37 68 4D 1A F0 36 ED C5 FA 97 20 93 8D 37 A3 A1 84 CE C9 4B 2B E8 15 CB 3D 9C 10 08 A1 FE 7E 51 B9 F7 F5 0A 8A 65 FF 6B 7C E6 01 2A ED BA E2 A7 26 32 F9 79 F5 2C 16 81 AA DD 15 1F D2 A4 C7 B7 26 7A 5A C6 CE EA 59 26 68 07 6F 10 E8 6B 3F 22 B3 B0 64 7B 05 AA 76 98 0B 03 1D 6F 25 B6 08 54 A8 87 8A 84 92 29 9A 2D A4 59 81 BF 52 DE 24 F9 5F C2 5A FA 1A D7 EE 03 6A 00 C3 8E 28 97 31 55 CC 07 1A 98 11 1E F3 E8 E3 5A 6B F1 91 87 4A 74 83 7E C1 DF 06 AF 2B C6 B0 B0 56 F6 96 D0 C4 AC F3 A8 7C D8 4A BF 50 66 09 AA D1 0F E8 8F 7D DE 70 56 8D D4 68 E3 1A BC C1 EA 9F 6C 8B F3 8D 04 D7 24 95 E5 E9 FC 72 36 D7 9D 01 C9 0B 81 46 01 4C B7 BB 48 36 B4 3E 52 3C D3 0E 24 36 64 94 CC 23 F9 A0 86 56 36 0E 67 B1 EF 86 1D 93 7F 58 3E B6 91 49 14 31 F6 EB C3 5A DF A8 C8 26 2E 29 37 7A 23 7C 3B D9 C0 53 33 52 02 AC 6B B5 FB F6 A1 6D 13 E4 87 CA 56 3A B2 0C 75 92 75 5C A0 1C C2 31 97 E8 1B 13 AC D7 E1 47 E3 E7 CE 86 FF 85 AE E2 BD 5C 6F 3F 65 FA 11 C6 C0 12 CE 86 19 C8 E2 72 8E B6 4E 88 73 E0 C1 31 86 42 F7 51 05 68 E0 73 99 0E 69 86 59 C9 4A 77 CA 76 10 AC DE 95 F9 17 4A 8A 5B 14 A8 16 57 C4 16 60 CF 0E 48 EE D0 DC 63 8B 9B 46 6D 96 41 1D 38 8B DF 70 31 95 3A F7 A8 1F B8 4D 7A BA E0 CC E9 58 B5 2A 87 42 43 63 DC 12 47 AC 32 49 D7 02 87 DB C9 5D 10 BC 93 65 F4 3C C3 FF C7 28 86 14 4D 4C 70 FD FE 5A 06 EA 01 C5 27 FA 46 9B 98 5E 71 D5 BE C1 0A A2 45 7F 09 1A 7D 12 4F 38 49 09 77 1B 8A 39 48 27 22 4C B1 A3 AA 68 8E 1B 73 B0 A6 EA 78 AA C3 33 16 3B 00 69 4A D5 07 06 42 65 50 2E F2 60 8B F0 9E 8A 7C 05 B7 DC 85 E7 EF 10 FD C8 FE 80 A9 C6 B0 46 35 0F 77 17 6C 7D EC 60 24 D9 21 76 AC DF 6B B2 FC B0 75 D1 3C 2D 69 60 C2 4E CD 62 58 72 D8 AC B3 F5 75 56 80 E3 D1 9B 95 1B E7 CD D1 C3 C2 FE 50 DC DD 10 D5 89 43 7E FB 90 54 4D 42 13 1A 47 20 DB 18 E7 BA 3D 2D AF 53 DC 8F 37 08 8C 3B 52 00 A4 62 AB 22 93 46 05 38 A8 C2 FF 2C F5 F8 5D B5 4B 04 7E 48 F7 03 75 DA C8 B0 E9 E0 0B 3B 7E 57 0A 1A 53 98 EE 1A 2A 48 C7 FD 22 D4 B0 E7 5C B3 75 8F B7 4E 8A EF B0 29 6C A9 C8 02 24 4E D6 3B 2C 82 4E F3 1E 62 94 40 64 2E 77 BB B9 3D 1E F4 BD DD BD FA DA 25 09 65 8D 5E 1B 3C 2E 80 22 11 D6 1D 32 B4 7E 89 B0 F6 85 83 C3 34 78 57 3C 97 DF 05 01 6C 8F 91 25 95 D8 BD D8 86 7C 8C F0 50 88 25 10 6D E6 E2 DA 76 31 80 55 2E E6 1F 37 A1 82 8B B5 FC 2B 71 5D 9B E6 89 CD 14 BB 49 28 BA 1D 49 71 08 A7 D2 B5 A4 1C 9C 1B DF EF C3 E7 55 2B F4 2E 4E 93 4A 74 B6 A9 47 18 23 9C 44 08 3D 13 06 24 41 06 1E BF 88 BC 3D 1B 75 92 80 C7 78 A4 CA 5A F1 79 EF 3F DC F5 5F AF 49 73 68 96 C9 DB 8E F2 A7 B4 2D 0F 50 64 0C EB EB F6 08 09 0A F5 0A 2C 88 5E AE 44 25 89 DF 7F 4C 5D 0C 73 47 3C 1A 2B 41 7B 9E 28 48 39 0A A2 D8 04 78 90 DE D5 88 9E C7 00 5F F8 63 CD BF 8D F1 5C 12 CE 7E 2B 09 D0 4C 42 7A 84 0F 36 C6 C9 5D AA 44 87 23 4A 76 76 94 1A 7A 2D D6 23 B4 84 EF 6D 3B C6 01 B2 F7 20 09 40 51 E4 80 58 5E A6 A5 97 2F 75 CE E7 97 78 F0 0B F9 31 98 CE 6C 40 4F A4 B3 14 AA A5 89 AA F9 9B 21 11 69 A8 E0 56 B0 F1 C9 CC 44 83 1C 32 E3 79 14 1A 5D C8 F3 41 C5 9A CE A1 B7 5B C2 53 22 49 15 FE 52 A9 38 DB BD 7A 69 83 06 0F 69 77 98 D1 F4 93 3C 83 37 B7 21 A5 D7 2A 9E D9 A3 BC 1C 9D 4F A4 22 51 4C 44 B9 35 C9 8E 41 FF 0D 6D FC BD 12 F5 CA 3E F9 EE 75 1D 01 9B CD 34 B2 C6 4A 4B 9D 2B 79 A5 12 52 BF FF F4 42 62 39 53 58 8E 82 F6 94 2C 00 97 0E 8A B3 5B 73 3D D6 CF 3E D5 14 BB 2D 5B E6 2D 78 88 D5 E8 33 BC E9 C9 A4 2D 36 41 F5 DA 5D 68 6E B6 B9 93 89 E0 15 E5 68 65 48 42 FA 9E 16 20 5A C8 CB 8D 61 52 E1 23 DE 0A 40 8C F5 6F 86 AD 36 F6 20 9E D4 6A B2 D9 7E 5E 3E F3 D7 C8 A8 25 CB 49 E5 FE BA A8 4E 34 41 B4 CB 9B AA BA 8F B9 53 F9 0A 67 AC 3A 02 D2 55 AB E3 6F 8C 79 E6 C0 2E 70 5C 6C E5 89 17 F2 A4 C8 8C 58 58 8C 3C 22 10 68 0D 9A 70 63 59 F6 C0 60 6F 1E B6 9E B5 69 B3 1B 0E D8 F8 8C 5D 06 2F 42 4F 69 BB 83 DF F8 20 8A BF 74 30 4A 57 C8 FE 13 AD 8B 09 B9 92 7A DD 53 DA A9 33 00 85 53 88 2E 58 3D A4 02 ED D0 E9 25 E2 EE 7A C0 08 B3 B5 BF 7D 36 07 0D 87 F7 6B 68 BF C6 7B A6 E4 B6 D7 76 FA BE 23 E6 53 94 D3 54 94 6D 39 87 3F 74 F3 ED 5C D6 E0 4F E8 5C AD 86 3E E7 E1 12 32 51 F0 E9 42 B5 12 46 26 B1 86 AD 19 1D A2 81 4E 3E F2 FF 8A 5F 9C 80 02 56 70 AA 0B 0D 2C 61 DA B9 1C 5A B3 6F 2E C5 32 C0 48 FE 19 9E F8 F4 30 3E E2 2C D8 A5 81 E9 C9 6B 44 6B B7 95 5D 94 0E C5 63 D7 78 FD 58 54 E1 19 E2 22 B5 48 10 D5 87 28 F7 A3 30 43 9D 69 B5 D5 38 D5 05 22 77 FC DC 93 62 08 CD 58 19 E4 65 E6 AC 05 6C FE C9 02 3A 28 48 77 AF D9 63 40 25 45 CF 89 4C 0A ED 60 C9 A8 75 A0 68 79 69 8C 13 5C 0C B4 FD 8F 27 8E BA 16 E5 1E AA 78 84 AF BE BB E9 09 9C 51 8A 10 2B DB 0E 7E F4 E2 A4 DE 15 85 A2 E2 40 E7 37 56 A5 AF 91 4E EA 80 E3 8F 3A F3 28 15 8D F4 FA D1 EF C0 09 98 43 1A A3 98 CA 94 BB DD EF 98 E1 98 6E AD 53 9F 48 E5 9E A5 1B 7A ED EE CC 5C 8B 05 AF B9 76 54 E1 C5 3A 91 00 A8 CE 1C AC D8 FC B6 2D 96 D3 CE E7 81 3F B0 E7 D5 39 C4 E0 E8 85 D4 18 51 9E 41 BA FE FA 32 0E 4C 4A 10 25 75 21 9E 0E 5D 29 A4 A0 6B F2 EA FF 70 9F 38 85 35 94 B6 90 39 DB 0D 25 E0 FF 89 97 93 94 88 84 8A BE D2 97 AE BF AC 2A 28 30 F4 A2 59 95 A1 F0 66 86 A5 2A 55 7A F0 35 0A CA CC DC 61 32 A8 B8 5C 47 90 19 91 E0 1E E1 1C BE FE A4 A3 02 27 7A 30 F6 10 11 CF ED 34 3F 18 74 E8 A5 23 C4 D9 73 5D 46 AA A5 EC BA 6E CE 40 EE E1 2D A0 9F CD DC B6 6D 6E CE 3A 94 A0 90 4D 7E DD 38 A9 52 27 3E 3D CF 94 C3 A7 07 F1 46 30 DB 0D BF 9F 30 12 25 FB 51 42 3F 74 49 3F 6C 1A 20 91 96 7C 1F 62 6C DA CA DE 99 48 74 D4 E2 5E E4 B8 AE BA 55 B5 95 E1 51 57 5B 0D B8 F9 4A 1F 86 CD FF AB 69 80 6F 65 76 DE 10 DF 91 EE 3F C4 69 81 76 6A 03 BB C5 73 5F 59 5A 0D BE 64 38 66 D0 75 EC 93 E7 52 E5 A6 3B 8F 99 8B A4 5E 6E B0 53 F5 4D 21 F4 D7 3E 7E 18 59 4F 83 56 E9 09 78 9C 90 9E 73 A2 87 F6 CC F4 DD 7C E5 24 BD DB E6 12 AC 48 28 96 98 B8 8F 92 20 F0 3D 22 0C 0B 34 93 9D D0 19 0E 9C 81 C2 FD A7 B1 09 56 E0 B8 C1 49 4F 76 9A 47 5A 69 17 32 99 61 76 05 F8 66 80 C3 D5 16 9D 78 88 C8 9F 2D 44 60 C5 44 18 C0 5F 90 59 52 9C 54 A8 C1 21 73 E9 B8 23 CC 8B A2 E9 E1 E9 6D 7A AF 2B 59 3E EB E3 E4 65 9C 5F 31 D3 EF 18 33 09 49 C8 C2 36 D5 4B 6C A4 79 66 B6 5B 8F C8 5F 74 88 5C 89 45 57 A8 1F 60 A0 2C D0 C9 6F 8D E5 D7 EF 64 47 B3 2F 5E D1 F7 A5 51 B2 E7 66 14 5C 9B 94 6B 47 C4 B1 D1 7E 25 01 70 9B E6 F9 02 B6 84 30 42 4C 9A 10 D9 95 FE F7 D1 60 05 9B CB 58 BE 92 A3 BD 7E B8 D2 CA E3 2D E3 EF 80 E5 86 64 BC BD BC 28 6D B8 C4 37 FB BD C3 5C BD 67 FA 22 98 79 22 5C 99 E2 90 02 FB 3F 09 10 A5 71 A3 95 17 AC 14 8F 6F 48 8F 39 B4 4E 23 78 2D FF FF 77 D9 E8 B9 F6 5D E0 39 44 92 C7 56 E9 25 F4 52 1C 6A CE 4C A2 BF 44 94 97 D4 42 3E 71 FC 59 68 16 67 AB DC 7A 4A 96 1E F1 F3 3E 85 F2 4C 2B 1E 2A 78 04 73 28 60 87 4B D9 4D 62 05 3C 33 DA 0B 13 90 EC 62 AF 6A 15 30 D2 46 1D 45 EA 4B 8A 23 7A D6 8B C5 89 6C 8E CE 6E 84 03 82 2D B5 19 E6 20 93 01 C2 24 84 74 23 79 F1 F4 99 FD 7C CC 0A B4 B4 18 5D 34 09 9F EE CF 6A 89 33 B3 DF D2 00 AC 4F 3E D9 A6 99 C8 13 A5 6B C8 2C 3C 30 B0 FD B7 13 CB FB C5 21 3B 1A EB 90 FA C1 4F 08 99 04 5D C5 8A 72 42 30 A4 49 88 5B 1C 31 14 1F 12 A6 8A 52 E9 1C 09 16 86 A2 81 19 30 50 9F A9 66 31 1B 6D 97 31 01 DF A9 77 F5 EB 59 AE 37 90 02 63 FE 85 25 79 3D A1 C2 30 12 83 50 3F 77 CA 2A 28 3C 87 84 C4 BE 4A D1 8E A4 A8 89 DD F7 21 03 9E 6C D3 6E AA 0A 25 27 8D 66 E3 C3 7E 17 95 0B CE E7 2C 37 55 80 85 CA 61 83 94 E3 63 0A 4F B0 CB C5 42 CE 0F 00 3D 4B 77 49 A7 96 22 E2 E0 AF 43 6B CE F2 D5 5F 0D F6 4F DB 37 D1 EE 8D 69 97 92 CD 2A BC 45 9D 3B 47 27 37 6B E3 DF 4B D8 FB A2 67 8F 7C 19 95 EE 98 E9 3A 05 28 8D C9 26 56 CB E0 4E A8 99 F9 CD 80 6B 65 18 B2 AD 66 E2 1A 14 7A 03 2D 24 E3 90 12 6A 25 05 2D 5C 32 7A 1C 13 D4 B6 F5 6D 4E A2 5D 71 32 88 50 1D 0F B6 DD 61 23 F7 DC BB 5C 27 B6 EB 7F 5B 89 5D 6E 8A 19 CF 36 D2 7F E6 55 0F E5 18 F9 9F 49 6D AC E8 5D 8C 2A 6B B7 D8 6F 00 ED 2A F0 B0 5F DE 96 D4 3D 23 C9 B1 75 EE 91 EC B6 31 DF 50 2C F9 C8 BD FD F7 A6 BC 98 02 BA 9C 23 24 6C A4 3E D6 2A 5A 65 4C 39 72 0C 8E 43 29 08 4C 21 B1 A2 29 76 6F 19 03 6A 2C 8D DB 9F 2D A5 6F 01 34 A6 6C 80 3D A1 2E 90 FA D5 56 A3 89 C0 B8 09 04 31 60 73 A5 7C 8F 04 92 7E A3 7F 60 24 B7 69 E8 5C 5B 53 55 D9 03 B6 32 6E 0B BB 2D 57 AC C5 7E 70 58 C3 4A CE 35 E9 26 AB F6 B4 B7 AE 5D 03 82 8B 30 D8 9D 30 9B 93 4C B0 48 D2 D6 3B 04 95 20 18 14 EC 75 58 E8 42 DE 1E C7 B9 3F BF 86 E9 3C 82 D8 62 0F 97 4D D1 D8 7D EE B1 1C C0 15 17 A8 D4 A9 D2 5B 2F 12 95 C2 7D E8 4C 51 6D 95 88 C8 33 7E 69 24 8F E4 2F 7F 22 20 32 BD 01 C8 71 C6 C1 A8 3C CA BC 8F 64 37 5A 4A 15 A6 36 F5 31 34 7E 70 78 5B 1C 8F 0B 14 28 9B 43 D1 49 3B F7 91 DC 12 F5 EF C6 0D 39 FE B4 6B 4D E1 BA 87 96 CB 75 87 B2 78 A1 D7 F6 7D DA ED 77 FE 42 DE 28 29 DF 1A 1F 11 CA 70 BC AF 9D 7D 5E 07 23 C8 8B 2C F7 1A 40 A2 15 73 2B 92 DE 98 57 E7 3D 43 A2 2A 8C 66 6A 0C 9D 15 A4 65 17 F5 A5 15 F7 CF 4B AE D0 46 E6 4E 62 E2 6E D9 FB 64 17 A8 96 57 8A 8B E8 89 C3 73 A8 FB 49 92 F6 4A 51 0A BF 2E 33 2E F6 6D BD C0 C7 0C 4F 69 8D 10 BB 46 C8 B4 88 0C D8 ED 2E 2B 0D 1E 77 E3 C6 52 E6 6D 56 80 5E A6 EA 34 86 5D 3B 3D EE 19 F4 62 9C BF 7F B1 6E 78 A1 75 58 EB 94 DB B9 1F 9A D9 72 EB 1E 60 58 87 46 B3 9D 2B 2B D7 04 8A 13 30 CD 35 16 C2 0E AB C3 93 B7 F4 F8 25 C5 BA 20 B5 62 64 A6 78 D7 E9 FD AD BC D0 69 F9 A7 AF C1 9D B7 8A B2 DA A6 CF F4 5E F4 FB 20 52 2A F2 3D 2F C1 CD A5 70 3A 8F 1C 4D 93 77 DC 35 1E 77 9F B9 15 7B 84 0A 7B 69 86 20 CC BA 7F 60 6D F8 D4 0E 97 9A 90 62 ED 9F BE FC 65 C6 A1 BD 58 D2 64 3A E8 73 69 37 B7 33 80 6F 5F D3 6B 7A 24 A5 62 A0 23 0A B9 51 7F AC E6 A0 E3 95 DA 61 97""" - .trimMargin().replace("\n", " ").hexToBytes() - - // 792 - val part2 = - """31 9D 14 F5 35 51 07 F7 6B 8E 3E 0B 5D C2 B9 C1 70 16 9E D2 2D 75 62 5E 62 82 CB 8B 22 A9 E9 DA 91 37 97 3B F9 95 AB 12 72 D1 7E 8C 87 2C A8 D1 AC CD 40 7B B1 5B 3E 4F 29 CA A6 D2 D8 9C 38 15 42 E6 66 35 9E C5 41 2C 4D BC 22 1F A1 AD 24 CE 4C C1 B2 E2 E0 A4 A4 DF E7 01 8B 10 90 C3 38 02 A9 0F 49 AA 8B 86 EC 58 B2 AA 79 6E FF 1E 1F 2A 35 3F 3D 96 A7 DC D0 F6 E5 18 4E EA C8 C5 72 76 3E 74 2E 12 05 78 6F FC BD 07 50 CA AF EE C2 11 00 00 02 88 - |00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 7C CC CC 8A 82 A1 2F A3 F6 08 8D 5C 7B 64 F8 BB 4F 09 87 B1 7C E3 01 53 5F C0 32 A8 6E A4 0A 1F 49 38 E5 FD 7F 20 52 A3 1E 66 A5 43 85 C4 96 97 3C 8F 2A 33 98 D7 A6 90 50 37 BE 76 2D 94 CE 1F D8 63 07 DC D1 5A 6F F0 FA 1F 41 9E 74 BE 8D FC 61 2C 66 3F BB 4C FB 9A 02 53 FF BE E5 FD 52 B7 FD CE DB 80 C0 6A 55 14 31 31 0C 8A 7D 24 DC EC 8C 45 62 ED D9 F6 DA BB EA C5 6E 76 66 11 F4 CB 2B 3B C7 45 6C BE 6F ED 9E 1D 2B 8A ED 3B C1 5B 06 DC 75 58 C9 66 13 4C 7D EA C5 F9 A4 D1 37 EF 2B BE 98 E3 37 1C 30 17 20 80 98 AD 5F BC 85 98 5B A1 7F 9E AE 54 0C 36 B0 6F FA 4A 5B 6F DC 7E B1 9E 99 F6 07 16 43 11 7A BC 82 F7 FB B2 95 7C 29 37 AF 38 70 6E A8 75 12 84 73 CF 15 A3 65 B9 2B E5 0A 01 30 67 A2 D2 BF 9F 30 AF 4D A5 A6 EA 4A B3 E4 BB AC 15 E3 FB CD FC B0 52 69 05 8D BE A0 11 1D A7 AB 65 6D F1 68 06 71 89 4F 0A 7E F4 68 A0 71 21 07 E4 85 41 76 16 07 78 2E C5 30 A6 2F 5D C7 DB EF 24 61 20 E6 6D FF 01 28 0D D6 73 42 BF F1 65 EA 7E DE 81 94 89 EB D0 65 8D 94 39 BE 89 7F B0 B3 0C 74 2F FA B4 2B 86 22 08 67 EB FA 62 83 FA BD CA 9D 92 95 A6 B0 BB 0C 76 07 C4 DC B9 E0 CD 67 AB 84 4D CC 55 52 E5 22 CD FD AC 08 35 81 36 9A 2D 7B 56 66 E8 B4 D9 A5 AA 7A 57 F2 F6 FB 20 A1 78 D5 5D F3 7C E4 7F 34 53 59 52 38 06 35 AD 6D 7A 97 99 AA 97 1D 9D 4A E4 22 7A 11 0C EA 16 27 7C 8A 9E F2 5A 82 D5 23 C3 01 BF D7 43 99 E7 26 25 AA 5A 27 29 ED 84 7F 9D 46 47 F8 C3 94 94 D7 C8 27 9F F7 93 16 4E 57 62 FC AC 32 2E A8 9F B2 62 EA 45 B0 53 A2 6C 52 D2 76 5F 48 00 93 5B 95 24 1F 3C E7 EC 40 26 66 0F C7 7D 30 91 A5 F2 6A 2F 2D CB 24 0B A3 F8 71 23 CA 31 A1 42 17 AC 9B 25 5A 2E 46 2D BC 34 DE 70 DA EF 4C E1 2D AE 2A 88 66 19 EE 35 02 C6 68 2C C4 0A 90 82 CA AB 42 D6 57 01 62 22 0D DF 65 6A 7E 6E 68 07 1D E6 1E DB E3 E6 22 F2 9A 36 F4 25 06 FA 91 83 9C 98 EC FB FD F0 F9 62 97 E6 37 30 F3 B3 09 46 D9 7D 7F D5 51 FF 8A FA B7 33 C9 15 AC D3 93 B7 8F 36 E8 1A 85 42 E5 C5 00 E6 28 9C FA 6C""" - .trimMargin().replace("\n", " ").hexToBytes() - - // packets sizes: 748, 5084 644 - - println("part1.size = ${part1.size}") - println("part2.size = ${part2.size}") - - reader.offer(buildPacket { writeFully(part1) }) - - assertEquals(1, received.size) - assertEquals(1, reader.getBufferedPackets().size) - assertEquals(5084 - (5696 - 4 - 748 - 4), reader.getMissingLength().toInt()) - - assertEquals( - """00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 6D A0 E3 2B 65 53 C5 AE 22 D0 7B AC 3D DD 3C 6E FF 24 84 38 F0 B7 A3 DE 5F 3A 15 DE 7E 6D 08 D1 8C 18 A9 F2 89 03 03 43 15 C6 32 01 74 5B DD A4 33 49 47 78 E0 5B 83 2C E7 3A E1 CC 50 9C A8 8C 5C 88 06 A0 90 04 6E 23 6F AD 84 D8 6B 10 64 AD 33 5B 3F B5 3C C3 24 6C BB 28 8C BC A2 BD 5E 91 EA FA FE 5C 3B C3 F4 3B 59 24 37 1C E2 13 DB 75 C1 7C D5 8B 2F 57 AD C0 16 13 97 12 60 D5 4C 21 E8 13 72 B3 F6 98 05 89 BA 49 60 F1 1C D9 6A 82 F6 A1 AE 78 82 48 60 A9 24 3C A7 7A 93 79 96 8B AA E2 FA DE 5F E9 12 FE 51 27 47 CB 6A 20 DB 64 22 B4 3A B4 C8 5E D0 45 31 9F 63 9B 61 A4 F9 56 CB 0B BF 27 21 55 99 2A 53 EA E4 DC EA D3 7E 62 B9 1D 2A 48 54 C3 6B D8 E0 CD A5 CC 84 AF A8 91 05 2D AC C3 64 82 5F 56 EA FB 13 5B A7 78 ED B1 E1 ED 25 74 1D EE 5D A3 5F 2E FA 0B 5C 65 69 EB DE 4E DD 63 08 83 2C 10 40 D0 44 49 F9 AE 48 B7 D1 75 8D B7 45 EC 08 DA B1 B2 EE EF CF F1 A3 75 93 21 AA C1 50 5C 9B FA CF CD 99 34 26 9C D2 E9 AA 1C 13 8A 8A 0A 5E EE 62 D1 89 31 32 44 88 40 6D C6 BF CF 3B 36 FE BB FC 7F 2D 62 E1 0D 06 0C BD 79 2F 0D 8C 9D 16 44 FB EE 84 AF 39 67 5C BD A6 C1 BD 77 C6 78 81 AF F4 DB C7 3D E9 2D 2F 5F 6C 5F BD 7C D5 A6 E8 96 D4 F0 8E F4 0F 5C 34 E1 DD A5 F9 AB 0A 70 54 1C D8 B5 2E 9B A9 11 9E B7 F8 27 40 04 A1 1A 9B B7 29 99 CD E0 13 9E 5C C5 FD E5 3B DE C5 85 48 DE 21 5D D7 10 AD 77 81 B3 90 9E B2 A1 70 C0 45 AA E4 06 0F DB E4 F7 0B CB 25 28 C9 C1 EA 0B 23 E9 EC 16 45 2F 3B 07 2E 05 15 EA E8 89 C9 CE D7 BE 2B 2D 0F C1 BC 16 8A 4B 79 22 78 4C 70 50 46 86 78 C2 6E DB A2 A9 FA 93 F8 B4 3F 32 50 EF FE 42 EC F6 99 AD 5E 9A F0 E8 B5 F3 96 5C 0B A9 93 DC F2 D9 EB 1C D9 B1 38 E1 87 73 B8 48 DF 3E 35 74 68 E7 C7 94 D4 05 83 C2 08 90 9E 7C ED 61 1A 5A B7 32 5F 09 36 37 6F D3 7B 6F 67 38 D2 EB FD 6A 60 98 87 DE A7 61 88 74 99 80 C4 4E A9 9B 9F CA 4D AB 20 E3 FA 37 07 57 BF E5 A2 9D C5 CB F7 BA 56 E0 38 1B 3D AC DC 51 36 7C 60 E7 BA 00 FB 67 BC 48 6D 17 C6 EB E2 93 F3 2D 5B 16 AF 6B 83 CC 27 15 23 76 5A 73 64 21 C6 21 8D C8 9F 5C 3B 61 47 6F 96 3D EA 7B EE 12 FF 20 F3 20 09 AE 60 C0 86 47 D2 45 18 BC 73 1B 21 AF DA 02 28 4C 05 A9 69 52 31 F8 75 B4 47 A5 A9 49 70 A6 5D 33 F2 07 2A 20 AD 5E 31 6A FC F6 96 11 48 F5 9D 85 CD 97 A6 BF D0 28 C3 51 AA 62 90 98 AD 7E 94 73 53 2F""", - received[0].toUHexString() - ) - - reader.offer(buildPacket { writeFully(part2) }) - - assertEquals(3, received.size) - assertEquals(0, reader.getBufferedPackets().size) - assertEquals(0, reader.getMissingLength().toInt()) - - assertEquals( - """00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 4F 05 F9 A5 25 DD A9 68 1B 80 60 1C D5 63 2F 8D 04 46 D2 7F 20 C1 F4 91 99 FF 90 BD E6 81 8E 24 ED 86 12 2D A4 41 C9 99 4C 70 70 75 29 A7 7A 6C 8C 51 9A CE 2B 43 A1 3E C8 97 CD AB AE 25 21 1A C5 D2 6E 3B 1D F6 3A DF EA 4B 43 C9 5D 1F 16 B3 04 DC BF 6C B8 78 60 A1 56 C9 E9 13 23 77 A3 33 8B B6 88 BD E0 16 74 DE F5 CA BF 50 5E 7F 74 66 29 5D 00 56 E0 AD 04 EF 07 A6 FB E0 A1 85 0F 11 C8 BF F2 E7 C1 21 DA 71 B3 D6 42 A7 0D 8B BB 38 8F BF 2C 54 C8 24 14 0D E3 DB 77 FC 25 C3 D9 3A 12 10 12 E2 A7 E2 81 61 F7 88 BD 2E 05 C4 AC 84 DE 33 6B 9B 8A 9C 78 97 AB 15 4C AE F2 FB AF 93 94 45 69 69 66 8E 46 59 78 53 6A 12 CA 4C E6 AF B7 CB D7 CD C2 47 A6 71 2C 66 D8 76 4D 13 3D 8F B1 33 E9 D4 F1 2B 6B B9 E7 DD 37 E1 91 C0 19 C5 4F 73 C8 89 AC 71 CE BD 3C 64 25 5F FF 00 67 C7 5D 22 CA B1 53 D4 05 22 1A 05 FA 3E BD 13 A6 F9 4B 08 C9 68 4D C0 43 1B 84 AC 2B C2 EA D6 82 8B 28 A2 32 C4 E9 87 36 C0 E7 13 3E B3 CD D6 70 0C 2C 4F E6 F4 D4 5E 32 80 04 D1 CA 4F E6 A1 D3 C3 71 5D 57 18 8B 6A E4 B2 54 47 FA 95 8E BB 3B 92 99 94 33 86 D2 EC 36 69 78 67 BB 17 DB 58 C7 6C 2F 95 0F D8 E5 B0 B5 6F ED 90 88 46 2D 46 BE 23 BE F5 3C 89 AE FB 63 BC F8 C5 E2 5B 96 F4 58 7D 60 FB F8 4F B8 F0 66 3C 89 EF 16 4E 51 30 76 B0 6A 73 DE 95 D2 AA 26 B4 DC BA AB E1 18 17 A2 91 68 FC E0 C3 CE 74 EC F8 5A AE AB E4 4C 6D 66 C3 EF 73 A3 C2 8B 3B C0 32 37 DE 05 A5 EF 7B 2A FB 40 E5 1F E2 FE 0B 95 76 1C 41 87 FC 34 3C 84 B0 63 4D 5B C2 DA 57 08 68 69 3C CC AB CB 66 09 BA 6A 18 25 80 76 E2 20 B8 AC 9F 84 A1 EC D4 21 75 80 0E C1 3C 6B 19 6E BF D6 6A 38 83 C1 21 64 8E 09 CC DF C2 01 D6 68 6A F9 38 8A 6F B2 74 32 EA 8C 90 88 9E 8B CC 21 66 82 76 2D A5 09 27 AC 3F C9 71 BC 0C 86 57 14 37 BC 87 50 A1 F3 9D 9F 27 C2 2E F0 01 10 D6 7F A8 78 AC DB 93 A7 40 42 84 74 8D 15 08 6D 6F EA 02 E2 68 20 BE 3E 70 18 5D A8 08 BA 93 7C D7 0B 8C 76 C3 6C EB 2C 2D BD 59 70 63 83 3D 26 A6 76 D8 11 A7 A8 E9 AA BF D5 EA 99 F1 08 10 9E 31 58 F1 59 99 ED 94 EB 53 64 49 0E 0F 1D 7A 10 3C FA 19 06 AB 49 A8 EE A9 21 2A 29 86 87 C7 8C 31 C0 E9 CA 57 99 E3 DC 32 F7 89 21 C7 72 5B 58 85 B8 65 6B D6 56 D6 C2 9F E5 03 6E BB B4 9D 09 FE 34 A2 DE 3E 86 8F FD A9 6D 8C 86 BC 4F B6 0F 1B 16 1E C4 36 CD F4 80 63 13 36 A7 2F 49 22 42 3E E9 FD 8B 0B BC E0 BA 2A 28 B8 7B 05 A9 72 23 17 51 30 BE CC CB A3 0B 7F 73 A4 9A E7 DA E6 D3 B1 92 0A CF 43 F3 6D D6 16 01 F5 0F 69 2C 67 72 39 BB 1B 87 F8 52 B7 AD 2D 47 D0 82 FB 1F EB 36 CC CC 19 40 F5 EA C1 B2 76 C3 3B E9 0D 8C 3C 1A 05 91 B4 E9 AA 9B FF 40 EF E7 36 D8 94 B2 76 99 B6 27 4E E9 01 A3 E5 A3 CE F1 7B 4E 6D F2 53 05 33 9D 1A C5 3C BC F3 E8 BF 84 0F A8 21 C0 10 CD D1 26 1B 34 80 AE 7B 48 97 45 F6 DF 8F 79 C3 4E C6 47 34 E4 FD 0D F9 20 D2 62 20 FE 96 32 73 69 04 6F 44 8B 68 AA A6 30 4C 28 BB C1 B4 0B 6B BC EF CD DA CA 45 C2 5D 71 C2 53 DD B0 92 3D 0F 80 37 C2 A9 8D 89 E3 D9 11 1C 98 F2 7E 4A 9A EE 6D 50 E0 04 E3 97 71 F2 AC 8D 5D 8A FE 75 F0 B5 E8 AD 3A 25 4D 2F 0C 82 1D 94 5A 7C 63 32 3E E3 82 95 80 2A 6F BB BA 51 38 1C EF 9E DC 1D B2 31 A9 F9 AA 05 27 EB A9 4A 58 D1 21 DE 1C 55 88 3F A5 EB 27 F4 CF DA DF 67 7E 24 5C A0 B6 BC 1F 4E E1 3F 70 86 62 DB A1 BE 5A 88 C6 20 22 B3 F3 DD 9D 08 1B 78 15 55 EC 47 76 AB E6 4C 77 35 D3 08 9F 52 9B 9F 42 58 28 A4 8D 96 F0 BF C1 42 90 1C 18 A2 98 25 86 B0 9B 3B DE 75 C1 87 4F 9A 7E FD 03 9F 0F 95 E4 39 04 FE F4 B7 DA 57 BE F0 D8 09 B6 42 F4 CD CF 8E 38 98 6B 29 77 D3 19 63 03 2D CC DB 6C 54 85 18 5D FA AB FE CE 46 6A 1F 8B 63 0F 67 27 55 E7 F4 03 7F B1 52 7F 2E 01 F7 8C B9 9F F6 03 4F DD 05 D2 3A D7 2D C9 1C 3D A1 2E 60 7A 0A E5 7B 72 C7 8D 18 9A FA 4B 3F 16 23 17 21 6B BF 32 9B A2 E9 64 F2 E4 F9 B2 65 81 8A 99 F7 23 36 8D 57 E7 A6 26 26 1F 7F 19 F7 5C 5B C3 08 A1 D8 27 C3 BE 98 26 B3 50 63 F0 05 6A 29 19 05 CA 4A 12 CF 33 95 27 53 14 A2 5F D0 37 B6 03 0E 0C 72 44 E4 DB 89 B3 E0 D6 0D AA 3F 1F DF E8 86 E1 55 D2 6B 15 AA 98 A2 92 E9 1B 2E 20 8A 6B C8 6B 0F 22 37 FD F5 36 06 BB 3F 03 23 9F 40 08 1C 58 DE 20 74 BB C2 7B 0A 81 FB 6F D8 89 DB 03 DA 89 86 B1 40 A3 AB 8D A8 CD 2D 9B 97 98 20 6D 73 8F 35 F2 26 F2 8B A1 47 35 27 9D 85 BC 65 4E 7A 42 FC 39 1D 62 24 7C 1A B1 01 CC FA 40 15 FC 4B 2F CE 1B 9B 0B EB 07 F7 12 55 BD 7C B1 5C BC AC 53 16 DB 34 CF D3 91 6A 92 9E FA E8 A2 6B 4D 49 36 3F 33 79 49 4D 52 EC 1A 3F 0A EB 9E 61 E8 8D FA A2 D4 A2 E4 26 1B 2A A2 CA 6A 94 35 8D 77 CE 0A 7F 99 7D D8 53 61 28 F7 27 43 38 99 05 9E B9 7E 9C B5 61 84 AE 0D 9C 44 EF D1 54 B8 3F B0 E8 D4 FE EB 42 A5 DA 24 07 28 F5 21 93 A2 53 30 18 26 AB 3C 99 88 EB 0A C8 D4 6E 76 25 A7 65 13 59 16 FE C0 E7 23 BD 6D 4D 5B DC 4C 02 8A 93 56 B5 3D B0 ED 2A 09 CD 01 9A 5A A0 62 FF 4C 23 7E 1C 2B 33 AD 29 B8 7B 4F A6 71 7B 1A C1 3E 2D B9 2F 78 56 CF D2 65 EA 02 E9 1D 4A 27 CD 94 B0 67 79 E3 9B 2B 9C 50 1B 78 ED 06 3C 06 C0 07 6E 53 49 73 2C 74 59 AF A7 92 16 A3 DA 35 B7 B9 B8 D8 CF 58 3E BF 43 BF 43 E8 C5 B7 36 B0 7E 65 AF 6F 75 89 C5 76 87 40 19 9C 4F 30 54 18 B2 09 74 4B D6 A5 29 22 76 E8 19 7C A5 A9 B0 98 12 06 0A 9E 87 F3 1F 75 44 32 CD 47 FE 56 7F 84 4E 73 EF 28 A3 C6 78 08 94 1D 6A D2 E4 31 20 99 63 D4 F7 A8 84 CE C8 5E 43 45 01 3F BC 9A D3 0C B7 FF B0 A8 3D C7 EE D7 74 76 50 9C 61 67 E3 E2 19 BA DD CB AF 8F A2 CD 55 56 1C 32 5F 16 AA AE 24 2B 10 D4 A1 F9 2D 91 93 1F C5 BE 7D 5F EC 4B F4 E5 3D FF 10 3B F7 2D 27 F1 97 FF 46 BF 6E 48 1C 7B 49 BE 1F 7A F8 79 0A A4 C4 2D 73 C2 FA 1A 71 56 6E A7 6B 1A 46 83 DA 80 47 1D E7 FD 03 3A 98 51 E5 3D 30 71 05 41 D5 F5 8F 7E BC F1 47 6E D2 2E 9B 6C 18 30 D0 92 F1 BD 5F 67 D4 5D BA 75 2F C2 5F 98 64 5F 2C 7B 72 8F 77 F9 7D 07 F9 66 9B 21 6F B1 ED F0 22 B4 0E 4D 3B 79 42 CD 84 66 F7 6F 57 B4 CD EE 22 B0 DB 31 74 12 DC D8 B3 54 07 04 18 77 D8 80 D4 FD 33 AE 57 64 E1 23 37 68 4D 1A F0 36 ED C5 FA 97 20 93 8D 37 A3 A1 84 CE C9 4B 2B E8 15 CB 3D 9C 10 08 A1 FE 7E 51 B9 F7 F5 0A 8A 65 FF 6B 7C E6 01 2A ED BA E2 A7 26 32 F9 79 F5 2C 16 81 AA DD 15 1F D2 A4 C7 B7 26 7A 5A C6 CE EA 59 26 68 07 6F 10 E8 6B 3F 22 B3 B0 64 7B 05 AA 76 98 0B 03 1D 6F 25 B6 08 54 A8 87 8A 84 92 29 9A 2D A4 59 81 BF 52 DE 24 F9 5F C2 5A FA 1A D7 EE 03 6A 00 C3 8E 28 97 31 55 CC 07 1A 98 11 1E F3 E8 E3 5A 6B F1 91 87 4A 74 83 7E C1 DF 06 AF 2B C6 B0 B0 56 F6 96 D0 C4 AC F3 A8 7C D8 4A BF 50 66 09 AA D1 0F E8 8F 7D DE 70 56 8D D4 68 E3 1A BC C1 EA 9F 6C 8B F3 8D 04 D7 24 95 E5 E9 FC 72 36 D7 9D 01 C9 0B 81 46 01 4C B7 BB 48 36 B4 3E 52 3C D3 0E 24 36 64 94 CC 23 F9 A0 86 56 36 0E 67 B1 EF 86 1D 93 7F 58 3E B6 91 49 14 31 F6 EB C3 5A DF A8 C8 26 2E 29 37 7A 23 7C 3B D9 C0 53 33 52 02 AC 6B B5 FB F6 A1 6D 13 E4 87 CA 56 3A B2 0C 75 92 75 5C A0 1C C2 31 97 E8 1B 13 AC D7 E1 47 E3 E7 CE 86 FF 85 AE E2 BD 5C 6F 3F 65 FA 11 C6 C0 12 CE 86 19 C8 E2 72 8E B6 4E 88 73 E0 C1 31 86 42 F7 51 05 68 E0 73 99 0E 69 86 59 C9 4A 77 CA 76 10 AC DE 95 F9 17 4A 8A 5B 14 A8 16 57 C4 16 60 CF 0E 48 EE D0 DC 63 8B 9B 46 6D 96 41 1D 38 8B DF 70 31 95 3A F7 A8 1F B8 4D 7A BA E0 CC E9 58 B5 2A 87 42 43 63 DC 12 47 AC 32 49 D7 02 87 DB C9 5D 10 BC 93 65 F4 3C C3 FF C7 28 86 14 4D 4C 70 FD FE 5A 06 EA 01 C5 27 FA 46 9B 98 5E 71 D5 BE C1 0A A2 45 7F 09 1A 7D 12 4F 38 49 09 77 1B 8A 39 48 27 22 4C B1 A3 AA 68 8E 1B 73 B0 A6 EA 78 AA C3 33 16 3B 00 69 4A D5 07 06 42 65 50 2E F2 60 8B F0 9E 8A 7C 05 B7 DC 85 E7 EF 10 FD C8 FE 80 A9 C6 B0 46 35 0F 77 17 6C 7D EC 60 24 D9 21 76 AC DF 6B B2 FC B0 75 D1 3C 2D 69 60 C2 4E CD 62 58 72 D8 AC B3 F5 75 56 80 E3 D1 9B 95 1B E7 CD D1 C3 C2 FE 50 DC DD 10 D5 89 43 7E FB 90 54 4D 42 13 1A 47 20 DB 18 E7 BA 3D 2D AF 53 DC 8F 37 08 8C 3B 52 00 A4 62 AB 22 93 46 05 38 A8 C2 FF 2C F5 F8 5D B5 4B 04 7E 48 F7 03 75 DA C8 B0 E9 E0 0B 3B 7E 57 0A 1A 53 98 EE 1A 2A 48 C7 FD 22 D4 B0 E7 5C B3 75 8F B7 4E 8A EF B0 29 6C A9 C8 02 24 4E D6 3B 2C 82 4E F3 1E 62 94 40 64 2E 77 BB B9 3D 1E F4 BD DD BD FA DA 25 09 65 8D 5E 1B 3C 2E 80 22 11 D6 1D 32 B4 7E 89 B0 F6 85 83 C3 34 78 57 3C 97 DF 05 01 6C 8F 91 25 95 D8 BD D8 86 7C 8C F0 50 88 25 10 6D E6 E2 DA 76 31 80 55 2E E6 1F 37 A1 82 8B B5 FC 2B 71 5D 9B E6 89 CD 14 BB 49 28 BA 1D 49 71 08 A7 D2 B5 A4 1C 9C 1B DF EF C3 E7 55 2B F4 2E 4E 93 4A 74 B6 A9 47 18 23 9C 44 08 3D 13 06 24 41 06 1E BF 88 BC 3D 1B 75 92 80 C7 78 A4 CA 5A F1 79 EF 3F DC F5 5F AF 49 73 68 96 C9 DB 8E F2 A7 B4 2D 0F 50 64 0C EB EB F6 08 09 0A F5 0A 2C 88 5E AE 44 25 89 DF 7F 4C 5D 0C 73 47 3C 1A 2B 41 7B 9E 28 48 39 0A A2 D8 04 78 90 DE D5 88 9E C7 00 5F F8 63 CD BF 8D F1 5C 12 CE 7E 2B 09 D0 4C 42 7A 84 0F 36 C6 C9 5D AA 44 87 23 4A 76 76 94 1A 7A 2D D6 23 B4 84 EF 6D 3B C6 01 B2 F7 20 09 40 51 E4 80 58 5E A6 A5 97 2F 75 CE E7 97 78 F0 0B F9 31 98 CE 6C 40 4F A4 B3 14 AA A5 89 AA F9 9B 21 11 69 A8 E0 56 B0 F1 C9 CC 44 83 1C 32 E3 79 14 1A 5D C8 F3 41 C5 9A CE A1 B7 5B C2 53 22 49 15 FE 52 A9 38 DB BD 7A 69 83 06 0F 69 77 98 D1 F4 93 3C 83 37 B7 21 A5 D7 2A 9E D9 A3 BC 1C 9D 4F A4 22 51 4C 44 B9 35 C9 8E 41 FF 0D 6D FC BD 12 F5 CA 3E F9 EE 75 1D 01 9B CD 34 B2 C6 4A 4B 9D 2B 79 A5 12 52 BF FF F4 42 62 39 53 58 8E 82 F6 94 2C 00 97 0E 8A B3 5B 73 3D D6 CF 3E D5 14 BB 2D 5B E6 2D 78 88 D5 E8 33 BC E9 C9 A4 2D 36 41 F5 DA 5D 68 6E B6 B9 93 89 E0 15 E5 68 65 48 42 FA 9E 16 20 5A C8 CB 8D 61 52 E1 23 DE 0A 40 8C F5 6F 86 AD 36 F6 20 9E D4 6A B2 D9 7E 5E 3E F3 D7 C8 A8 25 CB 49 E5 FE BA A8 4E 34 41 B4 CB 9B AA BA 8F B9 53 F9 0A 67 AC 3A 02 D2 55 AB E3 6F 8C 79 E6 C0 2E 70 5C 6C E5 89 17 F2 A4 C8 8C 58 58 8C 3C 22 10 68 0D 9A 70 63 59 F6 C0 60 6F 1E B6 9E B5 69 B3 1B 0E D8 F8 8C 5D 06 2F 42 4F 69 BB 83 DF F8 20 8A BF 74 30 4A 57 C8 FE 13 AD 8B 09 B9 92 7A DD 53 DA A9 33 00 85 53 88 2E 58 3D A4 02 ED D0 E9 25 E2 EE 7A C0 08 B3 B5 BF 7D 36 07 0D 87 F7 6B 68 BF C6 7B A6 E4 B6 D7 76 FA BE 23 E6 53 94 D3 54 94 6D 39 87 3F 74 F3 ED 5C D6 E0 4F E8 5C AD 86 3E E7 E1 12 32 51 F0 E9 42 B5 12 46 26 B1 86 AD 19 1D A2 81 4E 3E F2 FF 8A 5F 9C 80 02 56 70 AA 0B 0D 2C 61 DA B9 1C 5A B3 6F 2E C5 32 C0 48 FE 19 9E F8 F4 30 3E E2 2C D8 A5 81 E9 C9 6B 44 6B B7 95 5D 94 0E C5 63 D7 78 FD 58 54 E1 19 E2 22 B5 48 10 D5 87 28 F7 A3 30 43 9D 69 B5 D5 38 D5 05 22 77 FC DC 93 62 08 CD 58 19 E4 65 E6 AC 05 6C FE C9 02 3A 28 48 77 AF D9 63 40 25 45 CF 89 4C 0A ED 60 C9 A8 75 A0 68 79 69 8C 13 5C 0C B4 FD 8F 27 8E BA 16 E5 1E AA 78 84 AF BE BB E9 09 9C 51 8A 10 2B DB 0E 7E F4 E2 A4 DE 15 85 A2 E2 40 E7 37 56 A5 AF 91 4E EA 80 E3 8F 3A F3 28 15 8D F4 FA D1 EF C0 09 98 43 1A A3 98 CA 94 BB DD EF 98 E1 98 6E AD 53 9F 48 E5 9E A5 1B 7A ED EE CC 5C 8B 05 AF B9 76 54 E1 C5 3A 91 00 A8 CE 1C AC D8 FC B6 2D 96 D3 CE E7 81 3F B0 E7 D5 39 C4 E0 E8 85 D4 18 51 9E 41 BA FE FA 32 0E 4C 4A 10 25 75 21 9E 0E 5D 29 A4 A0 6B F2 EA FF 70 9F 38 85 35 94 B6 90 39 DB 0D 25 E0 FF 89 97 93 94 88 84 8A BE D2 97 AE BF AC 2A 28 30 F4 A2 59 95 A1 F0 66 86 A5 2A 55 7A F0 35 0A CA CC DC 61 32 A8 B8 5C 47 90 19 91 E0 1E E1 1C BE FE A4 A3 02 27 7A 30 F6 10 11 CF ED 34 3F 18 74 E8 A5 23 C4 D9 73 5D 46 AA A5 EC BA 6E CE 40 EE E1 2D A0 9F CD DC B6 6D 6E CE 3A 94 A0 90 4D 7E DD 38 A9 52 27 3E 3D CF 94 C3 A7 07 F1 46 30 DB 0D BF 9F 30 12 25 FB 51 42 3F 74 49 3F 6C 1A 20 91 96 7C 1F 62 6C DA CA DE 99 48 74 D4 E2 5E E4 B8 AE BA 55 B5 95 E1 51 57 5B 0D B8 F9 4A 1F 86 CD FF AB 69 80 6F 65 76 DE 10 DF 91 EE 3F C4 69 81 76 6A 03 BB C5 73 5F 59 5A 0D BE 64 38 66 D0 75 EC 93 E7 52 E5 A6 3B 8F 99 8B A4 5E 6E B0 53 F5 4D 21 F4 D7 3E 7E 18 59 4F 83 56 E9 09 78 9C 90 9E 73 A2 87 F6 CC F4 DD 7C E5 24 BD DB E6 12 AC 48 28 96 98 B8 8F 92 20 F0 3D 22 0C 0B 34 93 9D D0 19 0E 9C 81 C2 FD A7 B1 09 56 E0 B8 C1 49 4F 76 9A 47 5A 69 17 32 99 61 76 05 F8 66 80 C3 D5 16 9D 78 88 C8 9F 2D 44 60 C5 44 18 C0 5F 90 59 52 9C 54 A8 C1 21 73 E9 B8 23 CC 8B A2 E9 E1 E9 6D 7A AF 2B 59 3E EB E3 E4 65 9C 5F 31 D3 EF 18 33 09 49 C8 C2 36 D5 4B 6C A4 79 66 B6 5B 8F C8 5F 74 88 5C 89 45 57 A8 1F 60 A0 2C D0 C9 6F 8D E5 D7 EF 64 47 B3 2F 5E D1 F7 A5 51 B2 E7 66 14 5C 9B 94 6B 47 C4 B1 D1 7E 25 01 70 9B E6 F9 02 B6 84 30 42 4C 9A 10 D9 95 FE F7 D1 60 05 9B CB 58 BE 92 A3 BD 7E B8 D2 CA E3 2D E3 EF 80 E5 86 64 BC BD BC 28 6D B8 C4 37 FB BD C3 5C BD 67 FA 22 98 79 22 5C 99 E2 90 02 FB 3F 09 10 A5 71 A3 95 17 AC 14 8F 6F 48 8F 39 B4 4E 23 78 2D FF FF 77 D9 E8 B9 F6 5D E0 39 44 92 C7 56 E9 25 F4 52 1C 6A CE 4C A2 BF 44 94 97 D4 42 3E 71 FC 59 68 16 67 AB DC 7A 4A 96 1E F1 F3 3E 85 F2 4C 2B 1E 2A 78 04 73 28 60 87 4B D9 4D 62 05 3C 33 DA 0B 13 90 EC 62 AF 6A 15 30 D2 46 1D 45 EA 4B 8A 23 7A D6 8B C5 89 6C 8E CE 6E 84 03 82 2D B5 19 E6 20 93 01 C2 24 84 74 23 79 F1 F4 99 FD 7C CC 0A B4 B4 18 5D 34 09 9F EE CF 6A 89 33 B3 DF D2 00 AC 4F 3E D9 A6 99 C8 13 A5 6B C8 2C 3C 30 B0 FD B7 13 CB FB C5 21 3B 1A EB 90 FA C1 4F 08 99 04 5D C5 8A 72 42 30 A4 49 88 5B 1C 31 14 1F 12 A6 8A 52 E9 1C 09 16 86 A2 81 19 30 50 9F A9 66 31 1B 6D 97 31 01 DF A9 77 F5 EB 59 AE 37 90 02 63 FE 85 25 79 3D A1 C2 30 12 83 50 3F 77 CA 2A 28 3C 87 84 C4 BE 4A D1 8E A4 A8 89 DD F7 21 03 9E 6C D3 6E AA 0A 25 27 8D 66 E3 C3 7E 17 95 0B CE E7 2C 37 55 80 85 CA 61 83 94 E3 63 0A 4F B0 CB C5 42 CE 0F 00 3D 4B 77 49 A7 96 22 E2 E0 AF 43 6B CE F2 D5 5F 0D F6 4F DB 37 D1 EE 8D 69 97 92 CD 2A BC 45 9D 3B 47 27 37 6B E3 DF 4B D8 FB A2 67 8F 7C 19 95 EE 98 E9 3A 05 28 8D C9 26 56 CB E0 4E A8 99 F9 CD 80 6B 65 18 B2 AD 66 E2 1A 14 7A 03 2D 24 E3 90 12 6A 25 05 2D 5C 32 7A 1C 13 D4 B6 F5 6D 4E A2 5D 71 32 88 50 1D 0F B6 DD 61 23 F7 DC BB 5C 27 B6 EB 7F 5B 89 5D 6E 8A 19 CF 36 D2 7F E6 55 0F E5 18 F9 9F 49 6D AC E8 5D 8C 2A 6B B7 D8 6F 00 ED 2A F0 B0 5F DE 96 D4 3D 23 C9 B1 75 EE 91 EC B6 31 DF 50 2C F9 C8 BD FD F7 A6 BC 98 02 BA 9C 23 24 6C A4 3E D6 2A 5A 65 4C 39 72 0C 8E 43 29 08 4C 21 B1 A2 29 76 6F 19 03 6A 2C 8D DB 9F 2D A5 6F 01 34 A6 6C 80 3D A1 2E 90 FA D5 56 A3 89 C0 B8 09 04 31 60 73 A5 7C 8F 04 92 7E A3 7F 60 24 B7 69 E8 5C 5B 53 55 D9 03 B6 32 6E 0B BB 2D 57 AC C5 7E 70 58 C3 4A CE 35 E9 26 AB F6 B4 B7 AE 5D 03 82 8B 30 D8 9D 30 9B 93 4C B0 48 D2 D6 3B 04 95 20 18 14 EC 75 58 E8 42 DE 1E C7 B9 3F BF 86 E9 3C 82 D8 62 0F 97 4D D1 D8 7D EE B1 1C C0 15 17 A8 D4 A9 D2 5B 2F 12 95 C2 7D E8 4C 51 6D 95 88 C8 33 7E 69 24 8F E4 2F 7F 22 20 32 BD 01 C8 71 C6 C1 A8 3C CA BC 8F 64 37 5A 4A 15 A6 36 F5 31 34 7E 70 78 5B 1C 8F 0B 14 28 9B 43 D1 49 3B F7 91 DC 12 F5 EF C6 0D 39 FE B4 6B 4D E1 BA 87 96 CB 75 87 B2 78 A1 D7 F6 7D DA ED 77 FE 42 DE 28 29 DF 1A 1F 11 CA 70 BC AF 9D 7D 5E 07 23 C8 8B 2C F7 1A 40 A2 15 73 2B 92 DE 98 57 E7 3D 43 A2 2A 8C 66 6A 0C 9D 15 A4 65 17 F5 A5 15 F7 CF 4B AE D0 46 E6 4E 62 E2 6E D9 FB 64 17 A8 96 57 8A 8B E8 89 C3 73 A8 FB 49 92 F6 4A 51 0A BF 2E 33 2E F6 6D BD C0 C7 0C 4F 69 8D 10 BB 46 C8 B4 88 0C D8 ED 2E 2B 0D 1E 77 E3 C6 52 E6 6D 56 80 5E A6 EA 34 86 5D 3B 3D EE 19 F4 62 9C BF 7F B1 6E 78 A1 75 58 EB 94 DB B9 1F 9A D9 72 EB 1E 60 58 87 46 B3 9D 2B 2B D7 04 8A 13 30 CD 35 16 C2 0E AB C3 93 B7 F4 F8 25 C5 BA 20 B5 62 64 A6 78 D7 E9 FD AD BC D0 69 F9 A7 AF C1 9D B7 8A B2 DA A6 CF F4 5E F4 FB 20 52 2A F2 3D 2F C1 CD A5 70 3A 8F 1C 4D 93 77 DC 35 1E 77 9F B9 15 7B 84 0A 7B 69 86 20 CC BA 7F 60 6D F8 D4 0E 97 9A 90 62 ED 9F BE FC 65 C6 A1 BD 58 D2 64 3A E8 73 69 37 B7 33 80 6F 5F D3 6B 7A 24 A5 62 A0 23 0A B9 51 7F AC E6 A0 E3 95 DA 61 97""" - + """ 31 9D 14 F5 35 51 07 F7 6B 8E 3E 0B 5D C2 B9 C1 70 16 9E D2 2D 75 62 5E 62 82 CB 8B 22 A9 E9 DA 91 37 97 3B F9 95 AB 12 72 D1 7E 8C 87 2C A8 D1 AC CD 40 7B B1 5B 3E 4F 29 CA A6 D2 D8 9C 38 15 42 E6 66 35 9E C5 41 2C 4D BC 22 1F A1 AD 24 CE 4C C1 B2 E2 E0 A4 A4 DF E7 01 8B 10 90 C3 38 02 A9 0F 49 AA 8B 86 EC 58 B2 AA 79 6E FF 1E 1F 2A 35 3F 3D 96 A7 DC D0 F6 E5 18 4E EA C8 C5 72 76 3E 74 2E 12 05 78 6F FC BD 07 50 CA AF EE C2 11""", - received[1].toUHexString() - ) - - assertEquals( - """00 00 00 0B 01 00 00 00 00 0E 11 11 11 11 11 11 11 11 11 11 7C CC CC 8A 82 A1 2F A3 F6 08 8D 5C 7B 64 F8 BB 4F 09 87 B1 7C E3 01 53 5F C0 32 A8 6E A4 0A 1F 49 38 E5 FD 7F 20 52 A3 1E 66 A5 43 85 C4 96 97 3C 8F 2A 33 98 D7 A6 90 50 37 BE 76 2D 94 CE 1F D8 63 07 DC D1 5A 6F F0 FA 1F 41 9E 74 BE 8D FC 61 2C 66 3F BB 4C FB 9A 02 53 FF BE E5 FD 52 B7 FD CE DB 80 C0 6A 55 14 31 31 0C 8A 7D 24 DC EC 8C 45 62 ED D9 F6 DA BB EA C5 6E 76 66 11 F4 CB 2B 3B C7 45 6C BE 6F ED 9E 1D 2B 8A ED 3B C1 5B 06 DC 75 58 C9 66 13 4C 7D EA C5 F9 A4 D1 37 EF 2B BE 98 E3 37 1C 30 17 20 80 98 AD 5F BC 85 98 5B A1 7F 9E AE 54 0C 36 B0 6F FA 4A 5B 6F DC 7E B1 9E 99 F6 07 16 43 11 7A BC 82 F7 FB B2 95 7C 29 37 AF 38 70 6E A8 75 12 84 73 CF 15 A3 65 B9 2B E5 0A 01 30 67 A2 D2 BF 9F 30 AF 4D A5 A6 EA 4A B3 E4 BB AC 15 E3 FB CD FC B0 52 69 05 8D BE A0 11 1D A7 AB 65 6D F1 68 06 71 89 4F 0A 7E F4 68 A0 71 21 07 E4 85 41 76 16 07 78 2E C5 30 A6 2F 5D C7 DB EF 24 61 20 E6 6D FF 01 28 0D D6 73 42 BF F1 65 EA 7E DE 81 94 89 EB D0 65 8D 94 39 BE 89 7F B0 B3 0C 74 2F FA B4 2B 86 22 08 67 EB FA 62 83 FA BD CA 9D 92 95 A6 B0 BB 0C 76 07 C4 DC B9 E0 CD 67 AB 84 4D CC 55 52 E5 22 CD FD AC 08 35 81 36 9A 2D 7B 56 66 E8 B4 D9 A5 AA 7A 57 F2 F6 FB 20 A1 78 D5 5D F3 7C E4 7F 34 53 59 52 38 06 35 AD 6D 7A 97 99 AA 97 1D 9D 4A E4 22 7A 11 0C EA 16 27 7C 8A 9E F2 5A 82 D5 23 C3 01 BF D7 43 99 E7 26 25 AA 5A 27 29 ED 84 7F 9D 46 47 F8 C3 94 94 D7 C8 27 9F F7 93 16 4E 57 62 FC AC 32 2E A8 9F B2 62 EA 45 B0 53 A2 6C 52 D2 76 5F 48 00 93 5B 95 24 1F 3C E7 EC 40 26 66 0F C7 7D 30 91 A5 F2 6A 2F 2D CB 24 0B A3 F8 71 23 CA 31 A1 42 17 AC 9B 25 5A 2E 46 2D BC 34 DE 70 DA EF 4C E1 2D AE 2A 88 66 19 EE 35 02 C6 68 2C C4 0A 90 82 CA AB 42 D6 57 01 62 22 0D DF 65 6A 7E 6E 68 07 1D E6 1E DB E3 E6 22 F2 9A 36 F4 25 06 FA 91 83 9C 98 EC FB FD F0 F9 62 97 E6 37 30 F3 B3 09 46 D9 7D 7F D5 51 FF 8A FA B7 33 C9 15 AC D3 93 B7 8F 36 E8 1A 85 42 E5 C5 00 E6 28 9C FA 6C""", - received[2].toUHexString() - ) - } - - private inline fun buildLVPacket(crossinline block: BytePacketBuilder.() -> Unit): ByteReadPacket { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - - return buildPacket { - writeIntLVPacket(lengthOffset = { it + 4 }) { - block() - } - } - } - -} \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/network/framework/AbstractCommonNHTest.kt b/mirai-core/src/nativeTest/kotlin/network/framework/AbstractCommonNHTest.kt deleted file mode 100644 index fa0e6fc9f..000000000 --- a/mirai-core/src/nativeTest/kotlin/network/framework/AbstractCommonNHTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.internal.network.framework - -import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory - -/** - * Without selector. When network is closed, it will not reconnect, so that you can check for its states. - * - * @see AbstractCommonNHTestWithSelector - */ -internal actual abstract class AbstractCommonNHTest actual constructor() : - AbstractRealNetworkHandlerTest() { - - actual override val factory: NetworkHandlerFactory = - NetworkHandlerFactory { context, address -> - object : TestCommonNetworkHandler(bot, context, address) { - override suspend fun createConnection(): PlatformConn { - return conn - } - } - } - - - protected actual fun removeOutgoingPacketEncoder() { - } - - actual val conn: PlatformConn = PlatformConn() - -} - -internal actual class PlatformConn \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/package.kt b/mirai-core/src/nativeTest/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/nativeTest/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/test/NativeTestWrapper.kt b/mirai-core/src/nativeTest/kotlin/test/NativeTestWrapper.kt deleted file mode 100644 index 581f3f558..000000000 --- a/mirai-core/src/nativeTest/kotlin/test/NativeTestWrapper.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.internal.test - -import kotlinx.cinterop.toKString -import kotlinx.coroutines.runBlocking -import net.mamoe.mirai.internal.local.main -import platform.posix.getenv - -internal actual fun startNativeTestIfNeeded() { - if (getenv("mirai.native.test.main")?.toKString() == "true") { - runBlocking { main() } // If you see unresolved reference, create a file "TestMain.kt" in `/local` and add a `main` function in it. - } -} \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/test/PlatformInitializationTest.kt b/mirai-core/src/nativeTest/kotlin/test/PlatformInitializationTest.kt deleted file mode 100644 index b7bebc0bd..000000000 --- a/mirai-core/src/nativeTest/kotlin/test/PlatformInitializationTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.test - -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.test.StandardTestDispatcher -import net.mamoe.mirai.internal.initMirai - -/** - * All test classes should inherit from [AbstractTest] - * - * Note: To run a test in native sourceSets, use IDEA key shortcut 'control + shift + R' on macOS and 'Ctrl + Shift + R' on Windows. - * Or you can right-click the function name of the test case and invoke 'Run ...'. You should not expect to see a button icon around the line numbers. - */ -actual abstract class AbstractTest actual constructor() { - actual fun borrowSingleThreadDispatcher(): CoroutineDispatcher = StandardTestDispatcher() - - init { - Companion - } - - actual companion object { - init { - initMirai() - initializeTestCommon() - } - } - -} \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/testFramework/DebugProbes.kt b/mirai-core/src/nativeTest/kotlin/testFramework/DebugProbes.kt deleted file mode 100644 index 5730500bc..000000000 --- a/mirai-core/src/nativeTest/kotlin/testFramework/DebugProbes.kt +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2019-2023 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.internal.testFramework - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job - -@Suppress("UNUSED_PARAMETER", "unused") -actual object DebugProbes { - - /** - * Prints hierarchy representation from [jobToString] to the given . - */ -// public fun printJob(job: Job, out: PrintStream = System.out): Unit - - /** - * Prints all coroutines launched within the given . - * Throws [IllegalStateException] if the scope has no a job in it. - */ -// public fun printScope(scope: CoroutineScope, out: PrintStream = System.out): Unit - - /** - * Returns all existing coroutines info. - * The resulting collection represents a consistent snapshot of all existing coroutines at the moment of invocation. - */ -// public fun dumpCoroutinesInfo(): List - /** - * Whether coroutine creation stack traces should be sanitized. - * Sanitization removes all frames from `kotlinx.coroutines` package except - * the first one and the last one to simplify diagnostic. - */ - actual var sanitizeStackTraces: Boolean - get() = false - set(value) {} - - /** - * Whether coroutine creation stack traces should be captured. - * When enabled, for each created coroutine a stack trace of the current - * thread is captured and attached to the coroutine. - * This option can be useful during local debug sessions, but is recommended - * to be disabled in production environments to avoid stack trace dumping overhead. - */ - actual var enableCreationStackTraces: Boolean - get() = false - set(value) {} - - /** - * Determines whether debug probes were [installed][DebugProbes.install]. - */ - actual val isInstalled: Boolean - get() = false - - /** - * Installs a [DebugProbes] instead of no-op stdlib probes by redefining - * debug probes class using the same class loader as one loaded [DebugProbes] class. - */ - actual fun install() { - } - - /** - * Uninstall debug probes. - */ - actual fun uninstall() { - } - - /** - * Invokes given block of code with installed debug probes and uninstall probes in the end. - */ - actual inline fun withDebugProbes(block: () -> Unit) { - } - - /** - * Returns string representation of the coroutines [job] hierarchy with additional debug information. - * Hierarchy is printed from the [job] as a root transitively to all children. - */ - actual fun jobToString(job: Job): String { - return "" - } - - /** - * Returns string representation of all coroutines launched within the given [scope]. - * Throws [IllegalStateException] if the scope has no a job in it. - */ - actual fun scopeToString(scope: CoroutineScope): String { - return "" - } - - /** - * Dumps all active coroutines into the given output stream, providing a consistent snapshot of all existing coroutines at the moment of invocation. - * The output of this method is similar to `jstack` or a full thread dump. It can be used as the replacement to - * "Dump threads" action. - * - * Example of the output: - * ``` - * Coroutines dump 2018/11/12 19:45:14 - * - * Coroutine "coroutine#42":StandaloneCoroutine{Active}@58fdd99, state: SUSPENDED - * at MyClass$awaitData.invokeSuspend(MyClass.kt:37) - * (Coroutine creation stacktrace) - * at MyClass.createIoRequest(MyClass.kt:142) - * at MyClass.fetchData(MyClass.kt:154) - * at MyClass.showData(MyClass.kt:31) - * ... - * ``` - */ - actual fun dumpCoroutines() { - } - - /** - * Prints [job] hierarchy representation from [jobToString] to the given . - */ - actual fun printJob(job: Job) { - } - - /** - * Prints all coroutines launched within the given [scope]. - * Throws [IllegalStateException] if the scope has no a job in it. - */ - actual fun printScope(scope: CoroutineScope) { - } - -} \ No newline at end of file diff --git a/mirai-core/src/nativeTest/kotlin/testFramework/DynamicTest.kt b/mirai-core/src/nativeTest/kotlin/testFramework/DynamicTest.kt deleted file mode 100644 index 60d7da2a9..000000000 --- a/mirai-core/src/nativeTest/kotlin/testFramework/DynamicTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.internal.testFramework - -import kotlin.test.Test - -actual typealias TestFactory = Test - -actual open class DynamicTest( - val displayName: String, - val action: () -> Unit, -) - -@Suppress("ACTUAL_WITHOUT_EXPECT") -actual typealias DynamicTestsResult = Unit - -actual fun dynamicTest(displayName: String, action: () -> Unit): DynamicTest = DynamicTest(displayName, action) - -actual fun runDynamicTests(dynamicTests: List) { - for (dynamicTest in dynamicTests) { - println("=".repeat(32) + " ${dynamicTest.displayName} " + "=".repeat(32)) - dynamicTest.action.invoke() - println("=".repeat(32) + "=".repeat(dynamicTest.displayName.length + 2) + "=".repeat(32)) - } -} \ No newline at end of file diff --git a/mirai-core/src/unixMain/cinterop/Socket.def b/mirai-core/src/unixMain/cinterop/Socket.def deleted file mode 100644 index 777694743..000000000 --- a/mirai-core/src/unixMain/cinterop/Socket.def +++ /dev/null @@ -1,30 +0,0 @@ -headers = netdb.h - ---- - -#include -#include -#include - -static int socket_create_connect(char *host, ushort port) { - struct hostent *he; - struct sockaddr_in their_addr; /* connector's address information */ - if ((he = gethostbyname(host)) == NULL) { /* get the host info */ - return -1; - } - int sockfd; - if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { - return -2; - } - - their_addr.sin_family = AF_INET; /* host byte order */ - their_addr.sin_port = htons(port); /* short, network byte order */ - their_addr.sin_addr = *((struct in_addr *) he->h_addr); - bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */ - - if (connect(sockfd, (struct sockaddr *) &their_addr, sizeof(struct sockaddr)) == -1) { - return -3; - } - - return sockfd; -} \ No newline at end of file diff --git a/mirai-core/src/unixMain/kotlin/package.kt b/mirai-core/src/unixMain/kotlin/package.kt deleted file mode 100644 index 7df5cebc4..000000000 --- a/mirai-core/src/unixMain/kotlin/package.kt +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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.internal \ No newline at end of file diff --git a/mirai-core/src/unixMain/kotlin/utils/PlatformSocket.kt b/mirai-core/src/unixMain/kotlin/utils/PlatformSocket.kt deleted file mode 100644 index f0d317923..000000000 --- a/mirai-core/src/unixMain/kotlin/utils/PlatformSocket.kt +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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.internal.utils - -import io.ktor.utils.io.core.* -import io.ktor.utils.io.core.EOFException -import io.ktor.utils.io.errors.* -import kotlinx.cinterop.* -import kotlinx.coroutines.* -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import net.mamoe.mirai.internal.network.highway.HighwayProtocolChannel -import net.mamoe.mirai.utils.* -import net.mamoe.mirai.utils.Closeable -import platform.posix.close -import platform.posix.errno -import platform.posix.recv -import platform.posix.write -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - -/** - * TCP Socket. - */ -internal actual class PlatformSocket( - private val socket: Int, - bufferSize: Int = DEFAULT_BUFFER_SIZE * 2 // improve performance for some big packets -) : Closeable, HighwayProtocolChannel { - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) - private val readDispatcher: CoroutineDispatcher = newSingleThreadContext("PlatformSocket#$socket.dispatcher") - - // Native send and read are blocking. Using a dedicated thread(dispatcher) to do the job. - @Suppress("UnnecessaryOptInAnnotation") - @OptIn(ExperimentalCoroutinesApi::class, DelicateCoroutinesApi::class) - private val sendDispatcher: CoroutineDispatcher = newSingleThreadContext("PlatformSocket#$socket.dispatcher") - - private val readLock = Mutex() - private val writeLock = Mutex() - private val writeBuffer = ByteArray(bufferSize).pin() - - actual val isOpen: Boolean - get() = write(socket, null, 0).convert() != 0L - - actual override fun close() { - close(socket) - (readDispatcher as CloseableCoroutineDispatcher).close() - (sendDispatcher as CloseableCoroutineDispatcher).close() - writeBuffer.unpin() - } - - actual suspend fun send(packet: ByteArray, offset: Int, length: Int): Unit = writeLock.withLock { - withContext(sendDispatcher) { - require(offset >= 0) { "offset must >= 0" } - require(length >= 0) { "length must >= 0" } - require(offset + length <= packet.size) { "It must follows offset + length <= packet.size" } - packet.usePinned { pin -> - if (write(socket, pin.addressOf(offset), length.convert()).convert() < 0L) { - throw PosixException.forErrno(posixFunctionName = "write()").wrapIO() - } - } - } - } - - /** - * @throws SendPacketInternalException - */ - actual override suspend fun send(packet: ByteReadPacket): Unit = writeLock.withLock { - withContext(sendDispatcher) { - logger.info { "Native socket sending: len=${packet.remaining}" } - val writeBuffer = writeBuffer - while (packet.remaining != 0L) { - val length = packet.readAvailable(writeBuffer.get()) - if (write(socket, writeBuffer.addressOf(0), length.convert()).convert() < 0L) { - throw PosixException.forErrno(posixFunctionName = "write()").wrapIO() - } - logger.info { "Native socket sent $length bytes." } - } - } - } - - /** - * @throws ReadPacketInternalException - */ - actual override suspend fun read(): ByteReadPacket = readLock.withLock { - withContext(readDispatcher) { - logger.info { "Native socket reading." } - - val readBuffer = ByteArrayPool.borrow() - - try { - val length = readBuffer.usePinned { pinned -> - recv(socket, pinned.addressOf(0), pinned.get().size.convert(), 0).convert() - } - - if (length <= 0L) throw EOFException("recv: $length, errno=$errno") - logger.info { - "Native socket read $length bytes: ${ - readBuffer.copyOf(length.toInt()).toUHexString() - }" - } - readBuffer.toReadPacket(length = length.toInt()) { ByteArrayPool.recycle(it) } - } catch (e: Throwable) { - ByteArrayPool.recycle(readBuffer) - throw e - } - } - } - - actual companion object { - private val logger: MiraiLogger = MiraiLogger.Factory.create(PlatformSocket::class) - - actual suspend fun connect( - serverIp: String, - serverPort: Int - ): PlatformSocket { - val r = sockets.socket_create_connect(serverIp.cstr, serverPort.toUShort()) - if (r < 0) error("Failed socket_create_connect: $r") - return PlatformSocket(r) -// val addr = nativeHeap.alloc() { -// sin_family = AF_INET.toUByte() -// sin_addr.s_addr = resolveIpFromHost(serverIp).pointed.s_addr -// sin_port = serverPort.toUInt().toUShort() -// } -// -// val id = socket(AF_INET, SOCK_STREAM, 0) -// if (id == -1) throw PosixException.forErrno(posixFunctionName = "socket()") -// -// println("connect") -// val conn = connect(id, addr.ptr.reinterpret(), sizeOf().toUInt()) -// println("connect: $conn, $errno") -// if (conn < 0) throw PosixException.forErrno(posixFunctionName = "connect()") -// -// return PlatformSocket(conn) - } - -// private fun resolveIpFromHost(serverIp: String): CPointer { -// val host = gethostbyname(serverIp) // points to static data, don't free -// ?: throw IllegalStateException("Failed to resolve IP from host. host=$serverIp") -// println(host.pointed.h_addr_list?.get(1)?.reinterpret()?.pointed?.s_addr) -// return host.pointed.h_addr_list?.get(1)?.reinterpret() ?: error("Failed to get ip") -//// val hAddrList = host.pointed.h_addr_list -//// ?: throw IllegalStateException("Empty IP list resolved from host. host=$serverIp") -//// -//// -//// val str = hAddrList[0]!!.reinterpret() -//// -//// try { -//// return str.pointed.value -//// } finally { -////// free() -//// } -// } - - actual suspend inline fun withConnection( - serverIp: String, - serverPort: Int, - block: PlatformSocket.() -> R - ): R { - contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } - return connect(serverIp, serverPort).use(block) - } - } - -} diff --git a/mirai-deps-test/README.md b/mirai-deps-test/README.md index 4e75b3941..c0933b4b0 100644 --- a/mirai-deps-test/README.md +++ b/mirai-deps-test/README.md @@ -1,3 +1,3 @@ # native-deps-test -测试 Native \ No newline at end of file +测试 shadow relocation \ No newline at end of file diff --git a/mirai-deps-test/test/AbstractTest.kt b/mirai-deps-test/test/AbstractTest.kt index b15b8d94c..dcf47f9bb 100644 --- a/mirai-deps-test/test/AbstractTest.kt +++ b/mirai-deps-test/test/AbstractTest.kt @@ -90,7 +90,6 @@ abstract class AbstractTest { lateinit var mainSrcDir: File lateinit var commonMainSrcDir: File - lateinit var nativeMainSrcDir: File lateinit var testDir: File lateinit var buildFile: File lateinit var settingsFile: File @@ -154,7 +153,6 @@ abstract class AbstractTest { } mainSrcDir = tempDir.resolve("src/main/kotlin").apply { mkdirs() } commonMainSrcDir = tempDir.resolve("src/commonMain/kotlin").apply { mkdirs() } - nativeMainSrcDir = tempDir.resolve("src/nativeMain/kotlin").apply { mkdirs() } testDir = tempDir.resolve("src/test/kotlin").apply { mkdirs() } buildFile = tempDir.resolve("build.gradle.kts") diff --git a/mirai-deps-test/test/CoreDependencyResolutionTest.kt b/mirai-deps-test/test/CoreDependencyResolutionTest.kt index 6fdddf886..244a406da 100644 --- a/mirai-deps-test/test/CoreDependencyResolutionTest.kt +++ b/mirai-deps-test/test/CoreDependencyResolutionTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -90,13 +90,6 @@ class CoreDependencyResolutionTest : AbstractTest() { |kotlin { | targets { | jvm() - | val nativeMainSets = mutableListOf() - | val nativeTestSets = mutableListOf() - | when { - | Os.isFamily(Os.FAMILY_MAC) -> if (Os.isArch("aarch64")) macosArm64("native") else macosX64("native") - | Os.isFamily(Os.FAMILY_WINDOWS) -> mingwX64("native") - | else -> linuxX64("native") - | } | } | sourceSets { | val commonMain by getting { @@ -114,48 +107,4 @@ class CoreDependencyResolutionTest : AbstractTest() { runGradle("build") } - - @Test - @EnabledIf("isMiraiLocalAvailable", disabledReason = REASON_LOCAL_ARTIFACT_NOT_AVAILABLE) - fun `test resolve Native from common`() { - nativeMainSrcDir.resolve("main.kt").writeText(testCode) - buildFile.writeText( - """ - |import org.apache.tools.ant.taskdefs.condition.Os - |import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet - | - |plugins { - | id("org.jetbrains.kotlin.multiplatform") version "$kotlinVersion" - |} - |repositories { - | mavenCentral() - | mavenLocal() - |} - |kotlin { - | targets { - | jvm() - | val nativeMainSets = mutableListOf() - | val nativeTestSets = mutableListOf() - | when { - | Os.isFamily(Os.FAMILY_MAC) -> if (Os.isArch("aarch64")) macosArm64("native") else macosX64("native") - | Os.isFamily(Os.FAMILY_WINDOWS) -> mingwX64("native") - | else -> linuxX64("native") - | } - | } - | sourceSets { - | val nativeMain by getting { - | dependencies { - | api("net.mamoe:mirai-core:$miraiLocalVersion") - | } - | } - | } - |} - |kotlin.sourceSets.all { - | languageSettings.optIn("net.mamoe.mirai.utils.TestOnly") - |} - """.trimMargin() - ) - - runGradle("build") - } } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index f14dc74a5..4428b9b90 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -29,6 +29,10 @@ pluginManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0" +} + rootProject.name = "mirai" runCatching { rootProject.projectDir.resolve("local.properties").let { if (!it.exists()) it.createNewFile() } }