Skip to content

Commit 1ba898c

Browse files
committed
feat(common-streamable): 增加模块与新的公共类型 Streamable, 用来简化部分针对 Sequence 类型的转化操作,例如在JVM中转为 Stream 和在 JS 中转为数组。
1 parent a04aa48 commit 1ba898c

File tree

16 files changed

+512
-4
lines changed

16 files changed

+512
-4
lines changed

buildSrc/src/main/kotlin/P.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ sealed class P(override val group: String) : ProjectDetail() {
5252
5353
*/
5454
companion object {
55-
const val VERSION = "4.3.1"
56-
const val NEXT_VERSION = "4.3.2"
55+
const val VERSION = "4.4.0"
56+
const val NEXT_VERSION = "4.4.0"
5757
const val SNAPSHOT_VERSION = "$VERSION-SNAPSHOT"
5858
const val NEXT_SNAPSHOT_VERSION = "$NEXT_VERSION-SNAPSHOT"
5959

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ include(":simbot-gradles:simbot-gradle-suspendtransforms")
4444

4545
include(":simbot-commons:simbot-common-annotations")
4646
include(":simbot-commons:simbot-common-collection")
47+
include(":simbot-commons:simbot-common-streamable")
4748
include(":simbot-commons:simbot-common-atomic")
4849
include(":simbot-commons:simbot-common-apidefinition")
4950
include(":simbot-commons:simbot-common-core")

simbot-api/api/simbot-api.api

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ public abstract interface class love/forte/simbot/bot/BotManager : love/forte/si
371371
public fun all (Llove/forte/simbot/common/id/ID;)Lkotlin/sequences/Sequence;
372372
public fun allToList ()Ljava/util/List;
373373
public fun allToList (Llove/forte/simbot/common/id/ID;)Ljava/util/List;
374+
public fun allToStreamable ()Llove/forte/simbot/common/streamable/Streamable;
375+
public fun allToStreamable (Llove/forte/simbot/common/id/ID;)Llove/forte/simbot/common/streamable/Streamable;
374376
public fun asFuture ()Ljava/util/concurrent/CompletableFuture;
375377
public abstract fun cancel (Ljava/lang/Throwable;)V
376378
public static synthetic fun cancel$default (Llove/forte/simbot/bot/BotManager;Ljava/lang/Throwable;ILjava/lang/Object;)V
@@ -393,6 +395,7 @@ public final class love/forte/simbot/bot/BotManagerUtil {
393395

394396
public abstract interface class love/forte/simbot/bot/BotManagers : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker {
395397
public fun allBots ()Lkotlin/sequences/Sequence;
398+
public fun allBotsToStreamable ()Llove/forte/simbot/common/streamable/Streamable;
396399
public fun firstBot ()Llove/forte/simbot/bot/Bot;
397400
public fun firstBot (Llove/forte/simbot/common/id/ID;)Llove/forte/simbot/bot/Bot;
398401
}
@@ -1206,6 +1209,7 @@ public abstract interface class love/forte/simbot/event/EventListener {
12061209

12071210
public abstract interface class love/forte/simbot/event/EventListenerContainer {
12081211
public abstract fun getListeners ()Lkotlin/sequences/Sequence;
1212+
public fun listenersToStreamable ()Llove/forte/simbot/common/streamable/Streamable;
12091213
}
12101214

12111215
public abstract interface class love/forte/simbot/event/EventListenerContext {

simbot-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ kotlin {
7575
implementation(project(":simbot-commons:simbot-common-annotations"))
7676
implementation(project(":simbot-logger"))
7777

78+
api(project(":simbot-commons:simbot-common-streamable"))
7879
api(project(":simbot-commons:simbot-common-suspend-runner"))
7980
api(project(":simbot-commons:simbot-common-core"))
8081
api(project(":simbot-commons:simbot-common-collection"))

simbot-api/src/commonMain/kotlin/love/forte/simbot/bot/BotManager.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import love.forte.simbot.ability.CompletionAware
2727
import love.forte.simbot.ability.LifecycleAware
2828
import love.forte.simbot.common.function.MergeableFactory
2929
import love.forte.simbot.common.id.ID
30+
import love.forte.simbot.common.streamable.Streamable
31+
import love.forte.simbot.common.streamable.Streamable.Companion.asStreamable
3032
import love.forte.simbot.plugin.PluginFactory
3133
import love.forte.simbot.suspendrunner.ST
3234

@@ -57,6 +59,24 @@ public interface BotManager : AutoConfigurableBotPlugin, LifecycleAware, Complet
5759
*/
5860
public fun all(id: ID): Sequence<Bot> = all().filter { bot -> bot.id == id }
5961

62+
/**
63+
* 得到所有的 [Bot] 并转化为 [Streamable]。
64+
*
65+
* @since 4.4.0
66+
* @see all
67+
*/
68+
public fun allToStreamable(): Streamable<Bot> =
69+
all().asStreamable()
70+
71+
/**
72+
* 得到所有 `id` 符合条件的 [Bot] 并转化为 [Streamable]。
73+
*
74+
* @since 4.4.0
75+
* @see all
76+
*/
77+
public fun allToStreamable(id: ID): Streamable<Bot> =
78+
all(id).asStreamable()
79+
6080
/**
6181
* 将 [all] 收集为 [List] 并返回。
6282
*

simbot-api/src/commonMain/kotlin/love/forte/simbot/bot/BotManagers.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ package love.forte.simbot.bot
2828

2929
import love.forte.simbot.common.collection.toImmutable
3030
import love.forte.simbot.common.id.ID
31+
import love.forte.simbot.common.streamable.Streamable
32+
import love.forte.simbot.common.streamable.Streamable.Companion.asStreamable
3133
import kotlin.jvm.JvmMultifileClass
3234
import kotlin.jvm.JvmName
3335

@@ -41,6 +43,13 @@ public interface BotManagers : Collection<BotManager> {
4143
*/
4244
public fun allBots(): Sequence<Bot> = asSequence().flatMap { it.all() }
4345

46+
/**
47+
* 获取 [allBots] 的流转化器。
48+
*
49+
* @since 4.4.0
50+
*/
51+
public fun allBotsToStreamable(): Streamable<Bot> = allBots().asStreamable()
52+
4453
/**
4554
* 尝试获取第一个 [BotManager] 中的第一个 [Bot]。
4655
*

simbot-api/src/commonMain/kotlin/love/forte/simbot/event/EventListenerContainer.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Project https://github.com/simple-robot/simpler-robot
55
66
*
7-
* This file is part of the Simple Robot Library.
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
88
*
99
* This program is free software: you can redistribute it and/or modify
1010
* it under the terms of the GNU Lesser General Public License as published by
@@ -23,6 +23,9 @@
2323

2424
package love.forte.simbot.event
2525

26+
import love.forte.simbot.common.streamable.Streamable
27+
import love.forte.simbot.common.streamable.Streamable.Companion.asStreamable
28+
2629

2730
/**
2831
* 事件监听器的“容器”接口,提供用于获取其中的所有 [EventListener] 的API。
@@ -37,5 +40,11 @@ public interface EventListenerContainer {
3740
*/
3841
public val listeners: Sequence<EventListener>
3942

40-
43+
/**
44+
* 获取到 [listeners] 并转化为 [Streamable]
45+
*
46+
* @see listeners
47+
*/
48+
public fun listenersToStreamable(): Streamable<EventListener> =
49+
listeners.asStreamable()
4150
}

simbot-api/src/jvmMain/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
requires simbot.logger;
3232
requires static org.jetbrains.annotations;
3333
requires static simbot.common.annotations;
34+
requires simbot.common.streamable;
3435
requires simbot.common.suspendrunner;
3536
requires simbot.common.core;
3637
requires simbot.common.collection;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
public final class love/forte/simbot/common/streamable/Streamable : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
2+
public static final field Companion Llove/forte/simbot/common/streamable/Streamable$Companion;
3+
public synthetic fun <init> (Lkotlin/sequences/Sequence;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
4+
public final fun asSequence ()Lkotlin/sequences/Sequence;
5+
public final fun asStream ()Ljava/util/stream/Stream;
6+
public final fun collectTo (Ljava/util/Collection;)Ljava/util/Collection;
7+
public final fun collectToList ()Ljava/util/List;
8+
public fun iterator ()Ljava/util/Iterator;
9+
public static final fun of (Lkotlin/sequences/Sequence;)Llove/forte/simbot/common/streamable/Streamable;
10+
}
11+
12+
public final class love/forte/simbot/common/streamable/Streamable$Companion {
13+
public final fun of (Lkotlin/sequences/Sequence;)Llove/forte/simbot/common/streamable/Streamable;
14+
}
15+
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
import love.forte.gradle.common.kotlin.multiplatform.applyTier1
25+
import love.forte.gradle.common.kotlin.multiplatform.applyTier2
26+
import love.forte.gradle.common.kotlin.multiplatform.applyTier3
27+
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
28+
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
29+
30+
plugins {
31+
kotlin("multiplatform")
32+
kotlin("plugin.serialization")
33+
id("simbot.dokka-module-configuration")
34+
}
35+
36+
configJavaCompileWithModule("simbot.common.streamable")
37+
apply(plugin = "simbot-multiplatform-maven-publish")
38+
39+
kotlin {
40+
explicitApi()
41+
applyDefaultHierarchyTemplate()
42+
43+
configKotlinJvm(JVMConstants.KT_JVM_TARGET_VALUE)
44+
45+
js(IR) {
46+
configJs()
47+
}
48+
49+
applyTier1()
50+
applyTier2()
51+
applyTier3()
52+
53+
@OptIn(ExperimentalWasmDsl::class)
54+
wasmJs {
55+
configWasmJs()
56+
}
57+
58+
@OptIn(ExperimentalKotlinGradlePluginApi::class)
59+
compilerOptions {
60+
freeCompilerArgs.addAll(
61+
"-Xexpect-actual-classes"
62+
)
63+
}
64+
65+
sourceSets {
66+
commonTest {
67+
dependencies {
68+
implementation(kotlin("test"))
69+
}
70+
}
71+
72+
jvmTest {
73+
dependencies {
74+
implementation(kotlin("test-junit5"))
75+
}
76+
}
77+
}
78+
}
79+
80+
configWasmJsTest()
81+
82+
// https://book.kotlincn.net/text/testing-strategies.html
83+
tasks.withType<Test> {
84+
jvmArgs(
85+
"--add-opens",
86+
"java.base/jdk.internal.misc=ALL-UNNAMED",
87+
"--add-exports",
88+
"java.base/jdk.internal.util=ALL-UNNAMED",
89+
"--add-exports",
90+
"java.base/sun.security.action=ALL-UNNAMED"
91+
)
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
package love.forte.simbot.common.streamable
25+
26+
27+
/**
28+
*
29+
* 一个可流化的包装器类型。
30+
* 用于提供更便捷地对 [Sequence] 进行转化的API。
31+
*
32+
* [Streamable] 是一种用于便捷操作的**转化器**,
33+
* 而不是直接对流进行操作的类型。
34+
* 它的作用是减小不同平台间对 [Sequence] 的部分操作差异。
35+
*
36+
* [Streamable] 会有部分平台专供的API,例如在 JVM 中可转化为 `Stream`。
37+
*
38+
* @since 4.4.0
39+
*
40+
* @author ForteScarlet
41+
*/
42+
public expect class Streamable<out T> private constructor(seq: Sequence<T>) : Iterable<T> {
43+
/**
44+
* 转化为 [Sequence].
45+
*/
46+
public fun asSequence(): Sequence<T>
47+
48+
override fun iterator(): Iterator<T>
49+
50+
/**
51+
* 将结果转化为 [List]
52+
*/
53+
public fun collectToList(): List<T>
54+
55+
/**
56+
* 将内部的序列结果收集到 [C] 中。
57+
*/
58+
public fun <C : MutableCollection<in T>> collectTo(collection: C): C
59+
60+
public companion object {
61+
/**
62+
* 将 [Sequence] 转化为 [Streamable]
63+
*/
64+
public fun <T> Sequence<T>.asStreamable(): Streamable<T>
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
package love.forte.simbot.common.streamable
25+
26+
/**
27+
*
28+
* 一个可流化的包装器类型。
29+
* 用于提供更便捷地对 [Sequence] 进行转化的API。
30+
*
31+
* [Streamable] 是一种用于便捷操作的**转化器**,
32+
* 而不是直接对流进行操作的类型。
33+
* 它的作用是尽可能减小不同平台间对 [Sequence] 的操作差异。
34+
*
35+
* [Streamable] 会有部分平台专供的API,例如在 JVM 中可转化为 `Stream`。
36+
*
37+
* @since 4.4.0
38+
*
39+
* @author ForteScarlet
40+
*/
41+
public actual class Streamable<out T> private actual constructor(
42+
private val seq: Sequence<T>
43+
) : Iterable<T> {
44+
public actual fun asSequence(): Sequence<T> = seq
45+
actual override fun iterator(): Iterator<T> = seq.iterator()
46+
47+
/**
48+
* 将结果转化为 [List]
49+
*/
50+
public actual fun collectToList(): List<T> = seq.toList()
51+
52+
/**
53+
* 将内部的序列结果收集到 [C] 中。
54+
*/
55+
public actual fun <C : MutableCollection<in T>> collectTo(collection: C): C =
56+
seq.toCollection(collection)
57+
58+
/**
59+
* 收集元素为数组。
60+
*/
61+
public fun collectToArray(): Array<out T> =
62+
seq.toList().toTypedArray()
63+
64+
public actual companion object {
65+
/**
66+
* 将 [Sequence] 转化为 [Streamable]
67+
*/
68+
public actual fun <T> Sequence<T>.asStreamable(): Streamable<T> =
69+
Streamable(this)
70+
}
71+
}

0 commit comments

Comments
 (0)