From 525830739cb8e6d3ce83a99a7c2dd7e25d902893 Mon Sep 17 00:00:00 2001
From: Karlatemp <karlatemp@vip.qq.com>
Date: Sat, 14 Nov 2020 12:06:47 +0800
Subject: [PATCH] Fix ReusableInput resources releasing

fix #675
---
 .../internal/DeferredReusableInput.common.kt      |  1 +
 .../kotlin/utils/internal/ReusableInput.kt        |  2 ++
 .../utils/internal/DeferredReusableInput.jvm.kt   |  4 ++++
 .../kotlin/utils/internal/asReusableInput.jvm.kt  | 15 +++++++++++++--
 .../src/commonMain/kotlin/contact/FriendImpl.kt   |  6 ++----
 .../src/commonMain/kotlin/contact/GroupImpl.kt    |  6 ++----
 6 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/mirai-core-api/src/commonMain/kotlin/utils/internal/DeferredReusableInput.common.kt b/mirai-core-api/src/commonMain/kotlin/utils/internal/DeferredReusableInput.common.kt
index a370f5df4..044811c41 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/internal/DeferredReusableInput.common.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/internal/DeferredReusableInput.common.kt
@@ -16,4 +16,5 @@ internal expect class DeferredReusableInput(input: Any, extraArg: Any?) : Reusab
 
 
     suspend fun init(strategy: FileCacheStrategy)
+
 }
\ No newline at end of file
diff --git a/mirai-core-api/src/commonMain/kotlin/utils/internal/ReusableInput.kt b/mirai-core-api/src/commonMain/kotlin/utils/internal/ReusableInput.kt
index 145700e05..b772de789 100644
--- a/mirai-core-api/src/commonMain/kotlin/utils/internal/ReusableInput.kt
+++ b/mirai-core-api/src/commonMain/kotlin/utils/internal/ReusableInput.kt
@@ -23,4 +23,6 @@ internal interface ReusableInput {
      * Remember to close.
      */
     fun asInput(): Input
+
+    fun release()
 }
\ No newline at end of file
diff --git a/mirai-core-api/src/jvmMain/kotlin/utils/internal/DeferredReusableInput.jvm.kt b/mirai-core-api/src/jvmMain/kotlin/utils/internal/DeferredReusableInput.jvm.kt
index b2f401d01..17079eda8 100644
--- a/mirai-core-api/src/jvmMain/kotlin/utils/internal/DeferredReusableInput.jvm.kt
+++ b/mirai-core-api/src/jvmMain/kotlin/utils/internal/DeferredReusableInput.jvm.kt
@@ -57,5 +57,9 @@ internal actual class DeferredReusableInput actual constructor(
         return delegate?.asInput() ?: error("DeferredReusableInput not yet initialized")
     }
 
+    override fun release() {
+        return delegate?.release() ?: error("DeferredReusableInput not yet initialized")
+    }
+
     actual val initialized: Boolean get() = delegate != null
 }
\ No newline at end of file
diff --git a/mirai-core-api/src/jvmMain/kotlin/utils/internal/asReusableInput.jvm.kt b/mirai-core-api/src/jvmMain/kotlin/utils/internal/asReusableInput.jvm.kt
index 6daac0cd7..8c064468a 100644
--- a/mirai-core-api/src/jvmMain/kotlin/utils/internal/asReusableInput.jvm.kt
+++ b/mirai-core-api/src/jvmMain/kotlin/utils/internal/asReusableInput.jvm.kt
@@ -51,6 +51,10 @@ internal actual fun ByteArray.asReusableInput(): ReusableInput {
         override fun asInput(): Input {
             return ByteArrayInputStream(this@asReusableInput).asInput()
         }
+
+        override fun release() {
+            // nothing to do
+        }
     }
 }
 
@@ -69,7 +73,6 @@ internal fun File.asReusableInput(deleteOnClose: Boolean): ReusableInput {
 
                 override fun close() {
                     stream.close()
-                    if (deleteOnClose) this@asReusableInput.delete()
                 }
             }
         }
@@ -81,6 +84,11 @@ internal fun File.asReusableInput(deleteOnClose: Boolean): ReusableInput {
         override fun asInput(): Input {
             return inputStream().asInput()
         }
+
+        override fun release() {
+            if (deleteOnClose) this@asReusableInput.delete()
+        }
+
     }
 }
 
@@ -99,7 +107,6 @@ internal fun File.asReusableInput(deleteOnClose: Boolean, md5: ByteArray): Reusa
 
                 override fun close() {
                     stream.close()
-                    if (deleteOnClose) this@asReusableInput.delete()
                 }
             }
         }
@@ -111,6 +118,10 @@ internal fun File.asReusableInput(deleteOnClose: Boolean, md5: ByteArray): Reusa
         override fun asInput(): Input {
             return inputStream().asInput()
         }
+
+        override fun release() {
+            if (deleteOnClose) this@asReusableInput.delete()
+        }
     }
 }
 
diff --git a/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt b/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt
index 55dd84a8d..44a7de2b7 100644
--- a/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt
+++ b/mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt
@@ -22,7 +22,6 @@ import kotlinx.atomicfu.AtomicInt
 import kotlinx.atomicfu.atomic
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
-import kotlinx.io.core.Closeable
 import net.mamoe.mirai.LowLevelApi
 import net.mamoe.mirai.contact.Friend
 import net.mamoe.mirai.data.FriendInfo
@@ -110,8 +109,8 @@ internal class FriendImpl(
     }
 
     @JvmSynthetic
+    @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
     override suspend fun uploadImage(image: ExternalImage): Image = try {
-        @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
         if (image.input is net.mamoe.mirai.utils.internal.DeferredReusableInput) {
             image.input.init(bot.configuration.fileCacheStrategy)
         }
@@ -178,7 +177,6 @@ internal class FriendImpl(
             }
         }
     } finally {
-        @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
-        (image.input as? Closeable)?.close()
+        image.input.release()
     }
 }
\ No newline at end of file
diff --git a/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt b/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt
index 07ec202ae..4bc5797d0 100644
--- a/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt
+++ b/mirai-core/src/commonMain/kotlin/contact/GroupImpl.kt
@@ -15,7 +15,6 @@ package net.mamoe.mirai.internal.contact
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.launch
-import kotlinx.io.core.Closeable
 import net.mamoe.mirai.LowLevelApi
 import net.mamoe.mirai.Mirai
 import net.mamoe.mirai.contact.*
@@ -403,11 +402,10 @@ internal class GroupImpl(
         return result.getOrThrow()
     }
 
-    @Suppress("DEPRECATION")
+    @Suppress("DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
     @OptIn(ExperimentalTime::class)
     @JvmSynthetic
     override suspend fun uploadImage(image: ExternalImage): Image = try {
-        @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
         if (image.input is net.mamoe.mirai.utils.internal.DeferredReusableInput) {
             image.input.init(bot.configuration.fileCacheStrategy)
         }
@@ -451,7 +449,7 @@ internal class GroupImpl(
             }
         }
     } finally {
-        (image.input as? Closeable)?.close()
+        image.input.release()
     }
 
     /**