refs #35 hack to avoid cache clush for encodeAny and encode, double caching same object conflict. to refactor!

This commit is contained in:
Sergey Chernov 2025-07-19 14:12:41 +03:00
parent a9f65bdbe3
commit 405ff2ec2b
4 changed files with 36 additions and 29 deletions

View File

@ -81,17 +81,24 @@ data class ObjString(val value: String) : Obj() {
return value == other.value return value == other.value
} }
override suspend fun lynonType(): LynonType = LynonType.String
override suspend fun serialize(scope: Scope, encoder: LynonEncoder, lynonType: LynonType?) { override suspend fun serialize(scope: Scope, encoder: LynonEncoder, lynonType: LynonType?) {
if( lynonType == null )
encoder.encodeCached(this) { encoder.encodeBinaryData(value.encodeToByteArray()) }
else
encoder.encodeBinaryData(value.encodeToByteArray()) encoder.encodeBinaryData(value.encodeToByteArray())
} }
companion object { companion object {
val type = object : ObjClass("String") { val type = object : ObjClass("String") {
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj = override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj =
ObjString( if( lynonType == null )
decoder.unpackBinaryData().decodeToString() decoder.decodeCached {
// ?: scope.raiseError("unexpected end of data") ObjString(decoder.unpackBinaryData().decodeToString())
) }
else ObjString(decoder.unpackBinaryData().decodeToString())
}.apply { }.apply {
addFn("toInt") { addFn("toInt") {
ObjInt(thisAs<ObjString>().value.toLong()) ObjInt(thisAs<ObjString>().value.toLong())

View File

@ -41,7 +41,7 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe
// todo: rewrite/remove? // todo: rewrite/remove?
suspend fun unpackObject(scope: Scope, type: ObjClass): Obj { suspend fun unpackObject(scope: Scope, type: ObjClass): Obj {
return decodeCached { type.deserialize(scope, this, null) } return type.deserialize(scope, this, null)
} }
fun unpackBinaryData(): ByteArray = bin.decompress() fun unpackBinaryData(): ByteArray = bin.decompress()

View File

@ -28,21 +28,22 @@ open class LynonEncoder(val bout: BitOutput,val settings: LynonSettings = LynonS
suspend fun encodeCached(item: Any, packer: suspend LynonEncoder.() -> Unit) { suspend fun encodeCached(item: Any, packer: suspend LynonEncoder.() -> Unit) {
suspend fun serializeAndCache(key: Any = item) { suspend fun serializeAndCache(key: Any = item) {
cache[key]?.let { cacheId ->
val size = sizeInBits(cache.size)
bout.putBit(1)
bout.putBits(cacheId.toULong(), size)
} ?: run {
bout.putBit(0) bout.putBit(0)
if (settings.shouldCache(item)) if (settings.shouldCache(item))
cache[key] = cache.size cache[key] = cache.size
packer() packer()
} }
}
when (item) { when (item) {
is Obj -> cache[item]?.let { cacheId ->
val size = sizeInBits(cache.size)
bout.putBit(1)
bout.putBits(cacheId.toULong(), size)
} ?: serializeAndCache()
is ByteArray -> serializeAndCache(ByteChunk(item.asUByteArray())) is ByteArray -> serializeAndCache(ByteChunk(item.asUByteArray()))
is UByteArray -> serializeAndCache(ByteChunk(item)) is UByteArray -> serializeAndCache(ByteChunk(item))
else -> serializeAndCache(item)
} }
} }
@ -65,10 +66,8 @@ open class LynonEncoder(val bout: BitOutput,val settings: LynonSettings = LynonS
} }
suspend fun encodeObj(scope: Scope, obj: Obj) { suspend fun encodeObj(scope: Scope, obj: Obj) {
encodeCached(obj) {
obj.serialize(scope, this, null) obj.serialize(scope, this, null)
} }
}
fun encodeBinaryData(data: ByteArray) { fun encodeBinaryData(data: ByteArray) {
bout.compress(data) bout.compress(data)

View File

@ -328,6 +328,7 @@ class LynonTests {
testEncode(Instant.now().truncateToMicrosecond()) testEncode(Instant.now().truncateToMicrosecond())
testEncode("Hello, world".encodeUtf8()) testEncode("Hello, world".encodeUtf8())
testEncode("Hello, world")
""".trimIndent()) """.trimIndent())
} }