-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
63 changed files
with
4,018 additions
and
683 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 0 additions & 20 deletions
20
compiler-plugin/compiler-plugin-backend/src/main/core/kotlinx/rpc/codegen/RPCIrPlugin.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
core/src/commonMain/kotlin/kotlinx/rpc/UninitializedRPCFieldException.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* | ||
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.rpc | ||
|
||
import kotlin.reflect.KProperty | ||
|
||
/** | ||
* Thrown when an uninitialized field of an RPC interface is accessed. | ||
* | ||
* Use [awaitFieldInitialization] to await for the field initialization | ||
*/ | ||
public class UninitializedRPCFieldException(serviceName: String, property: KProperty<*>): Exception() { | ||
override val message: String = "${property.name} field of RPC service \"$serviceName\" in not initialized" | ||
} |
88 changes: 88 additions & 0 deletions
88
core/src/commonMain/kotlin/kotlinx/rpc/awaitFieldInitialization.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.rpc | ||
|
||
import kotlinx.rpc.internal.RPCDeferredField | ||
import kotlinx.rpc.internal.RPCServiceFieldsProvider | ||
import kotlinx.rpc.internal.findRPCStubProvider | ||
import kotlinx.rpc.internal.safeCast | ||
import kotlin.reflect.KClass | ||
|
||
/** | ||
* Waits for the initialization of an RPC field in the generated client: | ||
* | ||
* ```kotlin | ||
* interface MyService : RPC { | ||
* val stateFlow: StateFlow<Int> | ||
* } | ||
* | ||
* val service = rpcClient.withService<MyService>() | ||
* val currentValue = service.awaitFieldInitialization { stateFlow }.value | ||
* ``` | ||
* | ||
* @param T service type | ||
* @param R field type | ||
* @param getter function that returns the field of the context service to wait for. | ||
* @return service filed after it was initialized. | ||
*/ | ||
public suspend fun <T : RPC, R> T.awaitFieldInitialization(getter: T.() -> R): R { | ||
val field = getter() | ||
|
||
if (field is RPCDeferredField<*>) { | ||
@Suppress("UNCHECKED_CAST") | ||
return (field as RPCDeferredField<R>).await() | ||
} | ||
|
||
error("Please choose required field for a valid RPC client generated by RPCClient.withService method") | ||
} | ||
|
||
/** | ||
* Waits for the initialization of all RPC fields in the generated client: | ||
* | ||
* ```kotlin | ||
* interface MyService : RPC { | ||
* val stateFlow1: StateFlow<Int> | ||
* val stateFlow2: StateFlow<Int> | ||
* } | ||
* | ||
* val service = rpcClient.withService<MyService>() | ||
* val currentValue = service.awaitFieldInitialization() | ||
* // fields `stateFlow1` and `stateFlow2` are initialized | ||
* ``` | ||
* | ||
* @param T service type | ||
* @return specified service, after all of it's field were initialized. | ||
*/ | ||
public suspend inline fun <reified T : RPC> T.awaitFieldInitialization(): T { | ||
return awaitFieldInitialization(T::class) | ||
} | ||
|
||
/** | ||
* Waits for the initialization of all RPC fields in the generated client: | ||
* | ||
* ```kotlin | ||
* interface MyService : RPC { | ||
* val stateFlow1: StateFlow<Int> | ||
* val stateFlow2: StateFlow<Int> | ||
* } | ||
* | ||
* val service = rpcClient.withService<MyService>() | ||
* val currentValue = service.awaitFieldInitialization(MyService::class) | ||
* // fields `stateFlow1` and `stateFlow2` are initialized | ||
* ``` | ||
* | ||
* @param T service type | ||
* @param kClass [KClass] of the [T] type. | ||
* @return specified service, after all of it's field were initialized. | ||
*/ | ||
public suspend fun <T : RPC> T.awaitFieldInitialization(kClass: KClass<T>): T { | ||
findRPCStubProvider<RPCServiceFieldsProvider<T>>(kClass, RPCServiceFieldsProvider::class.safeCast()) | ||
.rpcFields(this) | ||
.forEach { field -> | ||
field.await() | ||
} | ||
|
||
return this | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/* | ||
* Copyright 2023-2024 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package kotlinx.rpc | ||
|
||
import kotlinx.atomicfu.atomic | ||
import kotlinx.rpc.internal.RPCStubServiceProvider | ||
import kotlinx.rpc.internal.findRPCStubProvider | ||
import kotlinx.rpc.internal.kClass | ||
import kotlinx.rpc.internal.safeCast | ||
import kotlin.reflect.KClass | ||
import kotlin.reflect.KType | ||
|
||
/** | ||
* Creates instance of the generated service [T], that is able to communicate with server using RPCClient. | ||
* | ||
* [awaitFieldInitialization] method can be used on that instance. | ||
* | ||
* @param T the exact type of the service to be created. | ||
* @return instance of the generated service. | ||
*/ | ||
public inline fun <reified T : RPC> RPCClient.withService(): T { | ||
return withService(T::class) | ||
} | ||
|
||
/** | ||
* Creates instance of the generated service [T], that is able to communicate with server using RPCClient. | ||
* | ||
* [awaitFieldInitialization] method can be used on that instance. | ||
* | ||
* @param T the exact type of the service to be created. | ||
* @param serviceKType [KType] of the service to be created. | ||
* @return instance of the generated service. | ||
*/ | ||
public fun <T : RPC> RPCClient.withService(serviceKType: KType): T { | ||
return withService(serviceKType.kClass()) | ||
} | ||
|
||
/** | ||
* Counter for locally added services. | ||
* Used to differentiate uniques local services, regardless of their type. | ||
*/ | ||
private val SERVICE_ID = atomic(0L) | ||
|
||
/** | ||
* Creates instance of the generated service [T], that is able to communicate with server using RPCClient. | ||
* | ||
* [awaitFieldInitialization] method can be used on that instance. | ||
* | ||
* @param T the exact type of the service to be created. | ||
* @param serviceKClass [KClass] of the service to be created. | ||
* @return instance of the generated service. | ||
*/ | ||
public fun <T : RPC> RPCClient.withService(serviceKClass: KClass<T>): T { | ||
val provider = findRPCStubProvider<RPCStubServiceProvider<T>>( | ||
kClass = serviceKClass, | ||
resultKClass = RPCStubServiceProvider::class.safeCast(), | ||
) | ||
|
||
val id = SERVICE_ID.incrementAndGet() | ||
|
||
return provider.withClient(id, this) | ||
} |
Oops, something went wrong.