refs #35 hack to avoid cache clush for encodeAny and encode, double caching same object conflict. to refactor!
This commit is contained in:
parent
a9f65bdbe3
commit
405ff2ec2b
@ -41,12 +41,12 @@ data class ObjString(val value: String) : Obj() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
override suspend fun getAt(scope: Scope, index: Obj): Obj {
|
||||||
if( index is ObjInt) return ObjChar(value[index.toInt()])
|
if (index is ObjInt) return ObjChar(value[index.toInt()])
|
||||||
if( index is ObjRange) {
|
if (index is ObjRange) {
|
||||||
val start = if(index.start == null || index.start.isNull) 0 else index.start.toInt()
|
val start = if (index.start == null || index.start.isNull) 0 else index.start.toInt()
|
||||||
val end = if( index.end == null || index.end.isNull ) value.length else {
|
val end = if (index.end == null || index.end.isNull) value.length else {
|
||||||
val e = index.end.toInt()
|
val e = index.end.toInt()
|
||||||
if( index.isEndInclusive) e + 1 else e
|
if (index.isEndInclusive) e + 1 else e
|
||||||
}
|
}
|
||||||
return ObjString(value.substring(start, end))
|
return ObjString(value.substring(start, end))
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ data class ObjString(val value: String) : Obj() {
|
|||||||
override suspend fun callOn(scope: Scope): Obj {
|
override suspend fun callOn(scope: Scope): Obj {
|
||||||
return ObjString(this.value.sprintf(*scope.args
|
return ObjString(this.value.sprintf(*scope.args
|
||||||
.toKotlinList(scope)
|
.toKotlinList(scope)
|
||||||
.map { if( it == null) "null" else it }
|
.map { if (it == null) "null" else it }
|
||||||
.toTypedArray()))
|
.toTypedArray()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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?) {
|
||||||
encoder.encodeBinaryData(value.encodeToByteArray())
|
if( lynonType == null )
|
||||||
|
encoder.encodeCached(this) { encoder.encodeBinaryData(value.encodeToByteArray()) }
|
||||||
|
else
|
||||||
|
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())
|
||||||
|
@ -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()
|
||||||
|
@ -21,28 +21,29 @@ enum class LynonType(val objClass: ObjClass) {
|
|||||||
Other(Obj.rootObjectType);
|
Other(Obj.rootObjectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
open class LynonEncoder(val bout: BitOutput,val settings: LynonSettings = LynonSettings.default) {
|
open class LynonEncoder(val bout: BitOutput, val settings: LynonSettings = LynonSettings.default) {
|
||||||
|
|
||||||
val cache = mutableMapOf<Any, Int>()
|
val cache = mutableMapOf<Any, Int>()
|
||||||
|
|
||||||
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) {
|
||||||
bout.putBit(0)
|
cache[key]?.let { cacheId ->
|
||||||
if( settings.shouldCache(item) )
|
|
||||||
cache[key] = cache.size
|
|
||||||
packer()
|
|
||||||
}
|
|
||||||
|
|
||||||
when(item) {
|
|
||||||
is Obj -> cache[item]?.let { cacheId ->
|
|
||||||
val size = sizeInBits(cache.size)
|
val size = sizeInBits(cache.size)
|
||||||
bout.putBit(1)
|
bout.putBit(1)
|
||||||
bout.putBits(cacheId.toULong(), size)
|
bout.putBits(cacheId.toULong(), size)
|
||||||
} ?: serializeAndCache()
|
} ?: run {
|
||||||
|
bout.putBit(0)
|
||||||
|
if (settings.shouldCache(item))
|
||||||
|
cache[key] = cache.size
|
||||||
|
packer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when (item) {
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ open class LynonEncoder(val bout: BitOutput,val settings: LynonSettings = LynonS
|
|||||||
*
|
*
|
||||||
* Caching is used automatically.
|
* Caching is used automatically.
|
||||||
*/
|
*/
|
||||||
suspend fun encodeAny(scope: Scope,value: Obj) {
|
suspend fun encodeAny(scope: Scope, value: Obj) {
|
||||||
encodeCached(value) {
|
encodeCached(value) {
|
||||||
val type = value.lynonType()
|
val type = value.lynonType()
|
||||||
putType(type)
|
putType(type)
|
||||||
@ -65,9 +66,7 @@ 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) {
|
||||||
|
@ -321,13 +321,14 @@ class LynonTests {
|
|||||||
testEncode(false)
|
testEncode(false)
|
||||||
testEncode(1.22345)
|
testEncode(1.22345)
|
||||||
testEncode(-π)
|
testEncode(-π)
|
||||||
|
|
||||||
import lyng.time
|
import lyng.time
|
||||||
testEncode(Instant.now().truncateToSecond())
|
testEncode(Instant.now().truncateToSecond())
|
||||||
testEncode(Instant.now().truncateToMillisecond())
|
testEncode(Instant.now().truncateToMillisecond())
|
||||||
testEncode(Instant.now().truncateToMicrosecond())
|
testEncode(Instant.now().truncateToMicrosecond())
|
||||||
|
|
||||||
testEncode("Hello, world".encodeUtf8())
|
testEncode("Hello, world".encodeUtf8())
|
||||||
|
testEncode("Hello, world")
|
||||||
|
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user