fixe #2 effective Instant binary representation (truncates to millis though)
This commit is contained in:
1 parent
d0f29ce06f
commit
ee20bfdee7
7 files changed
+111
-4
No files matched your search
@@ -0,0 +1,34 @@
|
||||
package net.sergeych.bintools
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.serializer
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* Experimental interface for packing and unpacking binary formats.
|
||||
* Initial support intended for BiPack and BOSS to make it fast replaceable.
|
||||
* Also, JSON text version with binary converter is presented by default.
|
||||
*/
|
||||
interface MotherPacker {
|
||||
fun <T>pack(type: KType, payload: T): ByteArray
|
||||
fun <T>unpack(type: KType,packed: ByteArray): T
|
||||
}
|
||||
|
||||
inline fun <reified T>MotherPacker.pack(payload: T) = pack(typeOf<T>(), payload)
|
||||
inline fun <reified T>MotherPacker.unpack(packed: ByteArray) = unpack<T>(typeOf<T>(), packed)
|
||||
|
||||
class JsonPacker : MotherPacker {
|
||||
override fun <T> pack(type: KType, payload: T): ByteArray {
|
||||
return Json.encodeToString(serializer(type), payload).encodeToByteArray()
|
||||
}
|
||||
|
||||
override fun <T> unpack(type: KType, packed: ByteArray): T {
|
||||
return Json.decodeFromString<T>(
|
||||
serializer(type) as KSerializer<T>,
|
||||
packed.decodeToString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.sergeych.bipack
|
||||
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
@@ -15,6 +16,7 @@ import net.sergeych.bintools.*
|
||||
* Decode BiPack format. Note that it relies on [DataSource] so can throw [DataSource.EndOfData]
|
||||
* excpetion. Specific frames when used can throw [InvalidFrameException] and its derivatives.e
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class BipackDecoder(
|
||||
val input: DataSource, var elementsCount: Int = 0, val isCollection: Boolean = false,
|
||||
val hasFixedSize: Boolean = false,
|
||||
@@ -64,12 +66,18 @@ class BipackDecoder(
|
||||
return elementIndex++
|
||||
}
|
||||
|
||||
override fun <T> decodeSerializableValue(deserializer: DeserializationStrategy<T>): T {
|
||||
return if( deserializer == Instant.serializer() )
|
||||
Instant.fromEpochMilliseconds(decodeLong()) as T
|
||||
else
|
||||
super.decodeSerializableValue(deserializer)
|
||||
}
|
||||
override fun decodeSequentially(): Boolean = isCollection
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor): CompositeDecoder {
|
||||
val isCollection = descriptor.kind == StructureKind.LIST || descriptor.kind == StructureKind.MAP
|
||||
|
||||
var source = if (descriptor.annotations.any { it is CrcProtected })
|
||||
val source = if (descriptor.annotations.any { it is CrcProtected })
|
||||
CRC32Source(input)
|
||||
else
|
||||
input
|
||||
@@ -119,6 +127,7 @@ class BipackDecoder(
|
||||
fun <T> decode(source: DataSource, deserializer: DeserializationStrategy<T>): T =
|
||||
BipackDecoder(source).decodeSerializableValue(deserializer)
|
||||
|
||||
@Suppress("unused")
|
||||
inline fun <reified T> decode(source: DataSource): T = decode(source, serializer())
|
||||
inline fun <reified T> decode(source: ByteArray): T =
|
||||
decode(source.toDataSource(), serializer())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.sergeych.bipack
|
||||
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.serialization.SerializationStrategy
|
||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.AbstractEncoder
|
||||
@@ -76,6 +77,11 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <T> encodeSerializableValue(serializer: SerializationStrategy<T>, value: T) {
|
||||
if (value is Instant) encodeLong(value.toEpochMilliseconds())
|
||||
else super.encodeSerializableValue(serializer, value)
|
||||
}
|
||||
|
||||
override fun beginStructure(descriptor: SerialDescriptor): CompositeEncoder {
|
||||
// frame protection should start before anything else:
|
||||
val sink = if (descriptor.annotations.any { it is CrcProtected })
|
||||
@@ -115,6 +121,7 @@ class BipackEncoder(val output: DataSink) : AbstractEncoder() {
|
||||
ArrayDataSink().also { encode(serializer, value, it) }.toByteArray()
|
||||
|
||||
inline fun <reified T> encode(value: T) = encode(serializer(), value)
|
||||
@Suppress("unused")
|
||||
inline fun <reified T> encode(value: T, sink: DataSink) = encode(serializer(), value, sink)
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.sergeych.bipack
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.serializer
|
||||
import net.sergeych.bintools.MotherPacker
|
||||
import net.sergeych.bintools.toDataSource
|
||||
import kotlin.reflect.KType
|
||||
|
||||
class MotherBipack : MotherPacker {
|
||||
override fun <T> pack(type: KType, payload: T): ByteArray {
|
||||
return BipackEncoder.encode(serializer(type), payload)
|
||||
}
|
||||
|
||||
override fun <T> unpack(type: KType, packed: ByteArray): T {
|
||||
return BipackDecoder.decode<T>(packed.toDataSource(),
|
||||
serializer(type) as KSerializer<T>)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user