Skip to content

Commit

Permalink
add docs to new serialization/deserialization strategies and refactor…
Browse files Browse the repository at this point in the history
… several things
  • Loading branch information
InsanusMokrassar committed Aug 24, 2024
1 parent c03440c commit 6d90e57
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 26 deletions.
64 changes: 60 additions & 4 deletions tgbotapi.core/api/tgbotapi.core.api
Original file line number Diff line number Diff line change
Expand Up @@ -26132,11 +26132,8 @@ public abstract interface class dev/inmo/tgbotapi/types/update/abstracts/Update
public abstract fun getUpdateId-4k5XoGU ()J
}

public final class dev/inmo/tgbotapi/types/update/abstracts/UpdateDeserializationStrategy : kotlinx/serialization/DeserializationStrategy {
public final class dev/inmo/tgbotapi/types/update/abstracts/UpdateDeserializationStrategy : dev/inmo/tgbotapi/utils/serializers/CallbackCustomizableDeserializationStrategy {
public static final field INSTANCE Ldev/inmo/tgbotapi/types/update/abstracts/UpdateDeserializationStrategy;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ldev/inmo/tgbotapi/types/update/abstracts/Update;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
}

public final class dev/inmo/tgbotapi/types/update/abstracts/UpdateSerializerWithoutSerialization : kotlinx/serialization/KSerializer {
Expand Down Expand Up @@ -26835,3 +26832,62 @@ public final class dev/inmo/tgbotapi/utils/passport/PassportDataDecryptionHandli
public static synthetic fun doInDecryptionContextWithPKCS8Key$default (Ldev/inmo/tgbotapi/types/passport/PassportData;Ljava/security/PrivateKey;Ljava/lang/String;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/lang/Object;
}

public class dev/inmo/tgbotapi/utils/serializers/CallbackCustomizableDeserializationStrategy : dev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy {
public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun addUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getCustomDeserializationStrategies ()Ljava/util/Set;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
protected final fun get_customDeserializationStrategies ()Ljava/util/LinkedHashSet;
public fun removeUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
}

public class dev/inmo/tgbotapi/utils/serializers/CallbackCustomizableSerializationStrategy : dev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy {
public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun addUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
public fun getCustomSerializationStrategies ()Ljava/util/Set;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
protected final fun get_customSerializationStrategies ()Ljava/util/LinkedHashSet;
public fun removeUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}

public class dev/inmo/tgbotapi/utils/serializers/CallbacksCustomizableDeserializationStrategy : dev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy, dev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy, dev/inmo/tgbotapi/utils/serializers/CustomizableSerializer {
public fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Lkotlinx/serialization/descriptors/SerialDescriptor;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun addUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
public fun addUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public fun getCustomDeserializationStrategies ()Ljava/util/Set;
public fun getCustomSerializationStrategies ()Ljava/util/Set;
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public fun removeUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
public fun removeUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}

public abstract interface class dev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy : kotlinx/serialization/DeserializationStrategy {
public abstract fun addUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
public abstract fun getCustomDeserializationStrategies ()Ljava/util/Set;
public abstract fun removeUpdateDeserializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy;)Z
}

public abstract interface class dev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy$JsonDeserializerStrategy {
public abstract fun deserializeOrNull (Lkotlinx/serialization/json/JsonElement;)Ldev/inmo/micro_utils/common/Optional;
}

public abstract interface class dev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy : kotlinx/serialization/SerializationStrategy {
public abstract fun addUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
public abstract fun getCustomSerializationStrategies ()Ljava/util/Set;
public abstract fun removeUpdateSerializationStrategy (Ldev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy;)Z
}

public abstract interface class dev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy$CustomSerializerStrategy {
public abstract fun optionallySerialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)Z
}

