diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjString.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjString.kt index 9a90af3..f40b77c 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjString.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjString.kt @@ -41,12 +41,12 @@ data class ObjString(val value: String) : Obj() { } override suspend fun getAt(scope: Scope, index: Obj): Obj { - if( index is ObjInt) return ObjChar(value[index.toInt()]) - if( index is ObjRange) { - 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 { + if (index is ObjInt) return ObjChar(value[index.toInt()]) + if (index is ObjRange) { + 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 e = index.end.toInt() - if( index.isEndInclusive) e + 1 else e + if (index.isEndInclusive) e + 1 else e } return ObjString(value.substring(start, end)) } @@ -60,7 +60,7 @@ data class ObjString(val value: String) : Obj() { override suspend fun callOn(scope: Scope): Obj { return ObjString(this.value.sprintf(*scope.args .toKotlinList(scope) - .map { if( it == null) "null" else it } + .map { if (it == null) "null" else it } .toTypedArray())) } @@ -81,17 +81,24 @@ data class ObjString(val value: String) : Obj() { return value == other.value } + override suspend fun lynonType(): LynonType = LynonType.String + 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 { val type = object : ObjClass("String") { override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj = - ObjString( - decoder.unpackBinaryData().decodeToString() -// ?: scope.raiseError("unexpected end of data") - ) + if( lynonType == null ) + decoder.decodeCached { + ObjString(decoder.unpackBinaryData().decodeToString()) + } + else ObjString(decoder.unpackBinaryData().decodeToString()) }.apply { addFn("toInt") { ObjInt(thisAs().value.toLong()) diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt index 4d6a12f..a56112c 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonDecoder.kt @@ -41,7 +41,7 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe // todo: rewrite/remove? 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() diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonEncoder.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonEncoder.kt index c5cc44b..c681d5c 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonEncoder.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lynon/LynonEncoder.kt @@ -21,28 +21,29 @@ enum class LynonType(val objClass: ObjClass) { 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() suspend fun encodeCached(item: Any, packer: suspend LynonEncoder.() -> Unit) { - suspend fun serializeAndCache(key: Any=item) { - bout.putBit(0) - if( settings.shouldCache(item) ) - cache[key] = cache.size - packer() - } - - when(item) { - is Obj -> cache[item]?.let { cacheId -> + suspend fun serializeAndCache(key: Any = item) { + cache[key]?.let { cacheId -> val size = sizeInBits(cache.size) bout.putBit(1) 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 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. */ - suspend fun encodeAny(scope: Scope,value: Obj) { + suspend fun encodeAny(scope: Scope, value: Obj) { encodeCached(value) { val type = value.lynonType() putType(type) @@ -65,9 +66,7 @@ open class LynonEncoder(val bout: BitOutput,val settings: LynonSettings = LynonS } suspend fun encodeObj(scope: Scope, obj: Obj) { - encodeCached(obj) { obj.serialize(scope, this, null) - } } fun encodeBinaryData(data: ByteArray) { diff --git a/lynglib/src/jvmTest/kotlin/LynonTests.kt b/lynglib/src/jvmTest/kotlin/LynonTests.kt index 98be838..582f618 100644 --- a/lynglib/src/jvmTest/kotlin/LynonTests.kt +++ b/lynglib/src/jvmTest/kotlin/LynonTests.kt @@ -321,13 +321,14 @@ class LynonTests { testEncode(false) testEncode(1.22345) testEncode(-π) - + import lyng.time testEncode(Instant.now().truncateToSecond()) testEncode(Instant.now().truncateToMillisecond()) testEncode(Instant.now().truncateToMicrosecond()) - + testEncode("Hello, world".encodeUtf8()) + testEncode("Hello, world") """.trimIndent()) }