From b40c09391789aa4cf745a3cf633df5fd42bc6596 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 28 Jun 2022 00:56:51 +0600 Subject: [PATCH] SimpleMapper, SimpleSuspendableMapper, mappers for CRUDRepo --- CHANGELOG.md | 4 +- .../dev/inmo/micro_utils/common/Mapper.kt | 53 +++++++++++ .../dev/inmo/micro_utils/repos/MapperRepo.kt | 13 +++ .../micro_utils/repos/mappers/CRUDMappers.kt | 89 +++++++++++++++++++ 4 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Mapper.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index aa1755adb01..5daa01e3045 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,11 @@ ## 0.11.7 +* `Common`: + * New abstractions `SimpleMapper` and `SimpleSuspendableMapper` * `Repos`: * `Common`: - * Add mappers for `ReadCRUDRepo` + * Add mappers for `CRUDRepo` ## 0.11.6 diff --git a/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Mapper.kt b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Mapper.kt new file mode 100644 index 00000000000..5fcee5a2749 --- /dev/null +++ b/common/src/commonMain/kotlin/dev/inmo/micro_utils/common/Mapper.kt @@ -0,0 +1,53 @@ +package dev.inmo.micro_utils.common + +interface SimpleMapper { + fun t1(from: T2): T1 + fun t2(from: T1): T2 + + operator fun T2.invoke(): T1 = t1(this) + operator fun T1.invoke(): T2 = t2(this) + + fun T2.convert(): T1 = t1(this) + fun T1.convert(): T2 = t2(this) +} + +class SimpleMapperImpl( + private val t1: (T2) -> T1, + private val t2: (T1) -> T2, +) : SimpleMapper { + override fun t1(from: T2): T1 = t1.invoke(from) + + override fun t2(from: T1): T2 = t2.invoke(from) +} + +@Suppress("NOTHING_TO_INLINE") +inline fun simpleMapper( + noinline t1: (T2) -> T1, + noinline t2: (T1) -> T2, +) = SimpleMapperImpl(t1, t2) + +interface SimpleSuspendableMapper { + suspend fun t1(from: T2): T1 + suspend fun t2(from: T1): T2 + + suspend operator fun T2.invoke(): T1 = t1(this) + suspend operator fun T1.invoke(): T2 = t2(this) + + suspend fun T2.convert(): T1 = t1(this) + suspend fun T1.convert(): T2 = t2(this) +} + +class SimpleSuspendableMapperImpl( + private val t1: suspend (T2) -> T1, + private val t2: suspend (T1) -> T2, +) : SimpleSuspendableMapper { + override suspend fun t1(from: T2): T1 = t1.invoke(from) + + override suspend fun t2(from: T1): T2 = t2.invoke(from) +} + +@Suppress("NOTHING_TO_INLINE") +inline fun simpleSuspendableMapper( + noinline t1: suspend (T2) -> T1, + noinline t2: suspend (T1) -> T2, +) = SimpleSuspendableMapperImpl(t1, t2) diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapperRepo.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapperRepo.kt index 313c7970f60..cb207e0972a 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapperRepo.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/MapperRepo.kt @@ -1,7 +1,20 @@ package dev.inmo.micro_utils.repos +import dev.inmo.micro_utils.common.* + @Suppress("UNCHECKED_CAST") interface MapperRepo { + val keyMapper: SimpleSuspendableMapper + get() = simpleSuspendableMapper( + { it.toInnerKey() }, + { it.toOutKey() } + ) + val valueMapper: SimpleSuspendableMapper + get() = simpleSuspendableMapper( + { it.toInnerValue() }, + { it.toOutValue() } + ) + suspend fun FromKey.toOutKey() = this as ToKey suspend fun FromValue.toOutValue() = this as ToValue diff --git a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/CRUDMappers.kt b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/CRUDMappers.kt index 0f9e45e58c0..82cb94d72b8 100644 --- a/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/CRUDMappers.kt +++ b/repos/common/src/commonMain/kotlin/dev/inmo/micro_utils/repos/mappers/CRUDMappers.kt @@ -1,7 +1,11 @@ package dev.inmo.micro_utils.repos.mappers +import dev.inmo.micro_utils.common.SimpleSuspendableMapper +import dev.inmo.micro_utils.common.simpleSuspendableMapper import dev.inmo.micro_utils.pagination.* import dev.inmo.micro_utils.repos.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map open class MapperReadCRUDRepo( private val to: ReadCRUDRepo, @@ -40,3 +44,88 @@ inline fun ): ReadCRUDRepo = withMapper( mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom) ) + +open class MapperWriteCRUDRepo( + private val to: WriteCRUDRepo, + mapper: MapperRepo, + inputMapper: SimpleSuspendableMapper +) : WriteCRUDRepo, + MapperRepo by mapper, + SimpleSuspendableMapper by inputMapper { + override val newObjectsFlow: Flow = to.newObjectsFlow.map { it.toInnerValue() } + override val updatedObjectsFlow: Flow = to.updatedObjectsFlow.map { it.toInnerValue() } + override val deletedObjectsIdsFlow: Flow = to.deletedObjectsIdsFlow.map { it.toInnerKey() } + + override suspend fun deleteById(ids: List) = to.deleteById(ids.map { it.toOutKey() }) + + override suspend fun update( + values: List> + ): List = to.update( + values.map { + it.first.toOutKey() to it.second.convert() + } + ).map { it.toInnerValue() } + + override suspend fun update( + id: FromId, + value: FromInput + ): FromRegistered? = to.update(id.toOutKey(), value.convert()) ?.toInnerValue() + + override suspend fun create(values: List): List = to.create( + values.map { + it.convert() + } + ).map { + it.toInnerValue() + } + +} + +@Suppress("NOTHING_TO_INLINE") +inline fun WriteCRUDRepo.withMapper( + mapper: MapperRepo, + simpleSuspendableMapper: SimpleSuspendableMapper +): WriteCRUDRepo = MapperWriteCRUDRepo(this, mapper, simpleSuspendableMapper) + +@Suppress("NOTHING_TO_INLINE") +inline fun WriteCRUDRepo.withMapper( + crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey }, + crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue }, + crossinline inputFromToTo: suspend FromInput.() -> ToInput = { this as ToInput }, + crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey }, + crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue }, + crossinline inputToToFrom: suspend ToInput.() -> FromInput = { this as FromInput }, +): WriteCRUDRepo = withMapper( + mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom), + simpleSuspendableMapper({ inputToToFrom(it) }, { inputFromToTo(it) }) +) + +@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE") +open class MapperCRUDRepo( + private val to: CRUDRepo, + private val mapper: MapperRepo, + private val inputMapper: SimpleSuspendableMapper +) : CRUDRepo, + MapperRepo by mapper, + ReadCRUDRepo by MapperReadCRUDRepo(to, mapper), + WriteCRUDRepo by MapperWriteCRUDRepo(to, mapper, inputMapper) + + +@Suppress("NOTHING_TO_INLINE") +inline fun CRUDRepo.withMapper( + mapper: MapperRepo, + simpleSuspendableMapper: SimpleSuspendableMapper +): CRUDRepo = MapperCRUDRepo(this, mapper, simpleSuspendableMapper) + +@Suppress("NOTHING_TO_INLINE") +inline fun CRUDRepo.withMapper( + crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey }, + crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue }, + crossinline inputFromToTo: suspend FromInput.() -> ToInput = { this as ToInput }, + crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey }, + crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue }, + crossinline inputToToFrom: suspend ToInput.() -> FromInput = { this as FromInput }, +): CRUDRepo = withMapper( + mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom), + simpleSuspendableMapper({ inputToToFrom(it) }, { inputFromToTo(it) }) +)