public abstract interface class dev/inmo/tgbotapi/utils/serializers/CustomizableSerializer : dev/inmo/tgbotapi/utils/serializers/CustomizableDeserializationStrategy, dev/inmo/tgbotapi/utils/serializers/CustomizableSerializationStrategy, kotlinx/serialization/KSerializer {
}

Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ object UpdateSerializerWithoutSerialization : KSerializer<Update> {
* @see kotlinx.serialization.json.Json.parse
*/
object UpdateDeserializationStrategy : CallbackCustomizableDeserializationStrategy<Update>(
JsonElement.serializer().descriptor,
{ _, jsonElement ->
descriptor = JsonElement.serializer().descriptor,
defaultDeserializeCallback = { _, jsonElement ->
nonstrictJsonFormat.decodeFromJsonElement(
RawUpdate.serializer(),
jsonElement!!
).asUpdate(
jsonElement
)
},
{ it, _, jsonElement ->
fallbackDeserialization = { it, _, jsonElement ->
UnknownUpdate(
UpdateId((jsonElement as? JsonObject) ?.get(updateIdField) ?.jsonPrimitive ?.longOrNull ?: -1L),
jsonElement!!,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package dev.inmo.tgbotapi.utils.serializers

import dev.inmo.micro_utils.common.Optional
import dev.inmo.micro_utils.common.onPresented
import dev.inmo.tgbotapi.types.update.RawUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy.deserialize
Expand All @@ -11,7 +13,7 @@ import kotlinx.serialization.json.JsonElement

interface CustomizableDeserializationStrategy<T> : DeserializationStrategy<T> {
fun interface JsonDeserializerStrategy<T> {
fun deserializeOrNull(json: JsonElement): T?
fun deserializeOrNull(json: JsonElement): Optional<T>
}
/**
* Contains [JsonDeserializerStrategy] which will be used in [deserialize] method when standard
Expand Down Expand Up @@ -48,18 +50,27 @@ open class CallbackCustomizableDeserializationStrategy<T>(
override val customDeserializationStrategies: Set<CustomizableDeserializationStrategy.JsonDeserializerStrategy<T>>
get() = _customDeserializationStrategies.toSet()

/**
* Trying to get [JsonElement] if [decoder] is [JsonDecoder]. Then it will use [defaultDeserializeCallback] to
* deserialize data. In case if [defaultDeserializeCallback] will throw exception it will firstly try to deserialize
* data by strategies from [customDeserializationStrategies] and, if no one will return presented data in [Optional]
* it will use [fallbackDeserialization] as last option to deserialize data
*/
override fun deserialize(decoder: Decoder): T {
val jsonDecoder = decoder as? JsonDecoder
val jsonElement = jsonDecoder ?.decodeJsonElement()
return runCatching {
defaultDeserializeCallback(decoder, jsonElement)
}.onFailure {
return (jsonElement ?.let {
customDeserializationStrategies.firstNotNullOfOrNull {
it.deserializeOrNull(jsonElement)
}.getOrElse {
(jsonElement ?.let {
customDeserializationStrategies.forEach {
it.deserializeOrNull(jsonElement).onPresented {
return@deserialize it
}
}
}) ?: fallbackDeserialization(it, decoder, jsonElement)
}.getOrThrow()
})
fallbackDeserialization(it, decoder, jsonElement)
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ interface CustomizableSerializationStrategy<T> : SerializationStrategy<T> {
): Boolean
}

/**
* @param defaultSerializeCallback Default way of serialization
* @param fallbackSerialization Fallback way which will be used in case when [defaultSerializeCallback] and [customSerializationStrategies]
* were unable to serialize data
*/
open class CallbackCustomizableSerializationStrategy<T>(
override val descriptor: SerialDescriptor,
private val defaultSerializeCallback: (encoder: Encoder, value: T) -> Unit,
Expand All @@ -48,13 +53,23 @@ open class CallbackCustomizableSerializationStrategy<T>(
override val customSerializationStrategies: Set<CustomizableSerializationStrategy.CustomSerializerStrategy<T>>
get() = _customSerializationStrategies.toSet()

/**
* Trying to serialize data by [defaultSerializeCallback]. If [defaultSerializeCallback] it will try to use each
* strategy from [customSerializationStrategies] until one of them will return true (means, serialized). If there
* are no any strategy success serialization and [defaultSerializeCallback] thrown exception will be used
* [fallbackSerialization] callback
*/
override fun serialize(encoder: Encoder, value: T) {
runCatching {
defaultSerializeCallback(encoder, value)
}.onFailure {
customSerializationStrategies.firstOrNull() {
it.optionallySerialize(encoder, value)
} ?: fallbackSerialization(it, encoder, value)
}.getOrElse {
customSerializationStrategies.forEach {
if (it.optionallySerialize(encoder, value)) {
return@getOrElse
}
}
// next line will be called onle in case all
fallbackSerialization(it, encoder, value)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package dev.inmo.tgbotapi.utils.serializers

import dev.inmo.tgbotapi.types.update.RawUpdate
import dev.inmo.tgbotapi.types.update.abstracts.Update
import dev.inmo.tgbotapi.types.update.abstracts.UpdateDeserializationStrategy.deserialize
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.JsonDecoder
import kotlinx.serialization.json.JsonElement

interface CustomizableSerializer<T> : KSerializer<T>, CustomizableSerializationStrategy<T>, CustomizableDeserializationStrategy<T> {
}
interface CustomizableSerializer<T> : KSerializer<T>, CustomizableSerializationStrategy<T>, CustomizableDeserializationStrategy<T>

/**
* Combines [CallbackCustomizableSerializationStrategy] and [CallbackCustomizableDeserializationStrategy]
*/
open class CallbacksCustomizableDeserializationStrategy<T>(
override val descriptor: SerialDescriptor,
defaultDeserializeCallback: (decoder: Decoder, jsonElement: JsonElement?) -> T,
Expand Down

0 comments on commit 6d90e57

Please sign in to comment.