commonMain.io.polywrap.core.Invoker.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of polywrap-client Show documentation
Show all versions of polywrap-client Show documentation
Polywrap Client for JVM and Android
package io.polywrap.core
import io.polywrap.core.msgpack.EnvSerializer
import io.polywrap.core.msgpack.NullableKVSerializer
import io.polywrap.core.msgpack.msgPackDecode
import io.polywrap.core.msgpack.msgPackEncode
import io.polywrap.core.resolution.Uri
import kotlinx.serialization.serializer
import uniffi.polywrap_native.FfiInvoker
import uniffi.polywrap_native.FfiUri
import uniffi.polywrap_native.FfiUriResolutionContext
@OptIn(ExperimentalUnsignedTypes::class)
open class Invoker(val ffiInvoker: FfiInvoker) : WrapInvoker, AutoCloseable {
override fun invokeRaw(
uri: FfiUri,
method: String,
args: List?,
env: List?,
resolutionContext: FfiUriResolutionContext?
): List = uri.use {
ffiInvoker.invokeRaw(
uri = uri,
method = method,
args = args,
env = env,
resolutionContext = resolutionContext
)
}
override fun invokeRaw(
uri: Uri,
method: String,
args: ByteArray?,
env: ByteArray?,
resolutionContext: FfiUriResolutionContext?
): Result = runCatching {
uri.toFfi().use {
ffiInvoker.invokeRaw(
uri = it,
method = method,
args = args?.asUByteArray()?.toList(),
env = env?.asUByteArray()?.toList(),
resolutionContext = resolutionContext
)
}
}.map {
it.toUByteArray().asByteArray()
}
/**
* Invokes the wrapper at the specified URI with the provided method and arguments of type [T], and environment.
*
* @param uri The URI of the wrapper to be invoked.
* @param method The method to be called on the wrapper.
* @param args An instance of serializable type [T] representing the arguments to be passed to the method.
* @param env A map representing the environment to be used during the invocation.
* @param resolutionContext The [FfiUriResolutionContext] to be used during URI resolution, or null for a default context.
* The caller owns resolutionContext and is responsible for closing it to prevent a memory leak.
* @return An [InvokeResult] containing the invocation result of type [R], or an error if the invocation fails.
*/
inline fun invoke(
uri: Uri,
method: String,
args: T? = null,
env: WrapEnv? = null,
resolutionContext: FfiUriResolutionContext? = null
): InvokeResult = invokeRaw(
uri = uri,
method = method,
args = args?.let { msgPackEncode(serializer(), it) },
env = env?.let { msgPackEncode(EnvSerializer, it) },
resolutionContext = resolutionContext
).mapCatching {
if (R::class == Map::class) {
msgPackDecode(NullableKVSerializer, it).getOrThrow() as R
} else {
msgPackDecode(serializer(), it).getOrThrow()
}
}
/**
* Invokes the wrapper at the specified URI with the provided method and arguments of type [T], and environment.
*
* @param uri The URI of the wrapper to be invoked.
* @param method The method to be called on the wrapper.
* @param args An instance of serializable type [T] representing the arguments to be passed to the method.
* @param env An instance of serializable type [E] representing the environment to be used during the invocation.
* @param resolutionContext The [FfiUriResolutionContext] to be used during URI resolution, or null for a default context.
* The caller owns resolutionContext and is responsible for closing it to prevent a memory leak.
* @return An [InvokeResult] containing the invocation result of type [R], or an error if the invocation fails.
*/
inline fun invoke(
uri: Uri,
method: String,
args: T? = null,
env: E,
resolutionContext: FfiUriResolutionContext? = null
): InvokeResult = invokeRaw(
uri = uri,
method = method,
args = args?.let { msgPackEncode(serializer(), it) },
env = msgPackEncode(serializer(), env),
resolutionContext = resolutionContext
).mapCatching {
if (R::class == Map::class) {
msgPackDecode(NullableKVSerializer, it).getOrThrow() as R
} else {
msgPackDecode(serializer(), it).getOrThrow()
}
}
/**
* Invokes the wrapper at the specified URI with the provided method, arguments, and environment.
*
* @param uri The URI of the wrapper to be invoked.
* @param method The method to be called on the wrapper.
* @param args A map of arguments to be passed to the method.
* @param env A map representing the environment to be used during the invocation.
* @param resolutionContext The [FfiUriResolutionContext] to be used during URI resolution, or null for a default context.
* The caller owns resolutionContext and is responsible for closing it to prevent a memory leak.
* @return An [InvokeResult] containing the invocation result of type [R], or an error if the invocation fails.
*/
inline fun invoke(
uri: Uri,
method: String,
args: Map? = null,
env: WrapEnv? = null,
resolutionContext: FfiUriResolutionContext? = null
): InvokeResult = invokeRaw(
uri = uri,
method = method,
args = args?.let { msgPackEncode(NullableKVSerializer, it) },
env = env?.let { msgPackEncode(EnvSerializer, it) },
resolutionContext = resolutionContext
).mapCatching {
if (R::class == Map::class) {
msgPackDecode(NullableKVSerializer, it).getOrThrow() as R
} else {
msgPackDecode(serializer(), it).getOrThrow()
}
}
override fun getInterfaces(): Map>? {
return ffiInvoker.getInterfaces()?.let { ffiInterfaces ->
val result: MutableMap> = mutableMapOf()
ffiInterfaces.forEach { (interfaceUri, implementations) ->
val key = Uri(interfaceUri)
val value = implementations.map { Uri(it) }
result[key] = value
}
result
}
}
override fun getImplementations(uri: Uri): Result> = runCatching {
val implementations = uri.toFfi().use { ffiInvoker.getImplementations(it) }
val result = implementations.map { Uri(it) }
result
}
override fun getEnvByUri(uri: Uri): Result {
val envBytes = runCatching {
uri.toFfi().use { ffiInvoker.getEnvByUri(it) }
}.getOrElse {
return Result.failure(it)
} ?: return Result.success(null)
return envBytes
.toUByteArray()
.asByteArray()
.let { msgPackDecode(EnvSerializer, it) }
}
override fun close() = ffiInvoker.close()
}