Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Zstd compression and improve compression configuration #991

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -2184,6 +2184,7 @@ public abstract class dev/kord/core/builder/kord/BaseKordBuilder {
public final fun cache (Lkotlin/jvm/functions/Function2;)V
public final fun gateways (Lkotlin/jvm/functions/Function2;)V
public final fun getApplicationId ()Ldev/kord/common/entity/Snowflake;
public final fun getCompression ()Ldev/kord/gateway/Compression;
public final fun getDefaultDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher;
public final fun getDefaultStrategy ()Ldev/kord/core/supplier/EntitySupplyStrategy;
public final fun getEventFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
Expand All @@ -2193,6 +2194,7 @@ public abstract class dev/kord/core/builder/kord/BaseKordBuilder {
public final fun getToken ()Ljava/lang/String;
public final fun requestHandler (Lkotlin/jvm/functions/Function1;)V
public final fun setApplicationId (Ldev/kord/common/entity/Snowflake;)V
public final fun setCompression (Ldev/kord/gateway/Compression;)V
public final fun setDefaultDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V
public final fun setDefaultStrategy (Ldev/kord/core/supplier/EntitySupplyStrategy;)V
public final fun setEventFlow (Lkotlinx/coroutines/flow/MutableSharedFlow;)V
Expand Down
3 changes: 3 additions & 0 deletions core/api/core.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,9 @@ abstract class dev.kord.core.builder.kord/BaseKordBuilder { // dev.kord.core.bui
final var applicationId // dev.kord.core.builder.kord/BaseKordBuilder.applicationId|{}applicationId[0]
final fun <get-applicationId>(): dev.kord.common.entity/Snowflake? // dev.kord.core.builder.kord/BaseKordBuilder.applicationId.<get-applicationId>|<get-applicationId>(){}[0]
final fun <set-applicationId>(dev.kord.common.entity/Snowflake?) // dev.kord.core.builder.kord/BaseKordBuilder.applicationId.<set-applicationId>|<set-applicationId>(dev.kord.common.entity.Snowflake?){}[0]
final var compression // dev.kord.core.builder.kord/BaseKordBuilder.compression|{}compression[0]
final fun <get-compression>(): dev.kord.gateway/Compression // dev.kord.core.builder.kord/BaseKordBuilder.compression.<get-compression>|<get-compression>(){}[0]
final fun <set-compression>(dev.kord.gateway/Compression) // dev.kord.core.builder.kord/BaseKordBuilder.compression.<set-compression>|<set-compression>(dev.kord.gateway.Compression){}[0]
final var defaultDispatcher // dev.kord.core.builder.kord/BaseKordBuilder.defaultDispatcher|{}defaultDispatcher[0]
final fun <get-defaultDispatcher>(): kotlinx.coroutines/CoroutineDispatcher // dev.kord.core.builder.kord/BaseKordBuilder.defaultDispatcher.<get-defaultDispatcher>|<get-defaultDispatcher>(){}[0]
final fun <set-defaultDispatcher>(kotlinx.coroutines/CoroutineDispatcher) // dev.kord.core.builder.kord/BaseKordBuilder.defaultDispatcher.<set-defaultDispatcher>|<set-defaultDispatcher>(kotlinx.coroutines.CoroutineDispatcher){}[0]
Expand Down
7 changes: 7 additions & 0 deletions core/src/commonMain/kotlin/builder/kord/KordBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import dev.kord.core.gateway.DefaultMasterGateway
import dev.kord.core.gateway.handler.DefaultGatewayEventInterceptor
import dev.kord.core.gateway.handler.GatewayEventInterceptor
import dev.kord.core.supplier.EntitySupplyStrategy
import dev.kord.gateway.Compression
import dev.kord.gateway.DefaultGateway
import dev.kord.gateway.Gateway
import dev.kord.gateway.builder.Shards
Expand Down Expand Up @@ -49,6 +50,7 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str
DefaultGateway {
client = resources.httpClient
identifyRateLimiter = rateLimiter
compression = [email protected]
}
}
}
Expand All @@ -57,6 +59,11 @@ public abstract class BaseKordBuilder internal constructor(public val token: Str
{ KtorRequestHandler(it.httpClient, ExclusionRequestRateLimiter(), token = token) }
private var cacheBuilder: KordCacheBuilder.(resources: ClientResources) -> Unit = {}

/**
* The [compression mode][Compression] used.
*/
public var compression: Compression = Compression.ZLib

/**
* Enables stack trace recovery on the currently defined [RequestHandler].
*
Expand Down
47 changes: 44 additions & 3 deletions gateway/api/gateway.api
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,43 @@ public final class dev/kord/gateway/Command$SerializationStrategy : kotlinx/seri
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}

public abstract interface class dev/kord/gateway/Compression {
public abstract fun getName ()Ljava/lang/String;
public abstract fun newDecompressor ()Ldev/kord/gateway/Decompressor;
}

public final class dev/kord/gateway/Compression$None : dev/kord/gateway/Compression {
public static final field INSTANCE Ldev/kord/gateway/Compression$None;
public fun equals (Ljava/lang/Object;)Z
public fun getName ()Ljava/lang/String;
public fun hashCode ()I
public fun newDecompressor ()Ldev/kord/gateway/Decompressor;
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/gateway/Compression$ZLib : dev/kord/gateway/Compression {
public static final field INSTANCE Ldev/kord/gateway/Compression$ZLib;
public fun equals (Ljava/lang/Object;)Z
public fun getName ()Ljava/lang/String;
public fun hashCode ()I
public fun newDecompressor ()Ldev/kord/gateway/Decompressor;
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/gateway/Compression$Zstd : dev/kord/gateway/Compression {
public static final field INSTANCE Ldev/kord/gateway/Compression$Zstd;
public fun equals (Ljava/lang/Object;)Z
public fun getName ()Ljava/lang/String;
public fun hashCode ()I
public fun newDecompressor ()Ldev/kord/gateway/Decompressor;
public fun toString ()Ljava/lang/String;
}

public final class dev/kord/gateway/Decompressor$Noop : dev/kord/gateway/Decompressor {
public fun close ()V
public fun decompress (Lio/ktor/websocket/Frame;)Ljava/lang/String;
}

public final class dev/kord/gateway/DefaultGateway : dev/kord/gateway/Gateway {
public static final field Companion Ldev/kord/gateway/DefaultGateway$Companion;
public fun <init> (Ldev/kord/gateway/DefaultGatewayData;)V
Expand All @@ -238,13 +275,15 @@ public final class dev/kord/gateway/DefaultGatewayBuilder {
public fun <init> ()V
public final fun build ()Ldev/kord/gateway/DefaultGateway;
public final fun getClient ()Lio/ktor/client/HttpClient;
public final fun getCompression ()Ldev/kord/gateway/Compression;
public final fun getDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher;
public final fun getEventFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
public final fun getIdentifyRateLimiter ()Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;
public final fun getReconnectRetry ()Ldev/kord/gateway/retry/Retry;
public final fun getSendRateLimiter ()Ldev/kord/common/ratelimit/RateLimiter;
public final fun getUrl ()Ljava/lang/String;
public final fun setClient (Lio/ktor/client/HttpClient;)V
public final fun setCompression (Ldev/kord/gateway/Compression;)V
public final fun setDispatcher (Lkotlinx/coroutines/CoroutineDispatcher;)V
public final fun setEventFlow (Lkotlinx/coroutines/flow/MutableSharedFlow;)V
public final fun setIdentifyRateLimiter (Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;)V
Expand All @@ -254,18 +293,20 @@ public final class dev/kord/gateway/DefaultGatewayBuilder {
}

public final class dev/kord/gateway/DefaultGatewayData {
public fun <init> (Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;)V
public fun <init> (Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;Ldev/kord/gateway/Compression;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Lio/ktor/client/HttpClient;
public final fun component3 ()Ldev/kord/gateway/retry/Retry;
public final fun component4 ()Ldev/kord/common/ratelimit/RateLimiter;
public final fun component5 ()Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;
public final fun component6 ()Lkotlinx/coroutines/CoroutineDispatcher;
public final fun component7 ()Lkotlinx/coroutines/flow/MutableSharedFlow;
public final fun copy (Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;)Ldev/kord/gateway/DefaultGatewayData;
public static synthetic fun copy$default (Ldev/kord/gateway/DefaultGatewayData;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;ILjava/lang/Object;)Ldev/kord/gateway/DefaultGatewayData;
public final fun component8 ()Ldev/kord/gateway/Compression;
public final fun copy (Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;Ldev/kord/gateway/Compression;)Ldev/kord/gateway/DefaultGatewayData;
public static synthetic fun copy$default (Ldev/kord/gateway/DefaultGatewayData;Ljava/lang/String;Lio/ktor/client/HttpClient;Ldev/kord/gateway/retry/Retry;Ldev/kord/common/ratelimit/RateLimiter;Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/flow/MutableSharedFlow;Ldev/kord/gateway/Compression;ILjava/lang/Object;)Ldev/kord/gateway/DefaultGatewayData;
public fun equals (Ljava/lang/Object;)Z
public final fun getClient ()Lio/ktor/client/HttpClient;
public final fun getCompression ()Ldev/kord/gateway/Compression;
public final fun getDispatcher ()Lkotlinx/coroutines/CoroutineDispatcher;
public final fun getEventFlow ()Lkotlinx/coroutines/flow/MutableSharedFlow;
public final fun getIdentifyRateLimiter ()Ldev/kord/gateway/ratelimit/IdentifyRateLimiter;
Expand Down
47 changes: 45 additions & 2 deletions gateway/api/gateway.klib.api
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,43 @@ abstract interface dev.kord.gateway/Gateway : kotlinx.coroutines/CoroutineScope
}
}

sealed interface dev.kord.gateway/Compression { // dev.kord.gateway/Compression|null[0]
abstract val name // dev.kord.gateway/Compression.name|{}name[0]
abstract fun <get-name>(): kotlin/String? // dev.kord.gateway/Compression.name.<get-name>|<get-name>(){}[0]

abstract fun newDecompressor(): dev.kord.gateway/Decompressor // dev.kord.gateway/Compression.newDecompressor|newDecompressor(){}[0]

final object None : dev.kord.gateway/Compression { // dev.kord.gateway/Compression.None|null[0]
final val name // dev.kord.gateway/Compression.None.name|{}name[0]
final fun <get-name>(): kotlin/String? // dev.kord.gateway/Compression.None.name.<get-name>|<get-name>(){}[0]

final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.gateway/Compression.None.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // dev.kord.gateway/Compression.None.hashCode|hashCode(){}[0]
final fun newDecompressor(): dev.kord.gateway/Decompressor // dev.kord.gateway/Compression.None.newDecompressor|newDecompressor(){}[0]
final fun toString(): kotlin/String // dev.kord.gateway/Compression.None.toString|toString(){}[0]
}

final object ZLib : dev.kord.gateway/Compression { // dev.kord.gateway/Compression.ZLib|null[0]
final val name // dev.kord.gateway/Compression.ZLib.name|{}name[0]
final fun <get-name>(): kotlin/String // dev.kord.gateway/Compression.ZLib.name.<get-name>|<get-name>(){}[0]

final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.gateway/Compression.ZLib.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // dev.kord.gateway/Compression.ZLib.hashCode|hashCode(){}[0]
final fun newDecompressor(): dev.kord.gateway/Decompressor // dev.kord.gateway/Compression.ZLib.newDecompressor|newDecompressor(){}[0]
final fun toString(): kotlin/String // dev.kord.gateway/Compression.ZLib.toString|toString(){}[0]
}

final object Zstd : dev.kord.gateway/Compression { // dev.kord.gateway/Compression.Zstd|null[0]
final val name // dev.kord.gateway/Compression.Zstd.name|{}name[0]
final fun <get-name>(): kotlin/String // dev.kord.gateway/Compression.Zstd.name.<get-name>|<get-name>(){}[0]

final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.gateway/Compression.Zstd.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // dev.kord.gateway/Compression.Zstd.hashCode|hashCode(){}[0]
final fun newDecompressor(): dev.kord.gateway/Decompressor // dev.kord.gateway/Compression.Zstd.newDecompressor|newDecompressor(){}[0]
final fun toString(): kotlin/String // dev.kord.gateway/Compression.Zstd.toString|toString(){}[0]
}
}

final class dev.kord.gateway.builder/LoginBuilder { // dev.kord.gateway.builder/LoginBuilder|null[0]
constructor <init>() // dev.kord.gateway.builder/LoginBuilder.<init>|<init>(){}[0]

Expand Down Expand Up @@ -405,6 +442,9 @@ final class dev.kord.gateway/DefaultGatewayBuilder { // dev.kord.gateway/Default
final var client // dev.kord.gateway/DefaultGatewayBuilder.client|{}client[0]
final fun <get-client>(): io.ktor.client/HttpClient? // dev.kord.gateway/DefaultGatewayBuilder.client.<get-client>|<get-client>(){}[0]
final fun <set-client>(io.ktor.client/HttpClient?) // dev.kord.gateway/DefaultGatewayBuilder.client.<set-client>|<set-client>(io.ktor.client.HttpClient?){}[0]
final var compression // dev.kord.gateway/DefaultGatewayBuilder.compression|{}compression[0]
final fun <get-compression>(): dev.kord.gateway/Compression // dev.kord.gateway/DefaultGatewayBuilder.compression.<get-compression>|<get-compression>(){}[0]
final fun <set-compression>(dev.kord.gateway/Compression) // dev.kord.gateway/DefaultGatewayBuilder.compression.<set-compression>|<set-compression>(dev.kord.gateway.Compression){}[0]
final var dispatcher // dev.kord.gateway/DefaultGatewayBuilder.dispatcher|{}dispatcher[0]
final fun <get-dispatcher>(): kotlinx.coroutines/CoroutineDispatcher // dev.kord.gateway/DefaultGatewayBuilder.dispatcher.<get-dispatcher>|<get-dispatcher>(){}[0]
final fun <set-dispatcher>(kotlinx.coroutines/CoroutineDispatcher) // dev.kord.gateway/DefaultGatewayBuilder.dispatcher.<set-dispatcher>|<set-dispatcher>(kotlinx.coroutines.CoroutineDispatcher){}[0]
Expand All @@ -428,10 +468,12 @@ final class dev.kord.gateway/DefaultGatewayBuilder { // dev.kord.gateway/Default
}

final class dev.kord.gateway/DefaultGatewayData { // dev.kord.gateway/DefaultGatewayData|null[0]
constructor <init>(kotlin/String, io.ktor.client/HttpClient, dev.kord.gateway.retry/Retry, dev.kord.common.ratelimit/RateLimiter, dev.kord.gateway.ratelimit/IdentifyRateLimiter, kotlinx.coroutines/CoroutineDispatcher, kotlinx.coroutines.flow/MutableSharedFlow<dev.kord.gateway/Event>) // dev.kord.gateway/DefaultGatewayData.<init>|<init>(kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;dev.kord.common.ratelimit.RateLimiter;dev.kord.gateway.ratelimit.IdentifyRateLimiter;kotlinx.coroutines.CoroutineDispatcher;kotlinx.coroutines.flow.MutableSharedFlow<dev.kord.gateway.Event>){}[0]
constructor <init>(kotlin/String, io.ktor.client/HttpClient, dev.kord.gateway.retry/Retry, dev.kord.common.ratelimit/RateLimiter, dev.kord.gateway.ratelimit/IdentifyRateLimiter, kotlinx.coroutines/CoroutineDispatcher, kotlinx.coroutines.flow/MutableSharedFlow<dev.kord.gateway/Event>, dev.kord.gateway/Compression) // dev.kord.gateway/DefaultGatewayData.<init>|<init>(kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;dev.kord.common.ratelimit.RateLimiter;dev.kord.gateway.ratelimit.IdentifyRateLimiter;kotlinx.coroutines.CoroutineDispatcher;kotlinx.coroutines.flow.MutableSharedFlow<dev.kord.gateway.Event>;dev.kord.gateway.Compression){}[0]

final val client // dev.kord.gateway/DefaultGatewayData.client|{}client[0]
final fun <get-client>(): io.ktor.client/HttpClient // dev.kord.gateway/DefaultGatewayData.client.<get-client>|<get-client>(){}[0]
final val compression // dev.kord.gateway/DefaultGatewayData.compression|{}compression[0]
final fun <get-compression>(): dev.kord.gateway/Compression // dev.kord.gateway/DefaultGatewayData.compression.<get-compression>|<get-compression>(){}[0]
final val dispatcher // dev.kord.gateway/DefaultGatewayData.dispatcher|{}dispatcher[0]
final fun <get-dispatcher>(): kotlinx.coroutines/CoroutineDispatcher // dev.kord.gateway/DefaultGatewayData.dispatcher.<get-dispatcher>|<get-dispatcher>(){}[0]
final val eventFlow // dev.kord.gateway/DefaultGatewayData.eventFlow|{}eventFlow[0]
Expand All @@ -452,7 +494,8 @@ final class dev.kord.gateway/DefaultGatewayData { // dev.kord.gateway/DefaultGat
final fun component5(): dev.kord.gateway.ratelimit/IdentifyRateLimiter // dev.kord.gateway/DefaultGatewayData.component5|component5(){}[0]
final fun component6(): kotlinx.coroutines/CoroutineDispatcher // dev.kord.gateway/DefaultGatewayData.component6|component6(){}[0]
final fun component7(): kotlinx.coroutines.flow/MutableSharedFlow<dev.kord.gateway/Event> // dev.kord.gateway/DefaultGatewayData.component7|component7(){}[0]
final fun copy(kotlin/String = ..., io.ktor.client/HttpClient = ..., dev.kord.gateway.retry/Retry = ..., dev.kord.common.ratelimit/RateLimiter = ..., dev.kord.gateway.ratelimit/IdentifyRateLimiter = ..., kotlinx.coroutines/CoroutineDispatcher = ..., kotlinx.coroutines.flow/MutableSharedFlow<dev.kord.gateway/Event> = ...): dev.kord.gateway/DefaultGatewayData // dev.kord.gateway/DefaultGatewayData.copy|copy(kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;dev.kord.common.ratelimit.RateLimiter;dev.kord.gateway.ratelimit.IdentifyRateLimiter;kotlinx.coroutines.CoroutineDispatcher;kotlinx.coroutines.flow.MutableSharedFlow<dev.kord.gateway.Event>){}[0]
final fun component8(): dev.kord.gateway/Compression // dev.kord.gateway/DefaultGatewayData.component8|component8(){}[0]
final fun copy(kotlin/String = ..., io.ktor.client/HttpClient = ..., dev.kord.gateway.retry/Retry = ..., dev.kord.common.ratelimit/RateLimiter = ..., dev.kord.gateway.ratelimit/IdentifyRateLimiter = ..., kotlinx.coroutines/CoroutineDispatcher = ..., kotlinx.coroutines.flow/MutableSharedFlow<dev.kord.gateway/Event> = ..., dev.kord.gateway/Compression = ...): dev.kord.gateway/DefaultGatewayData // dev.kord.gateway/DefaultGatewayData.copy|copy(kotlin.String;io.ktor.client.HttpClient;dev.kord.gateway.retry.Retry;dev.kord.common.ratelimit.RateLimiter;dev.kord.gateway.ratelimit.IdentifyRateLimiter;kotlinx.coroutines.CoroutineDispatcher;kotlinx.coroutines.flow.MutableSharedFlow<dev.kord.gateway.Event>;dev.kord.gateway.Compression){}[0]
final fun equals(kotlin/Any?): kotlin/Boolean // dev.kord.gateway/DefaultGatewayData.equals|equals(kotlin.Any?){}[0]
final fun hashCode(): kotlin/Int // dev.kord.gateway/DefaultGatewayData.hashCode|hashCode(){}[0]
final fun toString(): kotlin/String // dev.kord.gateway/DefaultGatewayData.toString|toString(){}[0]
Expand Down
2 changes: 2 additions & 0 deletions gateway/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ kotlin {
jvmMain {
dependencies {
implementation(libs.slf4j.api)
implementation(libs.zstd.jni)
}
}
jsMain {
dependencies {
implementation(libs.kotlin.node)
implementation(npm("fast-zlib", libs.versions.fastZlib.get()))
implementation(npm("fzstd", libs.versions.fzstd.get()))

// workaround for https://youtrack.jetbrains.com/issue/KT-43500 /
// https://youtrack.jetbrains.com/issue/KT-64109#focus=Comments-27-10064206.0-0 /
Expand Down
Loading