diff --git a/buildSrc/src/main/kotlin/P.kt b/buildSrc/src/main/kotlin/P.kt index 191debc30..4901fa548 100644 --- a/buildSrc/src/main/kotlin/P.kt +++ b/buildSrc/src/main/kotlin/P.kt @@ -47,8 +47,8 @@ fun isSnapshot(): Boolean = _isSnapshot @Suppress("MemberVisibilityCanBePrivate") sealed class P(override val group: String) : ProjectDetail() { companion object { - const val VERSION = "4.6.1" - const val NEXT_VERSION = "4.7.0" + const val VERSION = "4.7.0-beta1" + const val NEXT_VERSION = "4.7.0-beta2" const val SNAPSHOT_VERSION = "$VERSION-SNAPSHOT" const val NEXT_SNAPSHOT_VERSION = "$NEXT_VERSION-SNAPSHOT" diff --git a/gradle.properties b/gradle.properties index 6a98d39ae..ea4ad86c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -41,6 +41,8 @@ org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=1G -Dfile.encoding=UTF-8 #org.gradle.workers.max=8 org.gradle.parallel=true org.gradle.caching=true +#org.gradle.configuration-cache=true +#org.gradle.configuration-cache.problems=warn # https://kotlinlang.org/docs/gradle-compilation-and-caches.html#the-new-kotlin-compiler diff --git a/simbot-api/build.gradle.kts b/simbot-api/build.gradle.kts index 31e84c59e..d97a7bce9 100644 --- a/simbot-api/build.gradle.kts +++ b/simbot-api/build.gradle.kts @@ -83,7 +83,7 @@ kotlin { api(project(":simbot-commons:simbot-common-collection")) api(libs.kotlinx.coroutines.core) api(libs.kotlinx.serialization.core) - api(libs.kotlinx.io.core) + implementation(libs.kotlinx.io.core) implementation(libs.kotlinx.serialization.json) // suspend reversal annotations diff --git a/simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/IOResources.kt b/simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/IOResources.kt index 385b2a19f..db51f6fce 100644 --- a/simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/IOResources.kt +++ b/simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/IOResources.kt @@ -25,10 +25,12 @@ package love.forte.simbot.resource -import kotlinx.io.* -import kotlinx.io.files.FileNotFoundException +import kotlinx.io.RawSource +import kotlinx.io.Source +import kotlinx.io.buffered import kotlinx.io.files.Path import kotlinx.io.files.SystemFileSystem +import kotlinx.io.readByteArray import kotlin.annotation.AnnotationTarget.* import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -61,9 +63,6 @@ public annotation class ExperimentalIOResourceAPI /** * 根据完整的文件路径 [filePath] 得到一个基于对应文件的 [Resource]。 * - * 文件会在通过 [Resource.data] 读取数据时才会校验存在性。届时如果文件不存在, - * 则会得到 [IllegalStateException] 异常。 - * * 如果不确定文件系统使用的路径分隔符,或可能在多个使用不同路径分隔符的系统上使用, * 则考虑使用 [fileResource(base, ...parts)][fileResource]。 * @@ -71,10 +70,14 @@ public annotation class ExperimentalIOResourceAPI * 其中, _路径分隔符_ 在不同的文件系统中可能是不同的,例如在 Unit 中的 `/` * 和在 Windows 的 `\`。 * + * @throws kotlinx.io.files.FileNotFoundException see [kotlinx.io.files.FileSystem.source]. + * @throws kotlinx.io.IOException see [kotlinx.io.files.FileSystem.source]. + * * @since 4.7.0 */ @JvmName("valueOfPath") @ExperimentalIOResourceAPI +@Throws(Exception::class) public fun fileResource(filePath: String): Resource { val path = Path(filePath) return FilePathResource(path) @@ -83,6 +86,10 @@ public fun fileResource(filePath: String): Resource { /** * 根据文件路径片段集得到一个基于对应文件的 [Resource]。 * + * 文件会先在初始化时构造 [RawSource], 而后在读取 [Resource.data] + * 时使用 [Source]. 因此对文件存在性的校验和错误报告可能不会立即报告, + * 而是被推迟到真正读取数据时。 + * * 文件会在通过 [Resource.data] 读取数据时才会校验存在性。届时如果文件不存在, * 则会得到 [IllegalStateException] 异常。 * 此异常的 [IllegalStateException.cause] 可能是: @@ -90,47 +97,58 @@ public fun fileResource(filePath: String): Resource { * - [kotlinx.io.IOException] * 如果是这两个类型,则成因参考 [kotlinx.io.files.FileSystem.source]。 * + * @throws kotlinx.io.files.FileNotFoundException see [kotlinx.io.files.FileSystem.source]. + * @throws kotlinx.io.IOException see [kotlinx.io.files.FileSystem.source]. + * * @since 4.7.0 */ @JvmName("valueOfPath") @ExperimentalIOResourceAPI +@Throws(Exception::class) public fun fileResource(base: String, vararg parts: String): Resource { val path = Path(base, *parts) return FilePathResource(path) } /** - * 一个可以得到 [kotlinx.io.RawSource] 的 [Resource]。 + * 一个可以得到 [kotlinx.io.Source] 的 [Resource]。 * * @since 4.7.0 */ @ExperimentalIOResourceAPI -public interface RawSourceResource : Resource { - public fun source(): RawSource +public interface SourceResource : Resource { + /** + * 得到一个用于本次数据读取的 [Source]. + * @throws kotlinx.io.files.FileNotFoundException + * see [kotlinx.io.files.FileSystem.source], [RawSource.buffered] + * @throws kotlinx.io.IOException + * see [kotlinx.io.files.FileSystem.source], [RawSource.buffered] + * + * @see kotlinx.io.files.FileSystem.source + * @see RawSource.buffered + */ + @Throws(Exception::class) + public fun source(): Source - override fun data(): ByteArray { - return source().buffered().use { it.readByteArray() } - } + /** + * 使用 [source] 并读取其中全部的字节数据。 + * + * @throws IllegalStateException + * see [Source.readByteArray] + * @throws kotlinx.io.IOException + * see [Source.readByteArray] + * + * @see source + */ + @Throws(Exception::class) + override fun data(): ByteArray = source().use { it.readByteArray() } } -/** - * 一个可以得到 [kotlinx.io.Source] 的 [Resource]。 - * - * @since 4.7.0 - */ @ExperimentalIOResourceAPI -public interface SourceResource : RawSourceResource { - override fun source(): Source -} +private data class FilePathResource(val path: Path) : SourceResource { + private val source = SystemFileSystem.source(path) -@ExperimentalIOResourceAPI -private data class FilePathResource(val path: Path) : RawSourceResource { - override fun source(): RawSource = try { - SystemFileSystem.source(path) - } catch (fnf: FileNotFoundException) { - throw IllegalStateException(fnf.message, fnf) - } catch (io: IOException) { - throw IllegalStateException(io.message, io) - } + @Throws(Exception::class) + override fun source(): Source = source.buffered() } diff --git a/simbot-commons/simbot-common-annotations/src/commonMain/kotlin/love/forte/simbot/annotations/annotations.kt b/simbot-commons/simbot-common-annotations/src/commonMain/kotlin/love/forte/simbot/annotations/annotations.kt index 92200e6dd..076fabf33 100644 --- a/simbot-commons/simbot-common-annotations/src/commonMain/kotlin/love/forte/simbot/annotations/annotations.kt +++ b/simbot-commons/simbot-common-annotations/src/commonMain/kotlin/love/forte/simbot/annotations/annotations.kt @@ -47,6 +47,18 @@ public annotation class ExperimentalSimbotAPI @MustBeDocumented public annotation class InternalSimbotAPI +/** + * 实现了一个应当仅供内部实现的API。虽然超类对外可能稳定,但是不保证第三方实现稳定。 + * 通常被使用在 [SubclassOptInRequired] 中。 + * @since 4.7.0 + */ +@Retention(AnnotationRetention.BINARY) +@RequiresOptIn( + message = "实现了一个应当仅供内部实现的API。虽然超类对外可能稳定,但是不保证第三方实现稳定" +) +@MustBeDocumented +public annotation class InternalInheritanceAPI + /** * 一个脆弱的、或者具有复杂的须知、备注、条件的API。 * 这类API通常有很多前提条件以及注意事项,需要谨慎使用。 diff --git a/website b/website index 1fa1fe2a8..0629bb8cc 160000 --- a/website +++ b/website @@ -1 +1 @@ -Subproject commit 1fa1fe2a8fa022431a6f230fa4affeb0fc6151ed +Subproject commit 0629bb8cc694f0a96696bba4712146ffb34b16c3