mirror of
https://github.com/InsanusMokrassar/MicroUtils.git
synced 2025-09-17 22:39:25 +00:00
Compare commits
64 Commits
Author | SHA1 | Date | |
---|---|---|---|
c349af999b | |||
9a5709a34d | |||
28d311160b | |||
1ca7081a40 | |||
5ce8ebe82c | |||
a7a88b29b9 | |||
cd7b982385 | |||
ee59100075 | |||
f808ac58ef | |||
f33ada5396 | |||
984d781f2f | |||
dd33e1e8bc | |||
2950de29e5 | |||
50a8799f9d | |||
bdb0ce6fc7 | |||
18ec2bca96 | |||
937ef48794 | |||
6331f13e9a | |||
5213a2ff8e | |||
087d7452fd | |||
703094c924 | |||
eea645c865 | |||
324832a189 | |||
d55d735c51 | |||
e3ff1b9609 | |||
70c31966ca | |||
0e4188882f | |||
6bf0ce92ba | |||
d51bdc5086 | |||
f04f262cee | |||
0f172055ef | |||
e5dd4363f1 | |||
a3a48bbaac | |||
5e716fb9a8 | |||
11a36153cc | |||
8bee354f04 | |||
f7dd2b5ce7 | |||
8ca10c00bb | |||
905c7e8eda | |||
d4c5e849bf | |||
8250a2a021 | |||
01b3df7b8c | |||
daa6e4aff5 | |||
23bcb26a58 | |||
e55f60c30b | |||
0d0c16e16d | |||
540d5cce7c | |||
a548b00979 | |||
4b7ca6d565 | |||
0473fa238c | |||
cfc7119697 | |||
22a6520d3e | |||
fb25e91191 | |||
c116b270b6 | |||
aa2d598689 | |||
5ef3bb746b | |||
037616e271 | |||
abbea906f1 | |||
9132e216c9 | |||
12a7e3c4af | |||
b40c093917 | |||
7ac12455c8 | |||
5043eec7a2 | |||
cf31f53e01 |
@@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
name: Publish package to GitHub Packages
|
name: Build
|
||||||
on: [push]
|
on: [push]
|
||||||
jobs:
|
jobs:
|
||||||
publishing:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -20,9 +20,9 @@ jobs:
|
|||||||
mv gradle.properties.tmp gradle.properties
|
mv gradle.properties.tmp gradle.properties
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./gradlew build
|
run: ./gradlew build
|
||||||
- name: Publish
|
# - name: Publish
|
||||||
continue-on-error: true
|
# continue-on-error: true
|
||||||
run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository
|
# run: ./gradlew --no-parallel publishAllPublicationsToGithubPackagesRepository
|
||||||
env:
|
# env:
|
||||||
GITHUBPACKAGES_USER: ${{ github.actor }}
|
# GITHUBPACKAGES_USER: ${{ github.actor }}
|
||||||
GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
# GITHUBPACKAGES_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
|
2
.github/workflows/dokka_push.yml
vendored
2
.github/workflows/dokka_push.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
run: cd /usr/local/lib/android/sdk/build-tools/32.0.0/ && mv d8 dx && cd lib && mv d8.jar dx.jar
|
run: cd /usr/local/lib/android/sdk/build-tools/32.0.0/ && mv d8 dx && cd lib && mv d8.jar dx.jar
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./gradlew dokkaHtml
|
run: ./gradlew build && ./gradlew dokkaHtml
|
||||||
- name: Publish KDocs
|
- name: Publish KDocs
|
||||||
uses: peaceiris/actions-gh-pages@v3
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
with:
|
with:
|
||||||
|
85
CHANGELOG.md
85
CHANGELOG.md
@@ -1,5 +1,90 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.12.1
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Ktor`: `2.0.3` -> `2.1.0`
|
||||||
|
|
||||||
|
## 0.12.0
|
||||||
|
|
||||||
|
**OLD DEPRECATIONS HAVE BEEN REMOVED**
|
||||||
|
|
||||||
|
**MINIMAL ANDROID API HAS BEEN ENLARGED UP TO API 21 (Android 5.0)**
|
||||||
|
|
||||||
|
* `Versions`
|
||||||
|
* `Kotlin`: `1.6.21` -> `1.7.0`
|
||||||
|
* `Coroutines`: `1.6.3` -> `1.6.4`
|
||||||
|
* `Exposed`: `0.38.2` -> `0.39.2`
|
||||||
|
* `Compose`: `1.2.0-alpha01-dev729` -> `1.2.0-alpha01-dev753`
|
||||||
|
* `Klock`: `2.7.0` -> `3.0.0`
|
||||||
|
* `uuid`: `0.4.1` -> `0.5.0`
|
||||||
|
* `Android Core KTX`: `1.7.0` -> `1.8.0`
|
||||||
|
* `Android AppCompat`: `1.4.1` -> `1.4.2`
|
||||||
|
* `Ktor`:
|
||||||
|
* All previously standard functions related to work with binary data by default have been deprecated
|
||||||
|
|
||||||
|
## 0.11.14
|
||||||
|
|
||||||
|
* `Pagination`:
|
||||||
|
* `PaginationResult` got new field `objectsNumber` which by default is a times between `pagesNumber` and `size`
|
||||||
|
|
||||||
|
## 0.11.13
|
||||||
|
|
||||||
|
* `Versions`:
|
||||||
|
* `Coroutines`: `1.6.3` -> `1.6.4`
|
||||||
|
* `Compose`: `1.2.0-alpha01-dev629` -> `1.2.0-alpha01-dev731`
|
||||||
|
|
||||||
|
## 0.11.12
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Common`:
|
||||||
|
* `JVM`:
|
||||||
|
* Fixes in `ReadFileKeyValueRepo` methods (`values`/`keys`)
|
||||||
|
|
||||||
|
## 0.11.11
|
||||||
|
|
||||||
|
* `Crypto`:
|
||||||
|
* `hmacSha256` has been deprecated
|
||||||
|
* `Ktor`:
|
||||||
|
* `Client`:
|
||||||
|
* `BodyPair` has been deprecated
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* New interface `CacheRepo`
|
||||||
|
* New interface `FullCacheRepo`
|
||||||
|
* `actualize*` methods inside of full cache repos now open for overriding
|
||||||
|
|
||||||
|
## 0.11.10
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Cache`:
|
||||||
|
* `KVCache` has been replaced to the package `dev.inmo.micro_utils.repos.cache`
|
||||||
|
* `SimpleKVCache` has been replaced to the package `dev.inmo.micro_utils.repos.cache`
|
||||||
|
* New `KVCache` subtype - `FullKVCache`
|
||||||
|
* Add `Full*` variants of standard repos
|
||||||
|
* Add `cached`/`caching` (for write repos) extensions for all standard types of repos
|
||||||
|
|
||||||
|
## 0.11.9
|
||||||
|
|
||||||
|
* `Versions`
|
||||||
|
* `Coroutines`: `1.6.1` -> `1.6.3`
|
||||||
|
* `Ktor`: `2.0.2` -> `2.0.3`
|
||||||
|
* `Compose`: `1.2.0-alpha01-dev686` -> `1.2.0-alpha01-dev729`
|
||||||
|
|
||||||
|
## 0.11.8
|
||||||
|
|
||||||
|
* `Repos`:
|
||||||
|
* `Common`:
|
||||||
|
* Fixes in `FileKeyValueRepo`
|
||||||
|
|
||||||
|
## 0.11.7
|
||||||
|
|
||||||
|
* `Common`:
|
||||||
|
* New abstractions `SimpleMapper` and `SimpleSuspendableMapper`
|
||||||
|
* `Repos`:
|
||||||
|
* `Common`:
|
||||||
|
* Add mappers for `CRUDRepo`
|
||||||
|
|
||||||
## 0.11.6
|
## 0.11.6
|
||||||
|
|
||||||
* `FSM`:
|
* `FSM`:
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("unused", "NOTHING_TO_INLINE")
|
||||||
|
|
||||||
package dev.inmo.micro_utils.common
|
package dev.inmo.micro_utils.common
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
@@ -21,11 +23,10 @@ import kotlinx.serialization.encoding.*
|
|||||||
sealed interface Either<T1, T2> {
|
sealed interface Either<T1, T2> {
|
||||||
val optionalT1: Optional<T1>
|
val optionalT1: Optional<T1>
|
||||||
val optionalT2: Optional<T2>
|
val optionalT2: Optional<T2>
|
||||||
@Deprecated("Use optionalT1 instead", ReplaceWith("optionalT1"))
|
|
||||||
val t1: T1?
|
val t1OrNull: T1?
|
||||||
get() = optionalT1.dataOrNull()
|
get() = optionalT1.dataOrNull()
|
||||||
@Deprecated("Use optionalT2 instead", ReplaceWith("optionalT2"))
|
val t2OrNull: T2?
|
||||||
val t2: T2?
|
|
||||||
get() = optionalT2.dataOrNull()
|
get() = optionalT2.dataOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ class EitherSerializer<T1, T2>(
|
|||||||
t1Serializer: KSerializer<T1>,
|
t1Serializer: KSerializer<T1>,
|
||||||
t2Serializer: KSerializer<T2>,
|
t2Serializer: KSerializer<T2>,
|
||||||
) : KSerializer<Either<T1, T2>> {
|
) : KSerializer<Either<T1, T2>> {
|
||||||
@OptIn(InternalSerializationApi::class)
|
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
|
||||||
override val descriptor: SerialDescriptor = buildSerialDescriptor(
|
override val descriptor: SerialDescriptor = buildSerialDescriptor(
|
||||||
"TypedSerializer",
|
"TypedSerializer",
|
||||||
SerialKind.CONTEXTUAL
|
SerialKind.CONTEXTUAL
|
||||||
@@ -96,7 +97,7 @@ class EitherSerializer<T1, T2>(
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class EitherFirst<T1, T2>(
|
data class EitherFirst<T1, T2>(
|
||||||
override val t1: T1
|
val t1: T1
|
||||||
) : Either<T1, T2> {
|
) : Either<T1, T2> {
|
||||||
override val optionalT1: Optional<T1> = t1.optional
|
override val optionalT1: Optional<T1> = t1.optional
|
||||||
override val optionalT2: Optional<T2> = Optional.absent()
|
override val optionalT2: Optional<T2> = Optional.absent()
|
||||||
@@ -107,7 +108,7 @@ data class EitherFirst<T1, T2>(
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class EitherSecond<T1, T2>(
|
data class EitherSecond<T1, T2>(
|
||||||
override val t2: T2
|
val t2: T2
|
||||||
) : Either<T1, T2> {
|
) : Either<T1, T2> {
|
||||||
override val optionalT1: Optional<T1> = Optional.absent()
|
override val optionalT1: Optional<T1> = Optional.absent()
|
||||||
override val optionalT2: Optional<T2> = t2.optional
|
override val optionalT2: Optional<T2> = t2.optional
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
package dev.inmo.micro_utils.common
|
||||||
|
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
|
interface SimpleMapper<T1, T2> {
|
||||||
|
fun convertToT1(from: T2): T1
|
||||||
|
fun convertToT2(from: T1): T2
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("convertFromT2")
|
||||||
|
fun <T1, T2> SimpleMapper<T1, T2>.convert(from: T2) = convertToT1(from)
|
||||||
|
@JvmName("convertFromT1")
|
||||||
|
fun <T1, T2> SimpleMapper<T1, T2>.convert(from: T1) = convertToT2(from)
|
||||||
|
|
||||||
|
class SimpleMapperImpl<T1, T2>(
|
||||||
|
private val t1: (T2) -> T1,
|
||||||
|
private val t2: (T1) -> T2,
|
||||||
|
) : SimpleMapper<T1, T2> {
|
||||||
|
override fun convertToT1(from: T2): T1 = t1.invoke(from)
|
||||||
|
|
||||||
|
override fun convertToT2(from: T1): T2 = t2.invoke(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <T1, T2> simpleMapper(
|
||||||
|
noinline t1: (T2) -> T1,
|
||||||
|
noinline t2: (T1) -> T2,
|
||||||
|
) = SimpleMapperImpl(t1, t2)
|
||||||
|
|
||||||
|
interface SimpleSuspendableMapper<T1, T2> {
|
||||||
|
suspend fun convertToT1(from: T2): T1
|
||||||
|
suspend fun convertToT2(from: T1): T2
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmName("convertFromT2")
|
||||||
|
suspend fun <T1, T2> SimpleSuspendableMapper<T1, T2>.convert(from: T2) = convertToT1(from)
|
||||||
|
@JvmName("convertFromT1")
|
||||||
|
suspend fun <T1, T2> SimpleSuspendableMapper<T1, T2>.convert(from: T1) = convertToT2(from)
|
||||||
|
|
||||||
|
class SimpleSuspendableMapperImpl<T1, T2>(
|
||||||
|
private val t1: suspend (T2) -> T1,
|
||||||
|
private val t2: suspend (T1) -> T2,
|
||||||
|
) : SimpleSuspendableMapper<T1, T2> {
|
||||||
|
override suspend fun convertToT1(from: T2): T1 = t1.invoke(from)
|
||||||
|
|
||||||
|
override suspend fun convertToT2(from: T1): T2 = t2.invoke(from)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <T1, T2> simpleSuspendableMapper(
|
||||||
|
noinline t1: suspend (T2) -> T1,
|
||||||
|
noinline t2: suspend (T1) -> T2,
|
||||||
|
) = SimpleSuspendableMapperImpl(t1, t2)
|
@@ -41,10 +41,18 @@ data class Optional<T> internal constructor(
|
|||||||
inline val <T> T.optional
|
inline val <T> T.optional
|
||||||
get() = Optional.presented(this)
|
get() = Optional.presented(this)
|
||||||
|
|
||||||
|
inline val <T : Any> T?.optionalOrAbsentIfNull
|
||||||
|
get() = if (this == null) {
|
||||||
|
Optional.absent<T>()
|
||||||
|
} else {
|
||||||
|
Optional.presented(this)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
||||||
*/
|
*/
|
||||||
inline fun <T> Optional<T>.onPresented(block: (T) -> Unit): Optional<T> = apply {
|
inline fun <T> Optional<T>.onPresented(block: (T) -> Unit): Optional<T> = apply {
|
||||||
|
@OptIn(Warning::class)
|
||||||
if (dataPresented) { @Suppress("UNCHECKED_CAST") block(data as T) }
|
if (dataPresented) { @Suppress("UNCHECKED_CAST") block(data as T) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,6 +60,7 @@ inline fun <T> Optional<T>.onPresented(block: (T) -> Unit): Optional<T> = apply
|
|||||||
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
||||||
*/
|
*/
|
||||||
inline fun <T, R> Optional<T>.mapOnPresented(block: (T) -> R): R? = run {
|
inline fun <T, R> Optional<T>.mapOnPresented(block: (T) -> R): R? = run {
|
||||||
|
@OptIn(Warning::class)
|
||||||
if (dataPresented) { @Suppress("UNCHECKED_CAST") block(data as T) } else null
|
if (dataPresented) { @Suppress("UNCHECKED_CAST") block(data as T) } else null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +68,7 @@ inline fun <T, R> Optional<T>.mapOnPresented(block: (T) -> R): R? = run {
|
|||||||
* Will call [block] when data absent ([Optional.dataPresented] == false)
|
* Will call [block] when data absent ([Optional.dataPresented] == false)
|
||||||
*/
|
*/
|
||||||
inline fun <T> Optional<T>.onAbsent(block: () -> Unit): Optional<T> = apply {
|
inline fun <T> Optional<T>.onAbsent(block: () -> Unit): Optional<T> = apply {
|
||||||
|
@OptIn(Warning::class)
|
||||||
if (!dataPresented) { block() }
|
if (!dataPresented) { block() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,27 +76,22 @@ inline fun <T> Optional<T>.onAbsent(block: () -> Unit): Optional<T> = apply {
|
|||||||
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
* Will call [block] when data presented ([Optional.dataPresented] == true)
|
||||||
*/
|
*/
|
||||||
inline fun <T, R> Optional<T>.mapOnAbsent(block: () -> R): R? = run {
|
inline fun <T, R> Optional<T>.mapOnAbsent(block: () -> R): R? = run {
|
||||||
if (!dataPresented) { @Suppress("UNCHECKED_CAST") block() } else null
|
@OptIn(Warning::class)
|
||||||
|
if (!dataPresented) { block() } else null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or null otherwise
|
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or null otherwise
|
||||||
*/
|
*/
|
||||||
fun <T> Optional<T>.dataOrNull() = if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else null
|
fun <T> Optional<T>.dataOrNull() = @OptIn(Warning::class) if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or throw [throwable] otherwise
|
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or throw [throwable] otherwise
|
||||||
*/
|
*/
|
||||||
fun <T> Optional<T>.dataOrThrow(throwable: Throwable) = if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else throw throwable
|
fun <T> Optional<T>.dataOrThrow(throwable: Throwable) = @OptIn(Warning::class) if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else throw throwable
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or call [block] and returns the result of it
|
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or call [block] and returns the result of it
|
||||||
*/
|
*/
|
||||||
inline fun <T> Optional<T>.dataOrElse(block: () -> T) = if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else block()
|
inline fun <T> Optional<T>.dataOrElse(block: () -> T) = @OptIn(Warning::class) if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else block()
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns [Optional.data] if [Optional.dataPresented] of [this] is true, or call [block] and returns the result of it
|
|
||||||
*/
|
|
||||||
@Deprecated("dataOrElse now is inline", ReplaceWith("dataOrElse", "dev.inmo.micro_utils.common.dataOrElse"))
|
|
||||||
suspend fun <T> Optional<T>.dataOrElseSuspendable(block: suspend () -> T) = if (dataPresented) @Suppress("UNCHECKED_CAST") (data as T) else block()
|
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.crypto
|
|
||||||
|
|
||||||
expect fun SourceString.hmacSha256(key: String): String
|
|
@@ -1,12 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.crypto
|
|
||||||
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
class HmacSHA256 {
|
|
||||||
@Test
|
|
||||||
fun testSimpleHmacSHA256Message() {
|
|
||||||
val text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
|
||||||
val resultSha = text.hmacSha256("Example")
|
|
||||||
assertEquals("5a481d59329ef862b158eedc95392ebb22492ba3014661a3379d8201db992484", resultSha)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,7 +7,3 @@ external interface CryptoJs {
|
|||||||
@JsModule("crypto-js")
|
@JsModule("crypto-js")
|
||||||
@JsNonModule
|
@JsNonModule
|
||||||
external val CryptoJS: CryptoJs
|
external val CryptoJS: CryptoJs
|
||||||
|
|
||||||
actual fun SourceString.hmacSha256(key: String): String {
|
|
||||||
return CryptoJS.asDynamic().HmacSHA256(this, key).toString().unsafeCast<String>()
|
|
||||||
}
|
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.crypto
|
|
||||||
|
|
||||||
import javax.crypto.Mac
|
|
||||||
import javax.crypto.spec.SecretKeySpec
|
|
||||||
|
|
||||||
actual fun SourceString.hmacSha256(key: String): String {
|
|
||||||
val mac = Mac.getInstance("HmacSHA256")
|
|
||||||
|
|
||||||
val secretKey = SecretKeySpec(key.toByteArray(), "HmacSHA256")
|
|
||||||
mac.init(secretKey)
|
|
||||||
|
|
||||||
return mac.doFinal(toByteArray()).hex()
|
|
||||||
}
|
|
@@ -47,24 +47,11 @@ fun <I : O, O : State> CheckableHandlerHolder(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("CheckableHandlerHolder"))
|
|
||||||
fun <I : O, O : State> StateHandlerHolder(
|
|
||||||
inputKlass: KClass<I>,
|
|
||||||
strict: Boolean = false,
|
|
||||||
delegateTo: StatesHandler<I, O>
|
|
||||||
) = CheckableHandlerHolder(inputKlass, strict, delegateTo)
|
|
||||||
|
|
||||||
inline fun <reified I : O, O : State> CheckableHandlerHolder(
|
inline fun <reified I : O, O : State> CheckableHandlerHolder(
|
||||||
strict: Boolean = false,
|
strict: Boolean = false,
|
||||||
delegateTo: StatesHandler<I, O>
|
delegateTo: StatesHandler<I, O>
|
||||||
) = CheckableHandlerHolder(I::class, strict, delegateTo)
|
) = CheckableHandlerHolder(I::class, strict, delegateTo)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("CheckableHandlerHolder"))
|
|
||||||
inline fun <reified I : O, O : State> StateHandlerHolder(
|
|
||||||
strict: Boolean = false,
|
|
||||||
delegateTo: StatesHandler<I, O>
|
|
||||||
) = CheckableHandlerHolder(strict, delegateTo)
|
|
||||||
|
|
||||||
inline fun <reified I : O, O: State> StatesHandler<I, O>.holder(
|
inline fun <reified I : O, O: State> StatesHandler<I, O>.holder(
|
||||||
strict: Boolean = true
|
strict: Boolean = true
|
||||||
) = CheckableHandlerHolder<I, O>(
|
) = CheckableHandlerHolder<I, O>(
|
||||||
|
@@ -68,9 +68,6 @@ open class DefaultUpdatableStatesMachine<T : State>(
|
|||||||
*/
|
*/
|
||||||
protected open suspend fun shouldReplaceJob(previous: Optional<T>, new: T): Boolean = previous.dataOrNull() != new
|
protected open suspend fun shouldReplaceJob(previous: Optional<T>, new: T): Boolean = previous.dataOrNull() != new
|
||||||
|
|
||||||
@Deprecated("Overwrite shouldReplaceJob instead")
|
|
||||||
protected open suspend fun compare(previous: Optional<T>, new: T): Boolean = shouldReplaceJob(previous, new)
|
|
||||||
|
|
||||||
override suspend fun updateChain(currentState: T, newState: T) {
|
override suspend fun updateChain(currentState: T, newState: T) {
|
||||||
statesManager.update(currentState, newState)
|
statesManager.update(currentState, newState)
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.fsm.common.managers
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.fsm.common.State
|
|
||||||
import kotlinx.coroutines.flow.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates [DefaultStatesManager] with [InMemoryDefaultStatesManagerRepo]
|
|
||||||
*
|
|
||||||
* @param onContextsConflictResolver Receive old [State], new one and the state currently placed on new [State.context]
|
|
||||||
* key. In case when this callback will returns true, the state placed on [State.context] of new will be replaced by
|
|
||||||
* new state by using [endChain] with that state
|
|
||||||
*/
|
|
||||||
@Deprecated("Use DefaultStatesManager instead", ReplaceWith("DefaultStatesManager"))
|
|
||||||
fun <T: State> InMemoryStatesManager(
|
|
||||||
onStartContextsConflictResolver: suspend (old: T, new: T) -> Boolean = { _, _ -> true },
|
|
||||||
onUpdateContextsConflictResolver: suspend (old: T, new: T, currentNew: T) -> Boolean = { _, _, _ -> true }
|
|
||||||
) = DefaultStatesManager(onStartContextsConflictResolver = onStartContextsConflictResolver, onUpdateContextsConflictResolver = onUpdateContextsConflictResolver)
|
|
@@ -1,7 +1,6 @@
|
|||||||
import dev.inmo.micro_utils.fsm.common.*
|
import dev.inmo.micro_utils.fsm.common.*
|
||||||
import dev.inmo.micro_utils.fsm.common.dsl.buildFSM
|
import dev.inmo.micro_utils.fsm.common.dsl.buildFSM
|
||||||
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
|
import dev.inmo.micro_utils.fsm.common.managers.DefaultStatesManager
|
||||||
import dev.inmo.micro_utils.fsm.common.managers.InMemoryStatesManager
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
sealed interface TrafficLightState : State {
|
sealed interface TrafficLightState : State {
|
||||||
|
@@ -21,7 +21,7 @@ if (new File(projectDir, "secret.gradle").exists()) {
|
|||||||
owner "InsanusMokrassar"
|
owner "InsanusMokrassar"
|
||||||
repo "MicroUtils"
|
repo "MicroUtils"
|
||||||
|
|
||||||
tagName "${project.version}"
|
tagName "v${project.version}"
|
||||||
releaseName "${project.version}"
|
releaseName "${project.version}"
|
||||||
targetCommitish "${project.version}"
|
targetCommitish "${project.version}"
|
||||||
|
|
||||||
|
@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
|
|||||||
# Project data
|
# Project data
|
||||||
|
|
||||||
group=dev.inmo
|
group=dev.inmo
|
||||||
version=0.11.6
|
version=0.12.1
|
||||||
android_code_version=130
|
android_code_version=140
|
||||||
|
@@ -1,30 +1,30 @@
|
|||||||
[versions]
|
[versions]
|
||||||
|
|
||||||
kt = "1.6.21"
|
kt = "1.7.0"
|
||||||
kt-serialization = "1.3.3"
|
kt-serialization = "1.4.0-RC"
|
||||||
kt-coroutines = "1.6.1"
|
kt-coroutines = "1.6.4"
|
||||||
|
|
||||||
jb-compose = "1.2.0-alpha01-dev686"
|
jb-compose = "1.2.0-alpha01-dev753"
|
||||||
jb-exposed = "0.38.2"
|
jb-exposed = "0.39.2"
|
||||||
jb-dokka = "1.6.21"
|
jb-dokka = "1.7.0"
|
||||||
|
|
||||||
klock = "2.7.0"
|
klock = "3.0.0"
|
||||||
uuid = "0.4.1"
|
uuid = "0.5.0"
|
||||||
|
|
||||||
ktor = "2.0.2"
|
ktor = "2.1.0"
|
||||||
|
|
||||||
gh-release = "2.3.7"
|
gh-release = "2.4.1"
|
||||||
|
|
||||||
android-gradle = "7.0.4"
|
android-gradle = "7.2.2"
|
||||||
dexcount = "3.1.0"
|
dexcount = "3.1.0"
|
||||||
|
|
||||||
android-coreKtx = "1.7.0"
|
android-coreKtx = "1.8.0"
|
||||||
android-recyclerView = "1.2.1"
|
android-recyclerView = "1.2.1"
|
||||||
android-appCompat = "1.4.1"
|
android-appCompat = "1.4.2"
|
||||||
android-espresso = "3.3.0"
|
android-espresso = "3.4.0"
|
||||||
android-test = "1.1.2"
|
android-test = "1.1.3"
|
||||||
|
|
||||||
android-props-minSdk = "19"
|
android-props-minSdk = "21"
|
||||||
android-props-compileSdk = "32"
|
android-props-compileSdk = "32"
|
||||||
android-props-buildTools = "32.0.0"
|
android-props-buildTools = "32.0.0"
|
||||||
|
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -19,6 +19,7 @@ import kotlinx.serialization.DeserializationStrategy
|
|||||||
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
||||||
* connection. Must return true in case if must be reconnected. By default always reconnecting
|
* connection. Must return true in case if must be reconnected. By default always reconnecting
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
inline fun <T> HttpClient.createStandardWebsocketFlow(
|
inline fun <T> HttpClient.createStandardWebsocketFlow(
|
||||||
url: String,
|
url: String,
|
||||||
crossinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
|
crossinline checkReconnection: suspend (Throwable?) -> Boolean = { true },
|
||||||
@@ -65,6 +66,7 @@ inline fun <T> HttpClient.createStandardWebsocketFlow(
|
|||||||
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
* @param checkReconnection This lambda will be called when it is required to reconnect to websocket to establish
|
||||||
* connection. Must return true in case if must be reconnected. By default always reconnecting
|
* connection. Must return true in case if must be reconnected. By default always reconnecting
|
||||||
*/
|
*/
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
inline fun <T> HttpClient.createStandardWebsocketFlow(
|
inline fun <T> HttpClient.createStandardWebsocketFlow(
|
||||||
url: String,
|
url: String,
|
||||||
deserializer: DeserializationStrategy<T>,
|
deserializer: DeserializationStrategy<T>,
|
||||||
|
@@ -12,8 +12,7 @@ import io.ktor.http.*
|
|||||||
import io.ktor.utils.io.core.ByteReadPacket
|
import io.ktor.utils.io.core.ByteReadPacket
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.*
|
||||||
|
|
||||||
typealias BodyPair<T> = Pair<SerializationStrategy<T>, T>
|
@Deprecated("This class will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
|
|
||||||
class UnifiedRequester(
|
class UnifiedRequester(
|
||||||
val client: HttpClient = HttpClient(),
|
val client: HttpClient = HttpClient(),
|
||||||
val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
||||||
@@ -33,7 +32,7 @@ class UnifiedRequester(
|
|||||||
|
|
||||||
suspend fun <BodyType, ResultType> unipost(
|
suspend fun <BodyType, ResultType> unipost(
|
||||||
url: String,
|
url: String,
|
||||||
bodyInfo: BodyPair<BodyType>,
|
bodyInfo: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>
|
resultDeserializer: DeserializationStrategy<ResultType>
|
||||||
) = client.unipost(url, bodyInfo, resultDeserializer, serialFormat)
|
) = client.unipost(url, bodyInfo, resultDeserializer, serialFormat)
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ class UnifiedRequester(
|
|||||||
url: String,
|
url: String,
|
||||||
filename: String,
|
filename: String,
|
||||||
inputProvider: InputProvider,
|
inputProvider: InputProvider,
|
||||||
otherData: BodyPair<BodyType>,
|
otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
mimetype: String = "*/*",
|
mimetype: String = "*/*",
|
||||||
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
||||||
@@ -75,7 +74,7 @@ class UnifiedRequester(
|
|||||||
suspend fun <BodyType, ResultType> unimultipart(
|
suspend fun <BodyType, ResultType> unimultipart(
|
||||||
url: String,
|
url: String,
|
||||||
mppFile: MPPFile,
|
mppFile: MPPFile,
|
||||||
otherData: BodyPair<BodyType>,
|
otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
mimetype: String = "*/*",
|
mimetype: String = "*/*",
|
||||||
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
||||||
@@ -99,8 +98,10 @@ class UnifiedRequester(
|
|||||||
) = createStandardWebsocketFlow(url, { true }, deserializer, requestBuilder)
|
) = createStandardWebsocketFlow(url, { true }, deserializer, requestBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This property will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
val defaultRequester = UnifiedRequester()
|
val defaultRequester = UnifiedRequester()
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <ResultType> HttpClient.uniget(
|
suspend fun <ResultType> HttpClient.uniget(
|
||||||
url: String,
|
url: String,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
@@ -110,6 +111,7 @@ suspend fun <ResultType> HttpClient.uniget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
fun <T> SerializationStrategy<T>.encodeUrlQueryValue(
|
fun <T> SerializationStrategy<T>.encodeUrlQueryValue(
|
||||||
value: T,
|
value: T,
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
||||||
@@ -118,9 +120,10 @@ fun <T> SerializationStrategy<T>.encodeUrlQueryValue(
|
|||||||
value
|
value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <BodyType, ResultType> HttpClient.unipost(
|
suspend fun <BodyType, ResultType> HttpClient.unipost(
|
||||||
url: String,
|
url: String,
|
||||||
bodyInfo: BodyPair<BodyType>,
|
bodyInfo: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
||||||
) = post(url) {
|
) = post(url) {
|
||||||
@@ -131,6 +134,7 @@ suspend fun <BodyType, ResultType> HttpClient.unipost(
|
|||||||
serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>())
|
serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <ResultType> HttpClient.unimultipart(
|
suspend fun <ResultType> HttpClient.unimultipart(
|
||||||
url: String,
|
url: String,
|
||||||
filename: String,
|
filename: String,
|
||||||
@@ -159,10 +163,11 @@ suspend fun <ResultType> HttpClient.unimultipart(
|
|||||||
requestBuilder()
|
requestBuilder()
|
||||||
}.let { serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>()) }
|
}.let { serialFormat.decodeDefault(resultDeserializer, it.body<StandardKtorSerialInputData>()) }
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
|
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
|
||||||
url: String,
|
url: String,
|
||||||
filename: String,
|
filename: String,
|
||||||
otherData: BodyPair<BodyType>,
|
otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
inputProvider: InputProvider,
|
inputProvider: InputProvider,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
mimetype: String = "*/*",
|
mimetype: String = "*/*",
|
||||||
@@ -196,6 +201,7 @@ suspend fun <BodyType, ResultType> HttpClient.unimultipart(
|
|||||||
serialFormat
|
serialFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <ResultType> HttpClient.unimultipart(
|
suspend fun <ResultType> HttpClient.unimultipart(
|
||||||
url: String,
|
url: String,
|
||||||
mppFile: MPPFile,
|
mppFile: MPPFile,
|
||||||
@@ -217,10 +223,11 @@ suspend fun <ResultType> HttpClient.unimultipart(
|
|||||||
serialFormat
|
serialFormat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
|
suspend fun <BodyType, ResultType> HttpClient.unimultipart(
|
||||||
url: String,
|
url: String,
|
||||||
mppFile: MPPFile,
|
mppFile: MPPFile,
|
||||||
otherData: BodyPair<BodyType>,
|
otherData: Pair<SerializationStrategy<BodyType>, BodyType>,
|
||||||
resultDeserializer: DeserializationStrategy<ResultType>,
|
resultDeserializer: DeserializationStrategy<ResultType>,
|
||||||
mimetype: String = "*/*",
|
mimetype: String = "*/*",
|
||||||
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
additionalParametersBuilder: FormBuilder.() -> Unit = {},
|
||||||
|
@@ -33,6 +33,7 @@ fun <T> Route.includeWebsocketHandling(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon")
|
||||||
fun <T> Route.includeWebsocketHandling(
|
fun <T> Route.includeWebsocketHandling(
|
||||||
suburl: String,
|
suburl: String,
|
||||||
flow: Flow<T>,
|
flow: Flow<T>,
|
||||||
|
@@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.serialization.DeserializationStrategy
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
import kotlinx.serialization.SerializationStrategy
|
import kotlinx.serialization.SerializationStrategy
|
||||||
|
|
||||||
|
@Deprecated("This class method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
class UnifiedRouter(
|
class UnifiedRouter(
|
||||||
val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat,
|
val serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat,
|
||||||
val serialFormatContentType: ContentType = standardKtorSerialFormatContentType
|
val serialFormatContentType: ContentType = standardKtorSerialFormatContentType
|
||||||
@@ -97,6 +98,7 @@ class UnifiedRouter(
|
|||||||
|
|
||||||
val defaultUnifiedRouter = UnifiedRouter()
|
val defaultUnifiedRouter = UnifiedRouter()
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <T> ApplicationCall.unianswer(
|
suspend fun <T> ApplicationCall.unianswer(
|
||||||
answerSerializer: SerializationStrategy<T>,
|
answerSerializer: SerializationStrategy<T>,
|
||||||
answer: T
|
answer: T
|
||||||
@@ -107,6 +109,7 @@ suspend fun <T> ApplicationCall.unianswer(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <T> ApplicationCall.uniload(
|
suspend fun <T> ApplicationCall.uniload(
|
||||||
deserializer: DeserializationStrategy<T>
|
deserializer: DeserializationStrategy<T>
|
||||||
) = safely {
|
) = safely {
|
||||||
@@ -119,6 +122,7 @@ suspend fun <T> ApplicationCall.uniload(
|
|||||||
suspend fun ApplicationCall.uniloadMultipart(
|
suspend fun ApplicationCall.uniloadMultipart(
|
||||||
onFormItem: (PartData.FormItem) -> Unit = {},
|
onFormItem: (PartData.FormItem) -> Unit = {},
|
||||||
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
||||||
|
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
|
||||||
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
|
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
|
||||||
) = safely {
|
) = safely {
|
||||||
val multipartData = receiveMultipart()
|
val multipartData = receiveMultipart()
|
||||||
@@ -135,16 +139,19 @@ suspend fun ApplicationCall.uniloadMultipart(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PartData.BinaryItem -> onBinaryContent(it)
|
is PartData.BinaryItem -> onBinaryContent(it)
|
||||||
|
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resultInput ?: error("Bytes has not been received")
|
resultInput ?: error("Bytes has not been received")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <T> ApplicationCall.uniloadMultipart(
|
suspend fun <T> ApplicationCall.uniloadMultipart(
|
||||||
deserializer: DeserializationStrategy<T>,
|
deserializer: DeserializationStrategy<T>,
|
||||||
onFormItem: (PartData.FormItem) -> Unit = {},
|
onFormItem: (PartData.FormItem) -> Unit = {},
|
||||||
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
||||||
|
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
|
||||||
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
|
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
|
||||||
): Pair<Input, T> {
|
): Pair<Input, T> {
|
||||||
var data: Optional<T>? = null
|
var data: Optional<T>? = null
|
||||||
@@ -157,6 +164,7 @@ suspend fun <T> ApplicationCall.uniloadMultipart(
|
|||||||
onCustomFileItem(it)
|
onCustomFileItem(it)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onBinaryChannelItem,
|
||||||
onBinaryContent
|
onBinaryContent
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -164,10 +172,12 @@ suspend fun <T> ApplicationCall.uniloadMultipart(
|
|||||||
return resultInput to (completeData.dataOrNull().let { it as T })
|
return resultInput to (completeData.dataOrNull().let { it as T })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <T> ApplicationCall.uniloadMultipartFile(
|
suspend fun <T> ApplicationCall.uniloadMultipartFile(
|
||||||
deserializer: DeserializationStrategy<T>,
|
deserializer: DeserializationStrategy<T>,
|
||||||
onFormItem: (PartData.FormItem) -> Unit = {},
|
onFormItem: (PartData.FormItem) -> Unit = {},
|
||||||
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
||||||
|
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
|
||||||
onBinaryContent: (PartData.BinaryItem) -> Unit = {},
|
onBinaryContent: (PartData.BinaryItem) -> Unit = {},
|
||||||
) = safely {
|
) = safely {
|
||||||
val multipartData = receiveMultipart()
|
val multipartData = receiveMultipart()
|
||||||
@@ -204,6 +214,7 @@ suspend fun <T> ApplicationCall.uniloadMultipartFile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PartData.BinaryItem -> onBinaryContent(it)
|
is PartData.BinaryItem -> onBinaryContent(it)
|
||||||
|
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +225,7 @@ suspend fun <T> ApplicationCall.uniloadMultipartFile(
|
|||||||
suspend fun ApplicationCall.uniloadMultipartFile(
|
suspend fun ApplicationCall.uniloadMultipartFile(
|
||||||
onFormItem: (PartData.FormItem) -> Unit = {},
|
onFormItem: (PartData.FormItem) -> Unit = {},
|
||||||
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
onCustomFileItem: (PartData.FileItem) -> Unit = {},
|
||||||
|
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
|
||||||
onBinaryContent: (PartData.BinaryItem) -> Unit = {},
|
onBinaryContent: (PartData.BinaryItem) -> Unit = {},
|
||||||
) = safely {
|
) = safely {
|
||||||
val multipartData = receiveMultipart()
|
val multipartData = receiveMultipart()
|
||||||
@@ -247,6 +259,7 @@ suspend fun ApplicationCall.uniloadMultipartFile(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is PartData.BinaryItem -> onBinaryContent(it)
|
is PartData.BinaryItem -> onBinaryContent(it)
|
||||||
|
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +286,7 @@ suspend fun ApplicationCall.getQueryParameterOrSendError(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
fun <T> ApplicationCall.decodeUrlQueryValue(
|
fun <T> ApplicationCall.decodeUrlQueryValue(
|
||||||
field: String,
|
field: String,
|
||||||
deserializer: DeserializationStrategy<T>
|
deserializer: DeserializationStrategy<T>
|
||||||
@@ -283,6 +297,7 @@ fun <T> ApplicationCall.decodeUrlQueryValue(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("This method will be removed soon. It is now recommended to use built-in ktor features instead")
|
||||||
suspend fun <T> ApplicationCall.decodeUrlQueryValueOrSendError(
|
suspend fun <T> ApplicationCall.decodeUrlQueryValueOrSendError(
|
||||||
field: String,
|
field: String,
|
||||||
deserializer: DeserializationStrategy<T>
|
deserializer: DeserializationStrategy<T>
|
||||||
|
@@ -1,23 +1,60 @@
|
|||||||
package dev.inmo.micro_utils.pagination
|
package dev.inmo.micro_utils.pagination
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.*
|
||||||
|
import kotlin.math.ceil
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param page Current page number
|
||||||
|
* @param size Current page size. It can be greater than size of [results]
|
||||||
|
* @param results Result objects
|
||||||
|
* @param objectsNumber Count of all objects across all pages
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PaginationResult<T>(
|
data class PaginationResult<T>(
|
||||||
override val page: Int,
|
override val page: Int,
|
||||||
val pagesNumber: Int,
|
override val size: Int,
|
||||||
val results: List<T>,
|
val results: List<T>,
|
||||||
override val size: Int
|
val objectsNumber: Long
|
||||||
) : Pagination
|
) : Pagination {
|
||||||
|
/**
|
||||||
|
* Amount of pages for current pagination
|
||||||
|
*/
|
||||||
|
@EncodeDefault
|
||||||
|
val pagesNumber: Int = ceil(objectsNumber / size.toFloat()).toInt()
|
||||||
|
|
||||||
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0)
|
constructor(
|
||||||
|
page: Int,
|
||||||
|
results: List<T>,
|
||||||
|
pagesNumber: Int,
|
||||||
|
size: Int
|
||||||
|
) : this(
|
||||||
|
page,
|
||||||
|
size,
|
||||||
|
results,
|
||||||
|
(pagesNumber * size).toLong()
|
||||||
|
)
|
||||||
|
@Deprecated("Replace with The other order of incoming parameters or objectsCount parameter")
|
||||||
|
constructor(
|
||||||
|
page: Int,
|
||||||
|
pagesNumber: Int,
|
||||||
|
results: List<T>,
|
||||||
|
size: Int
|
||||||
|
) : this(
|
||||||
|
page,
|
||||||
|
results,
|
||||||
|
pagesNumber,
|
||||||
|
size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> emptyPaginationResult() = PaginationResult<T>(0, 0, emptyList(), 0L)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return New [PaginationResult] with [data] without checking of data sizes equality
|
* @return New [PaginationResult] with [data] without checking of data sizes equality
|
||||||
*/
|
*/
|
||||||
fun <I, O> PaginationResult<I>.changeResultsUnchecked(
|
fun <I, O> PaginationResult<I>.changeResultsUnchecked(
|
||||||
data: List<O>
|
data: List<O>
|
||||||
): PaginationResult<O> = PaginationResult(page, pagesNumber, data, size)
|
): PaginationResult<O> = PaginationResult(page, size, data, objectsNumber)
|
||||||
/**
|
/**
|
||||||
* @return New [PaginationResult] with [data] <b>with</b> checking of data sizes equality
|
* @return New [PaginationResult] with [data] <b>with</b> checking of data sizes equality
|
||||||
*/
|
*/
|
||||||
@@ -33,12 +70,9 @@ fun <T> List<T>.createPaginationResult(
|
|||||||
commonObjectsNumber: Long
|
commonObjectsNumber: Long
|
||||||
) = PaginationResult(
|
) = PaginationResult(
|
||||||
pagination.page,
|
pagination.page,
|
||||||
calculatePagesNumber(
|
pagination.size,
|
||||||
commonObjectsNumber,
|
|
||||||
pagination.size
|
|
||||||
),
|
|
||||||
this,
|
this,
|
||||||
pagination.size
|
commonObjectsNumber
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <T> List<T>.createPaginationResult(
|
fun <T> List<T>.createPaginationResult(
|
||||||
@@ -46,12 +80,9 @@ fun <T> List<T>.createPaginationResult(
|
|||||||
commonObjectsNumber: Long
|
commonObjectsNumber: Long
|
||||||
) = PaginationResult(
|
) = PaginationResult(
|
||||||
calculatePage(firstIndex, size),
|
calculatePage(firstIndex, size),
|
||||||
calculatePagesNumber(
|
size,
|
||||||
commonObjectsNumber,
|
|
||||||
size
|
|
||||||
),
|
|
||||||
this,
|
this,
|
||||||
size
|
commonObjectsNumber
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <T> Pair<Long, List<T>>.createPaginationResult(
|
fun <T> Pair<Long, List<T>>.createPaginationResult(
|
||||||
|
@@ -26,6 +26,10 @@ inline fun Pagination.nextPage() =
|
|||||||
size
|
size
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param page Current page number
|
||||||
|
* @param size Current page size
|
||||||
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
data class SimplePagination(
|
data class SimplePagination(
|
||||||
override val page: Int,
|
override val page: Int,
|
||||||
|
2
repos/cache/build.gradle
vendored
2
repos/cache/build.gradle
vendored
@@ -15,4 +15,4 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
package dev.inmo.micro_utils.repos.cache
|
package dev.inmo.micro_utils.repos.cache
|
||||||
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
|
|
||||||
open class ReadCRUDCacheRepo<ObjectType, IdType>(
|
open class ReadCRUDCacheRepo<ObjectType, IdType>(
|
||||||
protected val parentRepo: ReadCRUDRepo<ObjectType, IdType>,
|
protected open val parentRepo: ReadCRUDRepo<ObjectType, IdType>,
|
||||||
protected val kvCache: KVCache<IdType, ObjectType>,
|
protected open val kvCache: KVCache<IdType, ObjectType>,
|
||||||
protected val idGetter: (ObjectType) -> IdType
|
protected open val idGetter: (ObjectType) -> IdType
|
||||||
) : ReadCRUDRepo<ObjectType, IdType> by parentRepo {
|
) : ReadCRUDRepo<ObjectType, IdType> by parentRepo, CacheRepo {
|
||||||
override suspend fun getById(id: IdType): ObjectType? = kvCache.get(id) ?: (parentRepo.getById(id) ?.also {
|
override suspend fun getById(id: IdType): ObjectType? = kvCache.get(id) ?: (parentRepo.getById(id) ?.also {
|
||||||
kvCache.set(id, it)
|
kvCache.set(id, it)
|
||||||
})
|
})
|
||||||
@@ -18,8 +18,63 @@ open class ReadCRUDCacheRepo<ObjectType, IdType>(
|
|||||||
override suspend fun contains(id: IdType): Boolean = kvCache.contains(id) || parentRepo.contains(id)
|
override suspend fun contains(id: IdType): Boolean = kvCache.contains(id) || parentRepo.contains(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <ObjectType, IdType> ReadCRUDRepo<ObjectType, IdType>.cached(
|
||||||
|
kvCache: KVCache<IdType, ObjectType>,
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) = ReadCRUDCacheRepo(this, kvCache, idGetter)
|
||||||
|
|
||||||
|
open class WriteCRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
||||||
|
protected open val parentRepo: WriteCRUDRepo<ObjectType, IdType, InputValueType>,
|
||||||
|
protected open val kvCache: KVCache<IdType, ObjectType>,
|
||||||
|
protected open val scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
|
protected open val idGetter: (ObjectType) -> IdType
|
||||||
|
) : WriteCRUDRepo<ObjectType, IdType, InputValueType>, CacheRepo {
|
||||||
|
override val newObjectsFlow: Flow<ObjectType> by parentRepo::newObjectsFlow
|
||||||
|
override val updatedObjectsFlow: Flow<ObjectType> by parentRepo::updatedObjectsFlow
|
||||||
|
override val deletedObjectsIdsFlow: Flow<IdType> by parentRepo::deletedObjectsIdsFlow
|
||||||
|
|
||||||
|
val deletedObjectsFlowJob = parentRepo.deletedObjectsIdsFlow.onEach {
|
||||||
|
kvCache.unset(it)
|
||||||
|
}.launchIn(scope)
|
||||||
|
|
||||||
|
override suspend fun deleteById(ids: List<IdType>) = parentRepo.deleteById(ids)
|
||||||
|
|
||||||
|
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValueType>>): List<ObjectType> {
|
||||||
|
val updated = parentRepo.update(values)
|
||||||
|
|
||||||
|
kvCache.unset(values.map { it.id })
|
||||||
|
kvCache.set(updated.associateBy { idGetter(it) })
|
||||||
|
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun update(id: IdType, value: InputValueType): ObjectType? {
|
||||||
|
return parentRepo.update(id, value) ?.also {
|
||||||
|
kvCache.unset(id)
|
||||||
|
kvCache.set(idGetter(it), it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun create(values: List<InputValueType>): List<ObjectType> {
|
||||||
|
val created = parentRepo.create(values)
|
||||||
|
|
||||||
|
kvCache.set(
|
||||||
|
created.associateBy { idGetter(it) }
|
||||||
|
)
|
||||||
|
|
||||||
|
return created
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <ObjectType, IdType, InputType> WriteCRUDRepo<ObjectType, IdType, InputType>.caching(
|
||||||
|
kvCache: KVCache<IdType, ObjectType>,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) = WriteCRUDCacheRepo(this, kvCache, scope, idGetter)
|
||||||
|
|
||||||
|
|
||||||
open class CRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
open class CRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
||||||
parentRepo: CRUDRepo<ObjectType, IdType, InputValueType>,
|
override val parentRepo: CRUDRepo<ObjectType, IdType, InputValueType>,
|
||||||
kvCache: KVCache<IdType, ObjectType>,
|
kvCache: KVCache<IdType, ObjectType>,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
idGetter: (ObjectType) -> IdType
|
idGetter: (ObjectType) -> IdType
|
||||||
@@ -27,8 +82,17 @@ open class CRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
|||||||
parentRepo,
|
parentRepo,
|
||||||
kvCache,
|
kvCache,
|
||||||
idGetter
|
idGetter
|
||||||
), CRUDRepo<ObjectType, IdType, InputValueType>, WriteCRUDRepo<ObjectType, IdType, InputValueType> by parentRepo {
|
),
|
||||||
protected val onNewJob = parentRepo.newObjectsFlow.onEach { kvCache.set(idGetter(it), it) }.launchIn(scope)
|
WriteCRUDRepo<ObjectType, IdType, InputValueType> by WriteCRUDCacheRepo(
|
||||||
protected val onUpdatedJob = parentRepo.updatedObjectsFlow.onEach { kvCache.set(idGetter(it), it) }.launchIn(scope)
|
parentRepo,
|
||||||
protected val onRemoveJob = parentRepo.deletedObjectsIdsFlow.onEach { kvCache.unset(it) }.launchIn(scope)
|
kvCache,
|
||||||
}
|
scope,
|
||||||
|
idGetter
|
||||||
|
),
|
||||||
|
CRUDRepo<ObjectType, IdType, InputValueType>
|
||||||
|
|
||||||
|
fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached(
|
||||||
|
kvCache: KVCache<IdType, ObjectType>,
|
||||||
|
scope: CoroutineScope,
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) = CRUDCacheRepo(this, kvCache, scope, idGetter)
|
||||||
|
3
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt
vendored
Normal file
3
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/CacheRepo.kt
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache
|
||||||
|
|
||||||
|
interface CacheRepo
|
@@ -1,23 +1,35 @@
|
|||||||
package dev.inmo.micro_utils.repos.cache
|
package dev.inmo.micro_utils.repos.cache
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
open class ReadKeyValueCacheRepo<Key,Value>(
|
open class ReadKeyValueCacheRepo<Key,Value>(
|
||||||
protected val parentRepo: ReadKeyValueRepo<Key, Value>,
|
protected open val parentRepo: ReadKeyValueRepo<Key, Value>,
|
||||||
protected val kvCache: KVCache<Key, Value>,
|
protected open val kvCache: KVCache<Key, Value>,
|
||||||
) : ReadKeyValueRepo<Key,Value> by parentRepo {
|
) : ReadKeyValueRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
override suspend fun get(k: Key): Value? = kvCache.get(k) ?: parentRepo.get(k) ?.also { kvCache.set(k, it) }
|
override suspend fun get(k: Key): Value? = kvCache.get(k) ?: parentRepo.get(k) ?.also { kvCache.set(k, it) }
|
||||||
override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key)
|
override suspend fun contains(key: Key): Boolean = kvCache.contains(key) || parentRepo.contains(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
|
||||||
|
kvCache: KVCache<Key, Value>
|
||||||
|
) = ReadKeyValueCacheRepo(this, kvCache)
|
||||||
|
|
||||||
open class KeyValueCacheRepo<Key,Value>(
|
open class KeyValueCacheRepo<Key,Value>(
|
||||||
parentRepo: KeyValueRepo<Key, Value>,
|
parentRepo: KeyValueRepo<Key, Value>,
|
||||||
kvCache: KVCache<Key, Value>,
|
kvCache: KVCache<Key, Value>,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
) : ReadKeyValueCacheRepo<Key,Value>(parentRepo, kvCache), KeyValueRepo<Key,Value>, WriteKeyValueRepo<Key, Value> by parentRepo {
|
) : ReadKeyValueCacheRepo<Key,Value>(parentRepo, kvCache), KeyValueRepo<Key,Value>, WriteKeyValueRepo<Key, Value> by parentRepo, CacheRepo {
|
||||||
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope)
|
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope)
|
||||||
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope)
|
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> KeyValueRepo<Key, Value>.cached(
|
||||||
|
kvCache: KVCache<Key, Value>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = KeyValueCacheRepo(this, kvCache, scope)
|
||||||
|
@@ -5,14 +5,15 @@ import dev.inmo.micro_utils.pagination.PaginationResult
|
|||||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||||
import dev.inmo.micro_utils.pagination.utils.reverse
|
import dev.inmo.micro_utils.pagination.utils.reverse
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
open class ReadKeyValuesCacheRepo<Key,Value>(
|
open class ReadKeyValuesCacheRepo<Key,Value>(
|
||||||
protected val parentRepo: ReadKeyValuesRepo<Key, Value>,
|
protected open val parentRepo: ReadKeyValuesRepo<Key, Value>,
|
||||||
protected val kvCache: KVCache<Key, List<Value>>
|
protected open val kvCache: KVCache<Key, List<Value>>
|
||||||
) : ReadKeyValuesRepo<Key,Value> by parentRepo {
|
) : ReadKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
||||||
return kvCache.get(k) ?.paginate(
|
return kvCache.get(k) ?.paginate(
|
||||||
pagination.let { if (reversed) it.reverse(count(k)) else it }
|
pagination.let { if (reversed) it.reverse(count(k)) else it }
|
||||||
@@ -29,12 +30,21 @@ open class ReadKeyValuesCacheRepo<Key,Value>(
|
|||||||
override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
|
override suspend fun contains(k: Key): Boolean = kvCache.contains(k) || parentRepo.contains(k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
|
||||||
|
kvCache: KVCache<Key, List<Value>>
|
||||||
|
) = ReadKeyValuesCacheRepo(this, kvCache)
|
||||||
|
|
||||||
open class KeyValuesCacheRepo<Key,Value>(
|
open class KeyValuesCacheRepo<Key,Value>(
|
||||||
parentRepo: KeyValuesRepo<Key, Value>,
|
parentRepo: KeyValuesRepo<Key, Value>,
|
||||||
kvCache: KVCache<Key, List<Value>>,
|
kvCache: KVCache<Key, List<Value>>,
|
||||||
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo {
|
) : ReadKeyValuesCacheRepo<Key,Value>(parentRepo, kvCache), KeyValuesRepo<Key,Value>, WriteKeyValuesRepo<Key,Value> by parentRepo, CacheRepo {
|
||||||
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.plus(it.second) ?: listOf(it.second)) }.launchIn(scope)
|
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.plus(it.second) ?: listOf(it.second)) }.launchIn(scope)
|
||||||
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.minus(it.second) ?: return@onEach) }.launchIn(scope)
|
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.set(it.first, kvCache.get(it.first) ?.minus(it.second) ?: return@onEach) }.launchIn(scope)
|
||||||
protected val onDataClearedJob = parentRepo.onDataCleared.onEach { kvCache.unset(it) }.launchIn(scope)
|
protected val onDataClearedJob = parentRepo.onDataCleared.onEach { kvCache.unset(it) }.launchIn(scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> KeyValuesRepo<Key, Value>.cached(
|
||||||
|
kvCache: KVCache<Key, List<Value>>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = KeyValuesCacheRepo(this, kvCache, scope)
|
||||||
|
8
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt
vendored
Normal file
8
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/FullKVCache.kt
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.cache
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface declares that current type of [KVCache] will contains all the data all the time of its life
|
||||||
|
*/
|
||||||
|
interface FullKVCache<K, V> : KVCache<K, V> {
|
||||||
|
companion object
|
||||||
|
}
|
7
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt
vendored
Normal file
7
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/KVCache.kt
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.cache
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
|
||||||
|
interface KVCache<K, V> : KeyValueRepo<K, V> {
|
||||||
|
companion object
|
||||||
|
}
|
28
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt
vendored
Normal file
28
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/cache/SimpleFullKVCache.kt
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.cache
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
|
import dev.inmo.micro_utils.repos.MapKeyValueRepo
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
|
open class SimpleFullKVCache<K, V>(
|
||||||
|
private val kvParent: KeyValueRepo<K, V> = MapKeyValueRepo<K, V>()
|
||||||
|
) : FullKVCache<K, V>, KeyValueRepo<K, V> by kvParent {
|
||||||
|
protected val syncMutex = Mutex()
|
||||||
|
|
||||||
|
override suspend fun set(toSet: Map<K, V>) {
|
||||||
|
syncMutex.withLock {
|
||||||
|
kvParent.set(toSet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun unset(toUnset: List<K>) {
|
||||||
|
syncMutex.withLock {
|
||||||
|
kvParent.unset(toUnset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <K, V> FullKVCache(
|
||||||
|
kvParent: KeyValueRepo<K, V> = MapKeyValueRepo<K, V>()
|
||||||
|
) = SimpleFullKVCache<K, V>(kvParent)
|
@@ -1,36 +1,32 @@
|
|||||||
package dev.inmo.micro_utils.repos.cache
|
package dev.inmo.micro_utils.repos.cache.cache
|
||||||
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
|
||||||
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
import dev.inmo.micro_utils.pagination.utils.getAllWithNextPaging
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
interface KVCache<K, V> : KeyValueRepo<K, V>
|
|
||||||
|
|
||||||
open class SimpleKVCache<K, V>(
|
open class SimpleKVCache<K, V>(
|
||||||
protected val cachedValuesCount: Int,
|
protected val cachedValuesCount: Int,
|
||||||
private val kvParent: KeyValueRepo<K, V> = MapKeyValueRepo<K, V>()
|
private val kvParent: KeyValueRepo<K, V> = MapKeyValueRepo<K, V>()
|
||||||
) : KVCache<K, V>, KeyValueRepo<K, V> by kvParent {
|
) : KVCache<K, V>, KeyValueRepo<K, V> by kvParent {
|
||||||
protected open val cacheStack = ArrayList<K>(cachedValuesCount)
|
protected open val cacheQueue = ArrayDeque<K>(cachedValuesCount)
|
||||||
protected val syncMutex = Mutex()
|
protected val syncMutex = Mutex()
|
||||||
|
|
||||||
protected suspend fun makeUnset(toUnset: List<K>) {
|
protected suspend fun makeUnset(toUnset: List<K>) {
|
||||||
cacheStack.removeAll(toUnset)
|
cacheQueue.removeAll(toUnset)
|
||||||
kvParent.unset(toUnset)
|
kvParent.unset(toUnset)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun set(toSet: Map<K, V>) {
|
override suspend fun set(toSet: Map<K, V>) {
|
||||||
syncMutex.withLock {
|
syncMutex.withLock {
|
||||||
if (toSet.size > cachedValuesCount) {
|
for ((k, v) in toSet) {
|
||||||
cacheStack.clear()
|
if (cacheQueue.size >= cachedValuesCount) {
|
||||||
|
cacheQueue.removeFirstOrNull() ?.let {
|
||||||
kvParent.unset(getAllWithNextPaging { kvParent.keys(it) })
|
kvParent.unset(it)
|
||||||
val keysToInclude = toSet.keys.drop(toSet.size - cachedValuesCount)
|
}
|
||||||
|
}
|
||||||
cacheStack.addAll(keysToInclude)
|
cacheQueue.addLast(k)
|
||||||
kvParent.set(keysToInclude.associateWith { toSet.getValue(it) })
|
kvParent.set(k, v)
|
||||||
} else {
|
|
||||||
makeUnset(cacheStack.take(toSet.size))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,3 +35,8 @@ open class SimpleKVCache<K, V>(
|
|||||||
syncMutex.withLock { makeUnset(toUnset) }
|
syncMutex.withLock { makeUnset(toUnset) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <K, V> KVCache(
|
||||||
|
cachedValuesCount: Int,
|
||||||
|
kvParent: KeyValueRepo<K, V> = MapKeyValueRepo<K, V>()
|
||||||
|
) = SimpleKVCache<K, V>(cachedValuesCount, kvParent)
|
95
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt
vendored
Normal file
95
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCRUDCacheRepo.kt
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.full
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.*
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.pagination.utils.doForAllWithNextPaging
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.KVCache
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
||||||
|
open class FullReadCRUDCacheRepo<ObjectType, IdType>(
|
||||||
|
protected open val parentRepo: ReadCRUDRepo<ObjectType, IdType>,
|
||||||
|
protected open val kvCache: FullKVCache<IdType, ObjectType>,
|
||||||
|
protected open val idGetter: (ObjectType) -> IdType
|
||||||
|
) : ReadCRUDRepo<ObjectType, IdType>, FullCacheRepo {
|
||||||
|
protected inline fun <T> doOrTakeAndActualize(
|
||||||
|
action: FullKVCache<IdType, ObjectType>.() -> Optional<T>,
|
||||||
|
actionElse: ReadCRUDRepo<ObjectType, IdType>.() -> T,
|
||||||
|
actualize: FullKVCache<IdType, ObjectType>.(T) -> Unit
|
||||||
|
): T {
|
||||||
|
kvCache.action().onPresented {
|
||||||
|
return it
|
||||||
|
}.onAbsent {
|
||||||
|
return parentRepo.actionElse().also {
|
||||||
|
kvCache.actualize(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("The result should be returned above")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun actualizeAll() {
|
||||||
|
kvCache.clear()
|
||||||
|
doForAllWithNextPaging {
|
||||||
|
parentRepo.getByPagination(it).also {
|
||||||
|
kvCache.set(it.results.associateBy { idGetter(it) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = doOrTakeAndActualize(
|
||||||
|
{ values(pagination).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull },
|
||||||
|
{ getByPagination(pagination) },
|
||||||
|
{ if (it.results.isNotEmpty()) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(): Long = doOrTakeAndActualize(
|
||||||
|
{ count().takeIf { it != 0L }.optionalOrAbsentIfNull },
|
||||||
|
{ count() },
|
||||||
|
{ if (it != 0L) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(id: IdType): Boolean = doOrTakeAndActualize(
|
||||||
|
{ contains(id).takeIf { it }.optionalOrAbsentIfNull },
|
||||||
|
{ contains(id) },
|
||||||
|
{ if (it) parentRepo.getById(id) ?.let { set(id, it) } }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun getById(id: IdType): ObjectType? = doOrTakeAndActualize(
|
||||||
|
{ get(id) ?.optional ?: Optional.absent() },
|
||||||
|
{ getById(id) },
|
||||||
|
{ it ?.let { set(idGetter(it), it) } }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <ObjectType, IdType> ReadCRUDRepo<ObjectType, IdType>.cached(
|
||||||
|
kvCache: FullKVCache<IdType, ObjectType>,
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) = FullReadCRUDCacheRepo(this, kvCache, idGetter)
|
||||||
|
|
||||||
|
open class FullCRUDCacheRepo<ObjectType, IdType, InputValueType>(
|
||||||
|
override val parentRepo: CRUDRepo<ObjectType, IdType, InputValueType>,
|
||||||
|
kvCache: FullKVCache<IdType, ObjectType>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) : FullReadCRUDCacheRepo<ObjectType, IdType>(
|
||||||
|
parentRepo,
|
||||||
|
kvCache,
|
||||||
|
idGetter
|
||||||
|
),
|
||||||
|
WriteCRUDRepo<ObjectType, IdType, InputValueType> by WriteCRUDCacheRepo(
|
||||||
|
parentRepo,
|
||||||
|
kvCache,
|
||||||
|
scope,
|
||||||
|
idGetter
|
||||||
|
),
|
||||||
|
CRUDRepo<ObjectType, IdType, InputValueType>
|
||||||
|
|
||||||
|
fun <ObjectType, IdType, InputType> CRUDRepo<ObjectType, IdType, InputType>.cached(
|
||||||
|
kvCache: FullKVCache<IdType, ObjectType>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default),
|
||||||
|
idGetter: (ObjectType) -> IdType
|
||||||
|
) = FullCRUDCacheRepo(this, kvCache, scope, idGetter)
|
5
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCacheRepo.kt
vendored
Normal file
5
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullCacheRepo.kt
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.full
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.repos.cache.CacheRepo
|
||||||
|
|
||||||
|
interface FullCacheRepo : CacheRepo
|
104
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt
vendored
Normal file
104
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValueCacheRepo.kt
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.full
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.*
|
||||||
|
import dev.inmo.micro_utils.pagination.Pagination
|
||||||
|
import dev.inmo.micro_utils.pagination.PaginationResult
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import dev.inmo.micro_utils.repos.pagination.getAll
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
open class FullReadKeyValueCacheRepo<Key,Value>(
|
||||||
|
protected open val parentRepo: ReadKeyValueRepo<Key, Value>,
|
||||||
|
protected open val kvCache: FullKVCache<Key, Value>,
|
||||||
|
) : ReadKeyValueRepo<Key, Value>, FullCacheRepo {
|
||||||
|
protected inline fun <T> doOrTakeAndActualize(
|
||||||
|
action: FullKVCache<Key, Value>.() -> Optional<T>,
|
||||||
|
actionElse: ReadKeyValueRepo<Key, Value>.() -> T,
|
||||||
|
actualize: FullKVCache<Key, Value>.(T) -> Unit
|
||||||
|
): T {
|
||||||
|
kvCache.action().onPresented {
|
||||||
|
return it
|
||||||
|
}.onAbsent {
|
||||||
|
return parentRepo.actionElse().also {
|
||||||
|
kvCache.actualize(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("The result should be returned above")
|
||||||
|
}
|
||||||
|
protected open suspend fun actualizeAll() {
|
||||||
|
kvCache.clear()
|
||||||
|
kvCache.set(parentRepo.getAll { keys(it) }.toMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun get(k: Key): Value? = doOrTakeAndActualize(
|
||||||
|
{ get(k) ?.optional ?: Optional.absent() },
|
||||||
|
{ get(k) },
|
||||||
|
{ set(k, it ?: return@doOrTakeAndActualize) }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = doOrTakeAndActualize(
|
||||||
|
{ values(pagination, reversed).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull },
|
||||||
|
{ values(pagination, reversed) },
|
||||||
|
{ if (it.results.isNotEmpty()) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(): Long = doOrTakeAndActualize(
|
||||||
|
{ count().takeIf { it != 0L }.optionalOrAbsentIfNull },
|
||||||
|
{ count() },
|
||||||
|
{ if (it != 0L) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(key: Key): Boolean = doOrTakeAndActualize(
|
||||||
|
{ contains(key).takeIf { it }.optionalOrAbsentIfNull },
|
||||||
|
{ contains(key) },
|
||||||
|
{ if (it) parentRepo.get(key) ?.also { kvCache.set(key, it) } }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize(
|
||||||
|
{ keys(pagination, reversed).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull },
|
||||||
|
{ keys(pagination, reversed) },
|
||||||
|
{ if (it.results.isNotEmpty()) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean): PaginationResult<Key> = doOrTakeAndActualize(
|
||||||
|
{ keys(v, pagination, reversed).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull },
|
||||||
|
{ parentRepo.keys(v, pagination, reversed) },
|
||||||
|
{ if (it.results.isNotEmpty()) actualizeAll() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> ReadKeyValueRepo<Key, Value>.cached(
|
||||||
|
kvCache: FullKVCache<Key, Value>
|
||||||
|
) = FullReadKeyValueCacheRepo(this, kvCache)
|
||||||
|
|
||||||
|
open class FullWriteKeyValueCacheRepo<Key,Value>(
|
||||||
|
protected open val parentRepo: WriteKeyValueRepo<Key, Value>,
|
||||||
|
protected open val kvCache: FullKVCache<Key, Value>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) : WriteKeyValueRepo<Key, Value> by parentRepo, FullCacheRepo {
|
||||||
|
protected val onNewJob = parentRepo.onNewValue.onEach { kvCache.set(it.first, it.second) }.launchIn(scope)
|
||||||
|
protected val onRemoveJob = parentRepo.onValueRemoved.onEach { kvCache.unset(it) }.launchIn(scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> WriteKeyValueRepo<Key, Value>.caching(
|
||||||
|
kvCache: FullKVCache<Key, Value>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = FullWriteKeyValueCacheRepo(this, kvCache, scope)
|
||||||
|
|
||||||
|
open class FullKeyValueCacheRepo<Key,Value>(
|
||||||
|
parentRepo: KeyValueRepo<Key, Value>,
|
||||||
|
kvCache: FullKVCache<Key, Value>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) : FullWriteKeyValueCacheRepo<Key,Value>(parentRepo, kvCache, scope),
|
||||||
|
KeyValueRepo<Key,Value>,
|
||||||
|
ReadKeyValueRepo<Key, Value> by FullReadKeyValueCacheRepo(parentRepo, kvCache) {
|
||||||
|
override suspend fun unsetWithValues(toUnset: List<Value>) = parentRepo.unsetWithValues(toUnset)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> KeyValueRepo<Key, Value>.cached(
|
||||||
|
kvCache: FullKVCache<Key, Value>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = FullKeyValueCacheRepo(this, kvCache, scope)
|
154
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt
vendored
Normal file
154
repos/cache/src/commonMain/kotlin/dev/inmo/micro_utils/repos/cache/full/FullKeyValuesCacheRepo.kt
vendored
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.cache.full
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.*
|
||||||
|
import dev.inmo.micro_utils.pagination.*
|
||||||
|
import dev.inmo.micro_utils.pagination.utils.*
|
||||||
|
import dev.inmo.micro_utils.repos.*
|
||||||
|
import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
|
open class FullReadKeyValuesCacheRepo<Key,Value>(
|
||||||
|
protected open val parentRepo: ReadKeyValuesRepo<Key, Value>,
|
||||||
|
protected open val kvCache: FullKVCache<Key, List<Value>>,
|
||||||
|
) : ReadKeyValuesRepo<Key, Value>, FullCacheRepo {
|
||||||
|
protected inline fun <T> doOrTakeAndActualize(
|
||||||
|
action: FullKVCache<Key, List<Value>>.() -> Optional<T>,
|
||||||
|
actionElse: ReadKeyValuesRepo<Key, Value>.() -> T,
|
||||||
|
actualize: FullKVCache<Key, List<Value>>.(T) -> Unit
|
||||||
|
): T {
|
||||||
|
kvCache.action().onPresented {
|
||||||
|
return it
|
||||||
|
}.onAbsent {
|
||||||
|
return parentRepo.actionElse().also {
|
||||||
|
kvCache.actualize(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("The result should be returned above")
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun actualizeKey(k: Key) {
|
||||||
|
kvCache.set(k, parentRepo.getAll(k))
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open suspend fun actualizeAll() {
|
||||||
|
doAllWithCurrentPaging { kvCache.keys(it).also { kvCache.unset(it.results) } }
|
||||||
|
kvCache.set(parentRepo.getAll())
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> {
|
||||||
|
return doOrTakeAndActualize(
|
||||||
|
{
|
||||||
|
get(k) ?.paginate(
|
||||||
|
pagination.let { if (reversed) it.reverse(count(k)) else it }
|
||||||
|
) ?.let {
|
||||||
|
if (reversed) it.copy(results = it.results.reversed()) else it
|
||||||
|
}.optionalOrAbsentIfNull
|
||||||
|
},
|
||||||
|
{ get(k, pagination, reversed) },
|
||||||
|
{ actualizeKey(k) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> {
|
||||||
|
return doOrTakeAndActualize(
|
||||||
|
{
|
||||||
|
kvCache.keys(pagination, reversed).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull
|
||||||
|
},
|
||||||
|
{ parentRepo.keys(pagination, reversed) },
|
||||||
|
{ actualizeAll() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun count(): Long = doOrTakeAndActualize(
|
||||||
|
{ count().takeIf { it != 0L }.optionalOrAbsentIfNull },
|
||||||
|
{ count() },
|
||||||
|
{ if (it != 0L) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun count(k: Key): Long = doOrTakeAndActualize(
|
||||||
|
{ count().takeIf { it != 0L }.optionalOrAbsentIfNull },
|
||||||
|
{ count() },
|
||||||
|
{ if (it != 0L) actualizeKey(k) }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key, v: Value): Boolean = doOrTakeAndActualize(
|
||||||
|
{ get(k) ?.contains(v).takeIf { it == true }.optionalOrAbsentIfNull },
|
||||||
|
{ contains(k, v) },
|
||||||
|
{ if (it) actualizeKey(k) }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun contains(k: Key): Boolean = doOrTakeAndActualize(
|
||||||
|
{ contains(k).takeIf { it }.optionalOrAbsentIfNull },
|
||||||
|
{ contains(k) },
|
||||||
|
{ if (it) actualizeKey(k) }
|
||||||
|
)
|
||||||
|
|
||||||
|
override suspend fun keys(
|
||||||
|
v: Value,
|
||||||
|
pagination: Pagination,
|
||||||
|
reversed: Boolean
|
||||||
|
): PaginationResult<Key> = doOrTakeAndActualize(
|
||||||
|
{
|
||||||
|
val keys = getAllWithNextPaging { keys(it) }.filter { get(it) ?.contains(v) == true }.optionallyReverse(reversed)
|
||||||
|
if (keys.isNotEmpty()) {
|
||||||
|
keys.paginate(pagination.optionallyReverse(keys.size, reversed)).takeIf { it.results.isNotEmpty() }.optionalOrAbsentIfNull
|
||||||
|
} else {
|
||||||
|
Optional.absent()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ parentRepo.keys(v, pagination, reversed) },
|
||||||
|
{ if (it.results.isNotEmpty()) actualizeAll() }
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> ReadKeyValuesRepo<Key, Value>.cached(
|
||||||
|
kvCache: FullKVCache<Key, List<Value>>
|
||||||
|
) = FullReadKeyValuesCacheRepo(this, kvCache)
|
||||||
|
|
||||||
|
open class FullWriteKeyValuesCacheRepo<Key,Value>(
|
||||||
|
protected open val parentRepo: WriteKeyValuesRepo<Key, Value>,
|
||||||
|
protected open val kvCache: FullKVCache<Key, List<Value>>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) : WriteKeyValuesRepo<Key, Value> by parentRepo, FullCacheRepo {
|
||||||
|
protected val onNewJob = parentRepo.onNewValue.onEach {
|
||||||
|
kvCache.set(
|
||||||
|
it.first,
|
||||||
|
kvCache.get(it.first) ?.plus(it.second) ?: listOf(it.second)
|
||||||
|
)
|
||||||
|
}.launchIn(scope)
|
||||||
|
protected val onRemoveJob = parentRepo.onValueRemoved.onEach {
|
||||||
|
kvCache.set(
|
||||||
|
it.first,
|
||||||
|
kvCache.get(it.first) ?.minus(it.second) ?: return@onEach
|
||||||
|
)
|
||||||
|
}.launchIn(scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> WriteKeyValuesRepo<Key, Value>.caching(
|
||||||
|
kvCache: FullKVCache<Key, List<Value>>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = FullWriteKeyValuesCacheRepo(this, kvCache, scope)
|
||||||
|
|
||||||
|
open class FullKeyValuesCacheRepo<Key,Value>(
|
||||||
|
parentRepo: KeyValuesRepo<Key, Value>,
|
||||||
|
kvCache: FullKVCache<Key, List<Value>>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) : FullWriteKeyValuesCacheRepo<Key, Value>(parentRepo, kvCache, scope),
|
||||||
|
KeyValuesRepo<Key, Value>,
|
||||||
|
ReadKeyValuesRepo<Key, Value> by FullReadKeyValuesCacheRepo(parentRepo, kvCache) {
|
||||||
|
override suspend fun clearWithValue(v: Value) {
|
||||||
|
doAllWithCurrentPaging {
|
||||||
|
keys(v, it).also {
|
||||||
|
remove(it.results.associateWith { listOf(v) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <Key, Value> KeyValuesRepo<Key, Value>.caching(
|
||||||
|
kvCache: FullKVCache<Key, List<Value>>,
|
||||||
|
scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
|
||||||
|
) = FullKeyValuesCacheRepo(this, kvCache, scope)
|
@@ -1,22 +1,51 @@
|
|||||||
package dev.inmo.micro_utils.repos
|
package dev.inmo.micro_utils.repos
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.*
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
interface MapperRepo<FromKey, FromValue, ToKey, ToValue> {
|
interface MapperRepo<FromKey, FromValue, ToKey, ToValue> {
|
||||||
|
val keyMapper: SimpleSuspendableMapper<FromKey, ToKey>
|
||||||
|
get() = simpleSuspendableMapper(
|
||||||
|
{ it.toInnerKey() },
|
||||||
|
{ it.toOutKey() }
|
||||||
|
)
|
||||||
|
val valueMapper: SimpleSuspendableMapper<FromValue, ToValue>
|
||||||
|
get() = simpleSuspendableMapper(
|
||||||
|
{ it.toInnerValue() },
|
||||||
|
{ it.toOutValue() }
|
||||||
|
)
|
||||||
|
|
||||||
suspend fun FromKey.toOutKey() = this as ToKey
|
suspend fun FromKey.toOutKey() = this as ToKey
|
||||||
suspend fun FromValue.toOutValue() = this as ToValue
|
suspend fun FromValue.toOutValue() = this as ToValue
|
||||||
|
|
||||||
suspend fun ToKey.toInnerKey() = this as FromKey
|
suspend fun ToKey.toInnerKey() = this as FromKey
|
||||||
suspend fun ToValue.toInnerValue() = this as FromValue
|
suspend fun ToValue.toInnerValue() = this as FromValue
|
||||||
|
|
||||||
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> mapper(
|
class SimpleMapperRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
private val keyFromToTo: suspend FromKey.() -> ToKey,
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
private val valueFromToTo: suspend FromValue.() -> ToValue,
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
private val keyToToFrom: suspend ToKey.() -> FromKey,
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
private val valueToToFrom: suspend ToValue.() -> FromValue
|
||||||
) = object : MapperRepo<FromKey, FromValue, ToKey, ToValue> {
|
) : MapperRepo<FromKey, FromValue, ToKey, ToValue> {
|
||||||
override suspend fun FromKey.toOutKey(): ToKey = keyFromToTo()
|
override suspend fun FromKey.toOutKey(): ToKey = keyFromToTo()
|
||||||
override suspend fun FromValue.toOutValue(): ToValue = valueFromToTo()
|
override suspend fun FromValue.toOutValue(): ToValue = valueFromToTo()
|
||||||
override suspend fun ToKey.toInnerKey(): FromKey = keyToToFrom()
|
override suspend fun ToKey.toInnerKey(): FromKey = keyToToFrom()
|
||||||
override suspend fun ToValue.toInnerValue(): FromValue = valueToToFrom()
|
override suspend fun ToValue.toInnerValue(): FromValue = valueToToFrom()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operator fun <FromKey, FromValue, ToKey, ToValue> MapperRepo.Companion.invoke(
|
||||||
|
keyFromToTo: suspend FromKey.() -> ToKey,
|
||||||
|
valueFromToTo: suspend FromValue.() -> ToValue,
|
||||||
|
keyToToFrom: suspend ToKey.() -> FromKey,
|
||||||
|
valueToToFrom: suspend ToValue.() -> FromValue
|
||||||
|
) = SimpleMapperRepo(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
|
|
||||||
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> mapper(
|
||||||
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
|
) = MapperRepo(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
|
@@ -48,6 +48,10 @@ interface KeyValueRepo<Key, Value> : ReadKeyValueRepo<Key, Value>, WriteKeyValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun clear() {
|
||||||
|
doAllWithCurrentPaging { keys(it).also { unset(it.results) } }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
typealias StandardKeyValueRepo<Key,Value> = KeyValueRepo<Key, Value>
|
typealias StandardKeyValueRepo<Key,Value> = KeyValueRepo<Key, Value>
|
||||||
|
|
||||||
|
@@ -0,0 +1,130 @@
|
|||||||
|
package dev.inmo.micro_utils.repos.mappers
|
||||||
|
|
||||||
|
import dev.inmo.micro_utils.common.*
|
||||||
|
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<FromId, FromRegistered, ToId, ToRegistered>(
|
||||||
|
private val to: ReadCRUDRepo<ToRegistered, ToId>,
|
||||||
|
mapper: MapperRepo<FromId, FromRegistered, ToId, ToRegistered>
|
||||||
|
) : ReadCRUDRepo<FromRegistered, FromId>, MapperRepo<FromId, FromRegistered, ToId, ToRegistered> by mapper {
|
||||||
|
override suspend fun getByPagination(
|
||||||
|
pagination: Pagination
|
||||||
|
): PaginationResult<FromRegistered> = to.getByPagination(
|
||||||
|
pagination
|
||||||
|
).let {
|
||||||
|
it.changeResultsUnchecked(
|
||||||
|
it.results.map { it.toInnerValue() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun count(): Long = to.count()
|
||||||
|
|
||||||
|
override suspend fun contains(id: FromId): Boolean = to.contains(id.toOutKey())
|
||||||
|
|
||||||
|
override suspend fun getById(id: FromId): FromRegistered? = to.getById(
|
||||||
|
id.toOutKey()
|
||||||
|
) ?.toInnerValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <FromKey, FromValue, ToKey, ToValue> ReadCRUDRepo<ToValue, ToKey>.withMapper(
|
||||||
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
|
): ReadCRUDRepo<FromValue, FromKey> = MapperReadCRUDRepo(this, mapper)
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadCRUDRepo<ToValue, ToKey>.withMapper(
|
||||||
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
|
): ReadCRUDRepo<FromValue, FromKey> = withMapper(
|
||||||
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
|
)
|
||||||
|
|
||||||
|
open class MapperWriteCRUDRepo<FromId, FromRegistered, FromInput, ToId, ToRegistered, ToInput>(
|
||||||
|
private val to: WriteCRUDRepo<ToRegistered, ToId, ToInput>,
|
||||||
|
mapper: MapperRepo<FromId, FromRegistered, ToId, ToRegistered>,
|
||||||
|
inputMapper: SimpleSuspendableMapper<FromInput, ToInput>
|
||||||
|
) : WriteCRUDRepo<FromRegistered, FromId, FromInput>,
|
||||||
|
MapperRepo<FromId, FromRegistered, ToId, ToRegistered> by mapper,
|
||||||
|
SimpleSuspendableMapper<FromInput, ToInput> by inputMapper {
|
||||||
|
override val newObjectsFlow: Flow<FromRegistered> = to.newObjectsFlow.map { it.toInnerValue() }
|
||||||
|
override val updatedObjectsFlow: Flow<FromRegistered> = to.updatedObjectsFlow.map { it.toInnerValue() }
|
||||||
|
override val deletedObjectsIdsFlow: Flow<FromId> = to.deletedObjectsIdsFlow.map { it.toInnerKey() }
|
||||||
|
|
||||||
|
override suspend fun deleteById(ids: List<FromId>) = to.deleteById(ids.map { it.toOutKey() })
|
||||||
|
|
||||||
|
override suspend fun update(
|
||||||
|
values: List<UpdatedValuePair<FromId, FromInput>>
|
||||||
|
): List<FromRegistered> = to.update(
|
||||||
|
values.map {
|
||||||
|
it.first.toOutKey() to convert(it.second)
|
||||||
|
}
|
||||||
|
).map { it.toInnerValue() }
|
||||||
|
|
||||||
|
override suspend fun update(
|
||||||
|
id: FromId,
|
||||||
|
value: FromInput
|
||||||
|
): FromRegistered? = to.update(id.toOutKey(), convert(value)) ?.toInnerValue()
|
||||||
|
|
||||||
|
override suspend fun create(values: List<FromInput>): List<FromRegistered> = to.create(
|
||||||
|
values.map {
|
||||||
|
convert(it)
|
||||||
|
}
|
||||||
|
).map {
|
||||||
|
it.toInnerValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <FromKey, FromValue, FromInput, ToKey, ToValue, ToInput> WriteCRUDRepo<ToValue, ToKey, ToInput>.withMapper(
|
||||||
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>,
|
||||||
|
simpleSuspendableMapper: SimpleSuspendableMapper<FromInput, ToInput>
|
||||||
|
): WriteCRUDRepo<FromValue, FromKey, FromInput> = MapperWriteCRUDRepo(this, mapper, simpleSuspendableMapper)
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <reified FromKey, reified FromValue, reified FromInput, reified ToKey, reified ToValue, reified ToInput> WriteCRUDRepo<ToValue, ToKey, ToInput>.withMapper(
|
||||||
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
|
noinline inputFromToTo: suspend FromInput.() -> ToInput = { this as ToInput },
|
||||||
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
|
noinline inputToToFrom: suspend ToInput.() -> FromInput = { this as FromInput },
|
||||||
|
): WriteCRUDRepo<FromValue, FromKey, FromInput> = withMapper(
|
||||||
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom),
|
||||||
|
simpleSuspendableMapper({ inputToToFrom(it) }, { inputFromToTo(it) })
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
|
open class MapperCRUDRepo<FromId, FromRegistered, FromInput, ToId, ToRegistered, ToInput>(
|
||||||
|
private val to: CRUDRepo<ToRegistered, ToId, ToInput>,
|
||||||
|
private val mapper: MapperRepo<FromId, FromRegistered, ToId, ToRegistered>,
|
||||||
|
private val inputMapper: SimpleSuspendableMapper<FromInput, ToInput>
|
||||||
|
) : CRUDRepo<FromRegistered, FromId, FromInput>,
|
||||||
|
MapperRepo<FromId, FromRegistered, ToId, ToRegistered> by mapper,
|
||||||
|
ReadCRUDRepo<FromRegistered, FromId> by MapperReadCRUDRepo(to, mapper),
|
||||||
|
WriteCRUDRepo<FromRegistered, FromId, FromInput> by MapperWriteCRUDRepo(to, mapper, inputMapper)
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <FromKey, FromValue, FromInput, ToKey, ToValue, ToInput> CRUDRepo<ToValue, ToKey, ToInput>.withMapper(
|
||||||
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>,
|
||||||
|
simpleSuspendableMapper: SimpleSuspendableMapper<FromInput, ToInput>
|
||||||
|
): CRUDRepo<FromValue, FromKey, FromInput> = MapperCRUDRepo(this, mapper, simpleSuspendableMapper)
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun <reified FromKey, reified FromValue, reified FromInput, reified ToKey, reified ToValue, reified ToInput> CRUDRepo<ToValue, ToKey, ToInput>.withMapper(
|
||||||
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
|
noinline inputFromToTo: suspend FromInput.() -> ToInput = { this as ToInput },
|
||||||
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
|
noinline inputToToFrom: suspend ToInput.() -> FromInput = { this as FromInput },
|
||||||
|
): CRUDRepo<FromValue, FromKey, FromInput> = withMapper(
|
||||||
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom),
|
||||||
|
simpleSuspendableMapper({ inputToToFrom(it) }, { inputFromToTo(it) })
|
||||||
|
)
|
@@ -1,13 +1,10 @@
|
|||||||
package dev.inmo.micro_utils.repos.mappers
|
package dev.inmo.micro_utils.repos.mappers
|
||||||
|
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperReadKeyValueRepo", "dev.inmo.micro_utils.repos.mappers.MapperReadKeyValueRepo"))
|
|
||||||
typealias MapperReadStandardKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: ReadKeyValueRepo<ToKey, ToValue>,
|
private val to: ReadKeyValueRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
@@ -23,11 +20,8 @@ open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerValue() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerValue() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,11 +32,8 @@ open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerKey() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerKey() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,11 +46,8 @@ open class MapperReadKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerKey() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerKey() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,16 +65,14 @@ inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValueRepo<ToKey, ToValue>
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): ReadKeyValueRepo<FromKey, FromValue> = withMapper(
|
): ReadKeyValueRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperWriteKeyValueRepo", "dev.inmo.micro_utils.repos.mappers.MapperWriteKeyValueRepo"))
|
|
||||||
typealias MapperWriteStandardKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
open class MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperWriteKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: WriteKeyValueRepo<ToKey, ToValue>,
|
private val to: WriteKeyValueRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
@@ -122,16 +108,14 @@ inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValueRepo<ToKey, ToValue
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): WriteKeyValueRepo<FromKey, FromValue> = withMapper(
|
): WriteKeyValueRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperKeyValueRepo", "dev.inmo.micro_utils.repos.mappers.MapperKeyValueRepo"))
|
|
||||||
typealias MapperStandardKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperKeyValueRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: KeyValueRepo<ToKey, ToValue>,
|
private val to: KeyValueRepo<ToKey, ToValue>,
|
||||||
@@ -148,10 +132,10 @@ inline fun <FromKey, FromValue, ToKey, ToValue> KeyValueRepo<ToKey, ToValue>.wit
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValueRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): KeyValueRepo<FromKey, FromValue> = withMapper(
|
): KeyValueRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
package dev.inmo.micro_utils.repos.mappers
|
package dev.inmo.micro_utils.repos.mappers
|
||||||
|
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
import dev.inmo.micro_utils.repos.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperReadKeyValuesRepo", "dev.inmo.micro_utils.repos.mappers.MapperReadKeyValuesRepo"))
|
|
||||||
typealias MapperReadOneToManyKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: ReadKeyValuesRepo<ToKey, ToValue>,
|
private val to: ReadKeyValuesRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
@@ -21,11 +18,8 @@ open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerValue() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerValue() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,11 +30,8 @@ open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerKey() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerKey() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,11 +44,8 @@ open class MapperReadKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
|||||||
pagination,
|
pagination,
|
||||||
reversed
|
reversed
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.map { it.toInnerKey() }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map { it.toInnerKey() },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,16 +63,14 @@ inline fun <FromKey, FromValue, ToKey, ToValue> ReadKeyValuesRepo<ToKey, ToValue
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> ReadKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): ReadKeyValuesRepo<FromKey, FromValue> = withMapper(
|
): ReadKeyValuesRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperWriteKeyValuesRepo", "dev.inmo.micro_utils.repos.mappers.MapperWriteKeyValuesRepo"))
|
|
||||||
typealias MapperWriteOneToManyKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
open class MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperWriteKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: WriteKeyValuesRepo<ToKey, ToValue>,
|
private val to: WriteKeyValuesRepo<ToKey, ToValue>,
|
||||||
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
mapper: MapperRepo<FromKey, FromValue, ToKey, ToValue>
|
||||||
@@ -128,16 +114,14 @@ inline fun <FromKey, FromValue, ToKey, ToValue> WriteKeyValuesRepo<ToKey, ToValu
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> WriteKeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): WriteKeyValuesRepo<FromKey, FromValue> = withMapper(
|
): WriteKeyValuesRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapperKeyValuesRepo", "dev.inmo.micro_utils.repos.mappers.MapperKeyValuesRepo"))
|
|
||||||
typealias MapperOneToManyKeyValueRepo<FromKey, FromValue, ToKey, ToValue> = MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>
|
|
||||||
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
open class MapperKeyValuesRepo<FromKey, FromValue, ToKey, ToValue>(
|
||||||
private val to: KeyValuesRepo<ToKey, ToValue>,
|
private val to: KeyValuesRepo<ToKey, ToValue>,
|
||||||
@@ -154,10 +138,10 @@ inline fun <FromKey, FromValue, ToKey, ToValue> KeyValuesRepo<ToKey, ToValue>.wi
|
|||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
inline fun <reified FromKey, reified FromValue, reified ToKey, reified ToValue> KeyValuesRepo<ToKey, ToValue>.withMapper(
|
||||||
crossinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
noinline keyFromToTo: suspend FromKey.() -> ToKey = { this as ToKey },
|
||||||
crossinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
noinline valueFromToTo: suspend FromValue.() -> ToValue = { this as ToValue },
|
||||||
crossinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
noinline keyToToFrom: suspend ToKey.() -> FromKey = { this as FromKey },
|
||||||
crossinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
noinline valueToToFrom: suspend ToValue.() -> FromValue = { this as FromValue },
|
||||||
): KeyValuesRepo<FromKey, FromValue> = withMapper(
|
): KeyValuesRepo<FromKey, FromValue> = withMapper(
|
||||||
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
mapper(keyFromToTo, valueFromToTo, keyToToFrom, valueToToFrom)
|
||||||
)
|
)
|
||||||
|
@@ -13,9 +13,6 @@ import java.nio.file.StandardWatchEventKinds.*
|
|||||||
private inline val String.isAbsolute
|
private inline val String.isAbsolute
|
||||||
get() = startsWith(File.separator)
|
get() = startsWith(File.separator)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("FileReadKeyValueRepo", "dev.inmo.micro_utils.repos.FileReadKeyValueRepo"))
|
|
||||||
typealias FileReadStandardKeyValueRepo = FileReadKeyValueRepo
|
|
||||||
|
|
||||||
class FileReadKeyValueRepo(
|
class FileReadKeyValueRepo(
|
||||||
private val folder: File
|
private val folder: File
|
||||||
) : ReadKeyValueRepo<String, File> {
|
) : ReadKeyValueRepo<String, File> {
|
||||||
@@ -34,7 +31,7 @@ class FileReadKeyValueRepo(
|
|||||||
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<File> {
|
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<File> {
|
||||||
val count = count()
|
val count = count()
|
||||||
val resultPagination = if (reversed) pagination.reverse(count) else pagination
|
val resultPagination = if (reversed) pagination.reverse(count) else pagination
|
||||||
val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndex) ?: return emptyPaginationResult()
|
val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive) ?: return emptyPaginationResult()
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
filesPaths.reverse()
|
filesPaths.reverse()
|
||||||
}
|
}
|
||||||
@@ -47,7 +44,7 @@ class FileReadKeyValueRepo(
|
|||||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<String> {
|
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<String> {
|
||||||
val count = count()
|
val count = count()
|
||||||
val resultPagination = if (reversed) pagination.reverse(count) else pagination
|
val resultPagination = if (reversed) pagination.reverse(count) else pagination
|
||||||
val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndex) ?: return emptyPaginationResult()
|
val filesPaths = folder.list() ?.copyOfRange(resultPagination.firstIndex, resultPagination.lastIndexExclusive) ?: return emptyPaginationResult()
|
||||||
if (reversed) {
|
if (reversed) {
|
||||||
filesPaths.reverse()
|
filesPaths.reverse()
|
||||||
}
|
}
|
||||||
@@ -82,9 +79,6 @@ class FileReadKeyValueRepo(
|
|||||||
override suspend fun count(): Long = folder.list() ?.size ?.toLong() ?: 0L
|
override suspend fun count(): Long = folder.list() ?.size ?.toLong() ?: 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("FileWriteKeyValueRepo", "dev.inmo.micro_utils.repos.FileWriteKeyValueRepo"))
|
|
||||||
typealias FileWriteStandardKeyValueRepo = FileWriteKeyValueRepo
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Files watching will not correctly works on Android with version of API lower than API 26
|
* Files watching will not correctly works on Android with version of API lower than API 26
|
||||||
*/
|
*/
|
||||||
@@ -99,7 +93,9 @@ class FileWriteKeyValueRepo(
|
|||||||
override val onValueRemoved: Flow<String> = _onValueRemoved.asSharedFlow()
|
override val onValueRemoved: Flow<String> = _onValueRemoved.asSharedFlow()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
folder.mkdirs()
|
if (!folder.mkdirs() && !folder.exists()) {
|
||||||
|
error("Unable to create folder ${folder.absolutePath}")
|
||||||
|
}
|
||||||
filesChangedProcessingScope ?.let {
|
filesChangedProcessingScope ?.let {
|
||||||
it.launch {
|
it.launch {
|
||||||
try {
|
try {
|
||||||
@@ -144,15 +140,17 @@ class FileWriteKeyValueRepo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun set(toSet: Map<String, File>) {
|
override suspend fun set(toSet: Map<String, File>) {
|
||||||
supervisorScope {
|
val scope = CoroutineScope(currentCoroutineContext())
|
||||||
toSet.map { (filename, fileSource) ->
|
toSet.map { (filename, fileSource) ->
|
||||||
launch {
|
scope.launch {
|
||||||
val file = File(folder, filename)
|
val file = File(folder, filename)
|
||||||
|
|
||||||
file.delete()
|
file.delete()
|
||||||
fileSource.copyTo(file, overwrite = true)
|
fileSource.copyTo(file, overwrite = true)
|
||||||
_onNewValue.emit(filename to file)
|
if (!file.exists()) {
|
||||||
|
error("Can't create file $file with new content")
|
||||||
}
|
}
|
||||||
|
_onNewValue.emit(filename to file)
|
||||||
}
|
}
|
||||||
}.joinAll()
|
}.joinAll()
|
||||||
}
|
}
|
||||||
@@ -180,9 +178,6 @@ class FileWriteKeyValueRepo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("FileKeyValueRepo", "dev.inmo.micro_utils.repos.FileKeyValueRepo"))
|
|
||||||
typealias FileStandardKeyValueRepo = FileKeyValueRepo
|
|
||||||
|
|
||||||
@Warning("Files watching will not correctly works on Android Platform with version of API lower than API 26")
|
@Warning("Files watching will not correctly works on Android Platform with version of API lower than API 26")
|
||||||
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
class FileKeyValueRepo(
|
class FileKeyValueRepo(
|
||||||
|
@@ -3,8 +3,7 @@ package dev.inmo.micro_utils.repos.keyvalue
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import dev.inmo.micro_utils.pagination.Pagination
|
import dev.inmo.micro_utils.pagination.*
|
||||||
import dev.inmo.micro_utils.pagination.PaginationResult
|
|
||||||
import dev.inmo.micro_utils.pagination.utils.paginate
|
import dev.inmo.micro_utils.pagination.utils.paginate
|
||||||
import dev.inmo.micro_utils.pagination.utils.reverse
|
import dev.inmo.micro_utils.pagination.utils.reverse
|
||||||
import dev.inmo.micro_utils.repos.KeyValueRepo
|
import dev.inmo.micro_utils.repos.KeyValueRepo
|
||||||
@@ -72,14 +71,11 @@ class KeyValueStore<T : Any> internal constructor (
|
|||||||
return sharedPreferences.all.values.paginate(
|
return sharedPreferences.all.values.paginate(
|
||||||
resultPagination
|
resultPagination
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
|
||||||
it.pagesNumber,
|
|
||||||
it.results.map {
|
it.results.map {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
it as T
|
it as T
|
||||||
}.let { if (reversed) it.reversed() else it },
|
}.let { if (reversed) it.reversed() else it }
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,11 +85,8 @@ class KeyValueStore<T : Any> internal constructor (
|
|||||||
return sharedPreferences.all.keys.paginate(
|
return sharedPreferences.all.keys.paginate(
|
||||||
resultPagination
|
resultPagination
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.let { if (reversed) it.reversed() else it }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.let { if (reversed) it.reversed() else it },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,11 +96,8 @@ class KeyValueStore<T : Any> internal constructor (
|
|||||||
return sharedPreferences.all.mapNotNull { (k, value) -> if (value == v) k else null }.paginate(
|
return sharedPreferences.all.mapNotNull { (k, value) -> if (value == v) k else null }.paginate(
|
||||||
resultPagination
|
resultPagination
|
||||||
).let {
|
).let {
|
||||||
PaginationResult(
|
it.changeResultsUnchecked(
|
||||||
it.page,
|
it.results.let { if (reversed) it.reversed() else it }
|
||||||
it.pagesNumber,
|
|
||||||
it.results.let { if (reversed) it.reversed() else it },
|
|
||||||
it.size
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,12 +20,6 @@ abstract class AbstractExposedWriteCRUDRepo<ObjectType, IdType, InputValueType>(
|
|||||||
protected val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
protected val _newObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
||||||
protected val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
protected val _updatedObjectsFlow = MutableSharedFlow<ObjectType>(replyCacheInFlows, flowsChannelsSize)
|
||||||
protected val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize)
|
protected val _deletedObjectsIdsFlow = MutableSharedFlow<IdType>(replyCacheInFlows, flowsChannelsSize)
|
||||||
@Deprecated("Renamed", ReplaceWith("_newObjectsFlow"))
|
|
||||||
protected val newObjectsChannel = _newObjectsFlow
|
|
||||||
@Deprecated("Renamed", ReplaceWith("_updatedObjectsFlow"))
|
|
||||||
protected val updateObjectsChannel = _updatedObjectsFlow
|
|
||||||
@Deprecated("Renamed", ReplaceWith("_deletedObjectsIdsFlow"))
|
|
||||||
protected val deleteObjectsIdsChannel = _deletedObjectsIdsFlow
|
|
||||||
|
|
||||||
override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow()
|
override val newObjectsFlow: Flow<ObjectType> = _newObjectsFlow.asSharedFlow()
|
||||||
override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow()
|
override val updatedObjectsFlow: Flow<ObjectType> = _updatedObjectsFlow.asSharedFlow()
|
||||||
|
@@ -87,6 +87,7 @@ class WriteMapKeyValueRepo<Key, Value>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
class MapKeyValueRepo<Key, Value>(
|
class MapKeyValueRepo<Key, Value>(
|
||||||
private val map: MutableMap<Key, Value> = mutableMapOf()
|
private val map: MutableMap<Key, Value> = mutableMapOf()
|
||||||
) : KeyValueRepo<Key, Value>,
|
) : KeyValueRepo<Key, Value>,
|
||||||
|
@@ -5,8 +5,6 @@ import dev.inmo.micro_utils.pagination.utils.paginate
|
|||||||
import dev.inmo.micro_utils.pagination.utils.reverse
|
import dev.inmo.micro_utils.pagination.utils.reverse
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapReadKeyValuesRepo", "dev.inmo.micro_utils.repos.MapReadKeyValuesRepo"))
|
|
||||||
typealias MapReadOneToManyKeyValueRepo<Key, Value> = MapReadKeyValuesRepo<Key, Value>
|
|
||||||
class MapReadKeyValuesRepo<Key, Value>(
|
class MapReadKeyValuesRepo<Key, Value>(
|
||||||
private val map: Map<Key, List<Value>> = emptyMap()
|
private val map: Map<Key, List<Value>> = emptyMap()
|
||||||
) : ReadKeyValuesRepo<Key, Value> {
|
) : ReadKeyValuesRepo<Key, Value> {
|
||||||
@@ -55,8 +53,6 @@ class MapReadKeyValuesRepo<Key, Value>(
|
|||||||
override suspend fun count(): Long = map.size.toLong()
|
override suspend fun count(): Long = map.size.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapWriteKeyValuesRepo", "dev.inmo.micro_utils.repos.MapWriteKeyValuesRepo"))
|
|
||||||
typealias MapWriteOneToManyKeyValueRepo<Key, Value> = MapWriteKeyValuesRepo<Key, Value>
|
|
||||||
class MapWriteKeyValuesRepo<Key, Value>(
|
class MapWriteKeyValuesRepo<Key, Value>(
|
||||||
private val map: MutableMap<Key, MutableList<Value>> = mutableMapOf()
|
private val map: MutableMap<Key, MutableList<Value>> = mutableMapOf()
|
||||||
) : WriteKeyValuesRepo<Key, Value> {
|
) : WriteKeyValuesRepo<Key, Value> {
|
||||||
@@ -102,8 +98,7 @@ class MapWriteKeyValuesRepo<Key, Value>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("MapKeyValuesRepo", "dev.inmo.micro_utils.repos.MapKeyValuesRepo"))
|
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
||||||
typealias MapOneToManyKeyValueRepo1<Key, Value> = MapKeyValuesRepo<Key, Value>
|
|
||||||
class MapKeyValuesRepo<Key, Value>(
|
class MapKeyValuesRepo<Key, Value>(
|
||||||
private val map: MutableMap<Key, MutableList<Value>> = mutableMapOf()
|
private val map: MutableMap<Key, MutableList<Value>> = mutableMapOf()
|
||||||
) : KeyValuesRepo<Key, Value>,
|
) : KeyValuesRepo<Key, Value>,
|
||||||
@@ -113,6 +108,3 @@ class MapKeyValuesRepo<Key, Value>(
|
|||||||
fun <K, V> MutableMap<K, List<V>>.asKeyValuesRepo(): KeyValuesRepo<K, V> = MapKeyValuesRepo(
|
fun <K, V> MutableMap<K, List<V>>.asKeyValuesRepo(): KeyValuesRepo<K, V> = MapKeyValuesRepo(
|
||||||
map { (k, v) -> k to v.toMutableList() }.toMap().toMutableMap()
|
map { (k, v) -> k to v.toMutableList() }.toMap().toMutableMap()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Deprecated("Renamed", ReplaceWith("asKeyValuesRepo", "dev.inmo.micro_utils.repos.asKeyValuesRepo"))
|
|
||||||
fun <K, V> MutableMap<K, List<V>>.asOneToManyKeyValueRepo(): KeyValuesRepo<K, V> = asKeyValuesRepo()
|
|
||||||
|
@@ -1,65 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.crud
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.pagination.*
|
|
||||||
import dev.inmo.micro_utils.repos.ReadCRUDRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.countRouting
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.idParameterName
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.serializer
|
|
||||||
|
|
||||||
@Deprecated("Use KtorReadCRUDRepoClient instead")
|
|
||||||
class KtorReadStandardCrudRepo<ObjectType, IdType> (
|
|
||||||
private val baseUrl: String,
|
|
||||||
private val unifiedRequester: UnifiedRequester,
|
|
||||||
private val objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
private val objectsSerializerNullable: KSerializer<ObjectType?>,
|
|
||||||
private val idsSerializer: KSerializer<IdType>
|
|
||||||
) : ReadCRUDRepo<ObjectType, IdType> {
|
|
||||||
private val paginationResultSerializer = PaginationResult.serializer(objectsSerializer)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
objectsSerializerNullable: KSerializer<ObjectType?>,
|
|
||||||
idsSerializer: KSerializer<IdType>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (
|
|
||||||
baseUrl, UnifiedRequester(client, serialFormat), objectsSerializer, objectsSerializerNullable, idsSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getByPagination(pagination: Pagination): PaginationResult<ObjectType> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(baseUrl, getByPaginationRouting, pagination.asUrlQueryParts),
|
|
||||||
paginationResultSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getById(id: IdType): ObjectType? = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
getByIdRouting,
|
|
||||||
idParameterName to unifiedRequester.encodeUrlQueryValue(idsSerializer, id)
|
|
||||||
),
|
|
||||||
objectsSerializerNullable
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun contains(id: IdType): Boolean = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
containsRouting,
|
|
||||||
idParameterName to unifiedRequester.encodeUrlQueryValue(idsSerializer, id)
|
|
||||||
),
|
|
||||||
Boolean.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun count(): Long = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
countRouting
|
|
||||||
),
|
|
||||||
Long.serializer()
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,47 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.crud
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
|
||||||
import dev.inmo.micro_utils.ktor.common.StandardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.ktor.common.standardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
|
|
||||||
@Deprecated("Use KtorCRUDRepoClient instead")
|
|
||||||
class KtorStandardCrudRepo<ObjectType, IdType, InputValue> (
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
unifiedRequester: UnifiedRequester,
|
|
||||||
objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
objectsNullableSerializer: KSerializer<ObjectType?>,
|
|
||||||
inputsSerializer: KSerializer<InputValue>,
|
|
||||||
idsSerializer: KSerializer<IdType>
|
|
||||||
) : CRUDRepo<ObjectType, IdType, InputValue>,
|
|
||||||
ReadCRUDRepo<ObjectType, IdType> by KtorReadStandardCrudRepo(
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
objectsSerializer,
|
|
||||||
objectsNullableSerializer,
|
|
||||||
idsSerializer
|
|
||||||
),
|
|
||||||
WriteCRUDRepo<ObjectType, IdType, InputValue> by KtorWriteStandardCrudRepo(
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
objectsSerializer,
|
|
||||||
objectsNullableSerializer,
|
|
||||||
inputsSerializer,
|
|
||||||
idsSerializer
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
client: HttpClient,
|
|
||||||
objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
objectsNullableSerializer: KSerializer<ObjectType?>,
|
|
||||||
inputsSerializer: KSerializer<InputValue>,
|
|
||||||
idsSerializer: KSerializer<IdType>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this(
|
|
||||||
baseUrl, baseSubpart, UnifiedRequester(client, serialFormat), objectsSerializer, objectsNullableSerializer, inputsSerializer, idsSerializer
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,80 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.crud
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.repos.UpdatedValuePair
|
|
||||||
import dev.inmo.micro_utils.repos.WriteCRUDRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.crud.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.*
|
|
||||||
|
|
||||||
@Deprecated("Use KtorWriteCRUDRepoClient instead")
|
|
||||||
class KtorWriteStandardCrudRepo<ObjectType, IdType, InputValue> (
|
|
||||||
private val baseUrl: String,
|
|
||||||
private val unifiedRequester: UnifiedRequester,
|
|
||||||
private val objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
private val objectsNullableSerializer: KSerializer<ObjectType?>,
|
|
||||||
private val inputsSerializer: KSerializer<InputValue>,
|
|
||||||
private val idsSerializer: KSerializer<IdType>
|
|
||||||
) : WriteCRUDRepo<ObjectType, IdType, InputValue> {
|
|
||||||
private val listObjectsSerializer = ListSerializer(objectsSerializer)
|
|
||||||
private val listInputSerializer = ListSerializer(inputsSerializer)
|
|
||||||
private val listIdsSerializer = ListSerializer(idsSerializer)
|
|
||||||
private val inputUpdateSerializer = PairSerializer(
|
|
||||||
idsSerializer,
|
|
||||||
inputsSerializer
|
|
||||||
)
|
|
||||||
private val listInputUpdateSerializer = ListSerializer(inputUpdateSerializer)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
objectsSerializer: KSerializer<ObjectType>,
|
|
||||||
objectsSerializerNullable: KSerializer<ObjectType?>,
|
|
||||||
inputsSerializer: KSerializer<InputValue>,
|
|
||||||
idsSerializer: KSerializer<IdType>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (
|
|
||||||
baseUrl, UnifiedRequester(client, serialFormat), objectsSerializer, objectsSerializerNullable, inputsSerializer, idsSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override val newObjectsFlow: Flow<ObjectType> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, newObjectsFlowRouting),
|
|
||||||
deserializer = objectsSerializer
|
|
||||||
)
|
|
||||||
override val updatedObjectsFlow: Flow<ObjectType> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, updatedObjectsFlowRouting),
|
|
||||||
deserializer = objectsSerializer
|
|
||||||
)
|
|
||||||
override val deletedObjectsIdsFlow: Flow<IdType> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, deletedObjectsIdsFlowRouting),
|
|
||||||
deserializer = idsSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun create(values: List<InputValue>): List<ObjectType> = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(baseUrl, createRouting),
|
|
||||||
BodyPair(listInputSerializer, values),
|
|
||||||
listObjectsSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun update(id: IdType, value: InputValue): ObjectType? = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(baseUrl, updateRouting),
|
|
||||||
BodyPair(inputUpdateSerializer, id to value),
|
|
||||||
objectsNullableSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun update(values: List<UpdatedValuePair<IdType, InputValue>>): List<ObjectType> = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(baseUrl, updateManyRouting),
|
|
||||||
BodyPair(listInputUpdateSerializer, values),
|
|
||||||
listObjectsSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun deleteById(ids: List<IdType>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(baseUrl, deleteByIdRouting),
|
|
||||||
BodyPair(listIdsSerializer, ids),
|
|
||||||
Unit.serializer()
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,99 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.pagination.*
|
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValueRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.containsRoute
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.countRoute
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.keyParameterName
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.reversedParameterName
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
import kotlinx.serialization.builtins.serializer
|
|
||||||
|
|
||||||
@Deprecated("Replaced with KtorReadKeyValueRepoClient")
|
|
||||||
class KtorReadStandardKeyValueRepo<Key, Value> (
|
|
||||||
private val baseUrl: String,
|
|
||||||
private val unifiedRequester: UnifiedRequester,
|
|
||||||
private val keySerializer: KSerializer<Key>,
|
|
||||||
private val valueSerializer: KSerializer<Value>,
|
|
||||||
private val valueNullableSerializer: KSerializer<Value?>
|
|
||||||
) : ReadKeyValueRepo<Key, Value> {
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
keySerializer: KSerializer<Key>,
|
|
||||||
valueSerializer: KSerializer<Value>,
|
|
||||||
valueNullableSerializer: KSerializer<Value?>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (
|
|
||||||
baseUrl, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer, valueNullableSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun get(k: Key): Value? = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
getRoute,
|
|
||||||
mapOf(
|
|
||||||
keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, k)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
valueNullableSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun values(pagination: Pagination, reversed: Boolean): PaginationResult<Value> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
valuesRoute,
|
|
||||||
mapOf(
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
PaginationResult.serializer(valueSerializer)
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
keysRoute,
|
|
||||||
mapOf(
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
PaginationResult.serializer(keySerializer)
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean): PaginationResult<Key> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
keysRoute,
|
|
||||||
mapOf(
|
|
||||||
valueParameterName to unifiedRequester.encodeUrlQueryValue(valueSerializer, v),
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
PaginationResult.serializer(keySerializer)
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun contains(key: Key): Boolean = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
containsRoute,
|
|
||||||
mapOf(
|
|
||||||
keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, key)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Boolean.serializer(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun count(): Long = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
countRoute,
|
|
||||||
),
|
|
||||||
Long.serializer()
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
|
||||||
import dev.inmo.micro_utils.ktor.common.StandardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.ktor.common.standardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.*
|
|
||||||
|
|
||||||
@Deprecated("Replaced with KtorKeyValueRepoClient")
|
|
||||||
@Suppress("DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE")
|
|
||||||
class KtorStandartKeyValueRepo<K, V> (
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
unifiedRequester: UnifiedRequester,
|
|
||||||
keySerializer: KSerializer<K>,
|
|
||||||
valueSerializer: KSerializer<V>,
|
|
||||||
valueNullableSerializer: KSerializer<V?>
|
|
||||||
) : KeyValueRepo<K, V>,
|
|
||||||
ReadKeyValueRepo<K, V> by KtorReadStandardKeyValueRepo(
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
keySerializer,
|
|
||||||
valueSerializer,
|
|
||||||
valueNullableSerializer
|
|
||||||
),
|
|
||||||
WriteKeyValueRepo<K, V> by KtorWriteStandardKeyValueRepo(
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
keySerializer,
|
|
||||||
valueSerializer
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
client: HttpClient = HttpClient(),
|
|
||||||
keySerializer: KSerializer<K>,
|
|
||||||
valueSerializer: KSerializer<V>,
|
|
||||||
valueNullableSerializer: KSerializer<V?>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this(baseUrl, baseSubpart, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer, valueNullableSerializer)
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.key_value
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.repos.WriteKeyValueRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.key_value.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.*
|
|
||||||
|
|
||||||
@Deprecated("Replaced with KtorWriteKeyValueRepoClient")
|
|
||||||
class KtorWriteStandardKeyValueRepo<K, V> (
|
|
||||||
private var baseUrl: String,
|
|
||||||
private var unifiedRequester: UnifiedRequester,
|
|
||||||
private var keySerializer: KSerializer<K>,
|
|
||||||
private var valueSerializer: KSerializer<V>,
|
|
||||||
) : WriteKeyValueRepo<K, V> {
|
|
||||||
private val keyValueMapSerializer = MapSerializer(keySerializer, valueSerializer)
|
|
||||||
private val keysListSerializer = ListSerializer(keySerializer)
|
|
||||||
private val valuesListSerializer = ListSerializer(valueSerializer)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
keySerializer: KSerializer<K>,
|
|
||||||
valueSerializer: KSerializer<V>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (
|
|
||||||
baseUrl, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override val onNewValue: Flow<Pair<K, V>> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, onNewValueRoute),
|
|
||||||
deserializer = PairSerializer(keySerializer, valueSerializer)
|
|
||||||
)
|
|
||||||
|
|
||||||
override val onValueRemoved: Flow<K> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, onValueRemovedRoute),
|
|
||||||
deserializer = keySerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun set(toSet: Map<K, V>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
setRoute
|
|
||||||
),
|
|
||||||
BodyPair(keyValueMapSerializer, toSet),
|
|
||||||
Unit.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun unset(toUnset: List<K>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
unsetRoute,
|
|
||||||
),
|
|
||||||
BodyPair(keysListSerializer, toUnset),
|
|
||||||
Unit.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun unsetWithValues(toUnset: List<V>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
unsetWithValuesRoute,
|
|
||||||
),
|
|
||||||
BodyPair(valuesListSerializer, toUnset),
|
|
||||||
Unit.serializer()
|
|
||||||
)
|
|
||||||
}
|
|
@@ -1,38 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.UnifiedRequester
|
|
||||||
import dev.inmo.micro_utils.ktor.common.StandardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.ktor.common.standardKtorSerialFormat
|
|
||||||
import dev.inmo.micro_utils.repos.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
|
|
||||||
@Deprecated("Should be replaced with KtorKeyValuesRepoClient")
|
|
||||||
class KtorOneToManyKeyValueRepo<Key, Value>(
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
unifiedRequester: UnifiedRequester,
|
|
||||||
keySerializer: KSerializer<Key>,
|
|
||||||
valueSerializer: KSerializer<Value>,
|
|
||||||
) : KeyValuesRepo<Key, Value>,
|
|
||||||
ReadKeyValuesRepo<Key, Value> by KtorReadOneToManyKeyValueRepo<Key, Value> (
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
keySerializer,
|
|
||||||
valueSerializer,
|
|
||||||
),
|
|
||||||
WriteKeyValuesRepo<Key, Value> by KtorWriteOneToManyKeyValueRepo<Key, Value> (
|
|
||||||
"$baseUrl/$baseSubpart",
|
|
||||||
unifiedRequester,
|
|
||||||
keySerializer,
|
|
||||||
valueSerializer,
|
|
||||||
) {
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
baseSubpart: String,
|
|
||||||
client: HttpClient,
|
|
||||||
keySerializer: KSerializer<Key>,
|
|
||||||
valueSerializer: KSerializer<Value>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (baseUrl, baseSubpart, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer)
|
|
||||||
}
|
|
@@ -1,108 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.pagination.*
|
|
||||||
import dev.inmo.micro_utils.repos.ReadKeyValuesRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.keyParameterName
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.reversedParameterName
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.valueParameterName
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.serializer
|
|
||||||
|
|
||||||
@Deprecated("Should be replaced with KtorReadKeyValuesRepoClient")
|
|
||||||
class KtorReadOneToManyKeyValueRepo<Key, Value> (
|
|
||||||
private val baseUrl: String,
|
|
||||||
private val unifiedRequester: UnifiedRequester,
|
|
||||||
private val keySerializer: KSerializer<Key>,
|
|
||||||
private val valueSerializer: KSerializer<Value>
|
|
||||||
) : ReadKeyValuesRepo<Key, Value> {
|
|
||||||
private val paginationValueResultSerializer = PaginationResult.serializer(valueSerializer)
|
|
||||||
private val paginationKeyResultSerializer = PaginationResult.serializer(keySerializer)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
keySerializer: KSerializer<Key>,
|
|
||||||
valueSerializer: KSerializer<Value>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (baseUrl, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer)
|
|
||||||
|
|
||||||
override suspend fun get(k: Key, pagination: Pagination, reversed: Boolean): PaginationResult<Value> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
getRoute,
|
|
||||||
mapOf(
|
|
||||||
keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, k),
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
paginationValueResultSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun keys(pagination: Pagination, reversed: Boolean): PaginationResult<Key> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
keysRoute,
|
|
||||||
mapOf(
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
paginationKeyResultSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun keys(v: Value, pagination: Pagination, reversed: Boolean): PaginationResult<Key> = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
keysRoute,
|
|
||||||
mapOf(
|
|
||||||
valueParameterName to unifiedRequester.encodeUrlQueryValue(valueSerializer, v),
|
|
||||||
reversedParameterName to unifiedRequester.encodeUrlQueryValue(Boolean.serializer(), reversed)
|
|
||||||
) + pagination.asUrlQueryParts
|
|
||||||
),
|
|
||||||
paginationKeyResultSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun contains(k: Key): Boolean = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
containsByKeyRoute,
|
|
||||||
mapOf(keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, k))
|
|
||||||
),
|
|
||||||
Boolean.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun contains(k: Key, v: Value): Boolean = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
containsByKeyValueRoute,
|
|
||||||
mapOf(
|
|
||||||
keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, k),
|
|
||||||
valueParameterName to unifiedRequester.encodeUrlQueryValue(valueSerializer, v),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Boolean.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun count(k: Key): Long = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
countByKeyRoute,
|
|
||||||
mapOf(
|
|
||||||
keyParameterName to unifiedRequester.encodeUrlQueryValue(keySerializer, k)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Long.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun count(): Long = unifiedRequester.uniget(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
countRoute,
|
|
||||||
),
|
|
||||||
Long.serializer()
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
@@ -1,88 +0,0 @@
|
|||||||
package dev.inmo.micro_utils.repos.ktor.client.one_to_many
|
|
||||||
|
|
||||||
import dev.inmo.micro_utils.ktor.client.*
|
|
||||||
import dev.inmo.micro_utils.ktor.common.*
|
|
||||||
import dev.inmo.micro_utils.repos.WriteKeyValuesRepo
|
|
||||||
import dev.inmo.micro_utils.repos.ktor.common.one_to_many.*
|
|
||||||
import io.ktor.client.HttpClient
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.builtins.*
|
|
||||||
|
|
||||||
@Deprecated("Should be replaced with KtorWriteKeyValuesRepoClient")
|
|
||||||
class KtorWriteOneToManyKeyValueRepo<Key, Value> (
|
|
||||||
private val baseUrl: String,
|
|
||||||
private val unifiedRequester: UnifiedRequester,
|
|
||||||
private val keySerializer: KSerializer<Key>,
|
|
||||||
private val valueSerializer: KSerializer<Value>
|
|
||||||
) : WriteKeyValuesRepo<Key, Value> {
|
|
||||||
private val keyValueSerializer = PairSerializer(keySerializer, valueSerializer)
|
|
||||||
private val keyValueMapSerializer = MapSerializer(keySerializer, ListSerializer(valueSerializer))
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
baseUrl: String,
|
|
||||||
client: HttpClient,
|
|
||||||
keySerializer: KSerializer<Key>,
|
|
||||||
valueSerializer: KSerializer<Value>,
|
|
||||||
serialFormat: StandardKtorSerialFormat = standardKtorSerialFormat
|
|
||||||
) : this (
|
|
||||||
baseUrl, UnifiedRequester(client, serialFormat), keySerializer, valueSerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override val onNewValue: Flow<Pair<Key, Value>> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, onNewValueRoute),
|
|
||||||
deserializer = keyValueSerializer
|
|
||||||
)
|
|
||||||
override val onValueRemoved: Flow<Pair<Key, Value>> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, onValueRemovedRoute),
|
|
||||||
deserializer = keyValueSerializer
|
|
||||||
)
|
|
||||||
override val onDataCleared: Flow<Key> = unifiedRequester.createStandardWebsocketFlow(
|
|
||||||
buildStandardUrl(baseUrl, onDataClearedRoute),
|
|
||||||
deserializer = keySerializer
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun remove(toRemove: Map<Key, List<Value>>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
removeRoute,
|
|
||||||
),
|
|
||||||
BodyPair(keyValueMapSerializer, toRemove),
|
|
||||||
Unit.serializer(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun add(toAdd: Map<Key, List<Value>>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
addRoute,
|
|
||||||
),
|
|
||||||
BodyPair(keyValueMapSerializer, toAdd),
|
|
||||||
Unit.serializer(),
|
|
||||||
)
|
|
||||||
override suspend fun clear(k: Key) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
clearRoute,
|
|
||||||
),
|
|
||||||
BodyPair(keySerializer, k),
|
|
||||||
Unit.serializer(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun clearWithValue(v: Value) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
clearWithValueRoute,
|
|
||||||
),
|
|
||||||
BodyPair(valueSerializer, v),
|
|
||||||
Unit.serializer(),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun set(toSet: Map<Key, List<Value>>) = unifiedRequester.unipost(
|
|
||||||
buildStandardUrl(
|
|
||||||
baseUrl,
|
|
||||||
setRoute,
|
|
||||||
),
|
|
||||||
BodyPair(keyValueMapSerializer, toSet),
|
|
||||||
Unit.serializer(),
|
|
||||||
)
|
|
||||||
}
|
|
Reference in New Issue
Block a user