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 {
 | 
			
		||||
        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<ObjString>().value.toLong())
 | 
			
		||||
 | 
			
		||||
@ -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()
 | 
			
		||||
 | 
			
		||||
@ -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<Any, Int>()
 | 
			
		||||
 | 
			
		||||
    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) {
 | 
			
		||||
 | 
			
		||||
@ -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())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user