Update actions signatures to avoid unnecessary nulls

This commit is contained in:
Alexander Nozik 2023-05-25 09:51:27 +03:00
parent b7be570271
commit 25d7fe0a8e
4 changed files with 23 additions and 15 deletions

View File

@ -25,9 +25,9 @@ private suspend fun <D : Device, T> DevicePropertySpec<D, T>.readMeta(device: D)
private suspend fun <D : Device, I, O> DeviceActionSpec<D, I, O>.executeWithMeta( private suspend fun <D : Device, I, O> DeviceActionSpec<D, I, O>.executeWithMeta(
device: D, device: D,
item: Meta?, item: Meta,
): Meta? { ): Meta? {
val arg = item?.let { inputConverter.metaToObject(item) } val arg: I = inputConverter.metaToObject(item) ?: error("Failed to convert $item with $inputConverter")
val res = execute(device, arg) val res = execute(device, arg)
return res?.let { outputConverter.objectToMeta(res) } return res?.let { outputConverter.objectToMeta(res) }
} }
@ -146,7 +146,7 @@ public abstract class DeviceBase<D : Device>(
override suspend fun execute(actionName: String, argument: Meta?): Meta? { override suspend fun execute(actionName: String, argument: Meta?): Meta? {
val spec = actions[actionName] ?: error("Action with name $actionName not found") val spec = actions[actionName] ?: error("Action with name $actionName not found")
return spec.executeWithMeta(self, argument) return spec.executeWithMeta(self, argument ?: Meta.EMPTY)
} }
} }

View File

@ -66,7 +66,7 @@ public interface DeviceActionSpec<in D : Device, I, O> {
/** /**
* Execute action on a device * Execute action on a device
*/ */
public suspend fun execute(device: D, input: I?): O? public suspend fun execute(device: D, input: I): O
} }
/** /**
@ -137,5 +137,8 @@ public suspend fun <D : Device> D.invalidate(propertySpec: DevicePropertySpec<D,
/** /**
* Execute the action with name according to [actionSpec] * Execute the action with name according to [actionSpec]
*/ */
public suspend fun <I, O, D : Device> D.execute(actionSpec: DeviceActionSpec<D, I, O>, input: I? = null): O? = public suspend fun <I, O, D : Device> D.execute(actionSpec: DeviceActionSpec<D, I, O>, input: I): O =
actionSpec.execute(this, input) actionSpec.execute(this, input)
public suspend fun <O, D : Device> D.execute(actionSpec: DeviceActionSpec<D, Unit, O>): O =
actionSpec.execute(this, Unit)

View File

@ -12,6 +12,13 @@ import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1 import kotlin.reflect.KProperty1
public object UnitMetaConverter: MetaConverter<Unit>{
override fun metaToObject(meta: Meta): Unit = Unit
override fun objectToMeta(obj: Unit): Meta = Meta.EMPTY
}
public val MetaConverter.Companion.unit: MetaConverter<Unit> get() = UnitMetaConverter
@OptIn(InternalDeviceAPI::class) @OptIn(InternalDeviceAPI::class)
public abstract class DeviceSpec<D : Device> { public abstract class DeviceSpec<D : Device> {
@ -165,7 +172,7 @@ public abstract class DeviceSpec<D : Device> {
outputConverter: MetaConverter<O>, outputConverter: MetaConverter<O>,
descriptorBuilder: ActionDescriptor.() -> Unit = {}, descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
execute: suspend D.(I?) -> O?, execute: suspend D.(I) -> O,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, I, O>>> =
PropertyDelegateProvider { _: DeviceSpec<D>, property -> PropertyDelegateProvider { _: DeviceSpec<D>, property ->
val actionName = name ?: property.name val actionName = name ?: property.name
@ -175,7 +182,7 @@ public abstract class DeviceSpec<D : Device> {
override val inputConverter: MetaConverter<I> = inputConverter override val inputConverter: MetaConverter<I> = inputConverter
override val outputConverter: MetaConverter<O> = outputConverter override val outputConverter: MetaConverter<O> = outputConverter
override suspend fun execute(device: D, input: I?): O? = withContext(device.coroutineContext) { override suspend fun execute(device: D, input: I): O = withContext(device.coroutineContext) {
device.execute(input) device.execute(input)
} }
} }
@ -191,7 +198,7 @@ public abstract class DeviceSpec<D : Device> {
public fun metaAction( public fun metaAction(
descriptorBuilder: ActionDescriptor.() -> Unit = {}, descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
execute: suspend D.(Meta?) -> Meta?, execute: suspend D.(Meta) -> Meta,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> =
action( action(
MetaConverter.Companion.meta, MetaConverter.Companion.meta,
@ -209,15 +216,14 @@ public abstract class DeviceSpec<D : Device> {
descriptorBuilder: ActionDescriptor.() -> Unit = {}, descriptorBuilder: ActionDescriptor.() -> Unit = {},
name: String? = null, name: String? = null,
execute: suspend D.() -> Unit, execute: suspend D.() -> Unit,
): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Meta, Meta>>> = ): PropertyDelegateProvider<DeviceSpec<D>, ReadOnlyProperty<DeviceSpec<D>, DeviceActionSpec<D, Unit, Unit>>> =
action( action(
MetaConverter.Companion.meta, MetaConverter.Companion.unit,
MetaConverter.Companion.meta, MetaConverter.Companion.unit,
descriptorBuilder, descriptorBuilder,
name name
) { ) {
execute() execute()
null
} }
} }

View File

@ -68,11 +68,10 @@ class DemoDevice(context: Context, meta: Meta) : DeviceBySpec<IDemoDevice>(Compa
} }
val resetScale by action(MetaConverter.meta, MetaConverter.meta) { val resetScale by unitAction {
write(timeScale, 5000.0) write(timeScale, 5000.0)
write(sinScale, 1.0) write(sinScale, 1.0)
write(cosScale, 1.0) write(cosScale, 1.0)
null
} }
override suspend fun IDemoDevice.onOpen() { override suspend fun IDemoDevice.onOpen() {