maps serialization

This commit is contained in:
sergeych committed 2025-08-03 15:06:46 +03:00
1 parent 2339130241
commit 790cce0d24
5 files changed
+76 -27

No files matched your search

@@ -94,6 +94,15 @@ class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
return map == other.map
}
override suspend fun lynonType(): LynonType = LynonType.Map
override suspend fun serialize(scope: Scope, encoder: LynonEncoder, lynonType: LynonType?) {
val keys = map.keys.map { it.toObj() }
val values = map.values.map { it.toObj() }
encoder.encodeAnyList(scope, keys)
encoder.encodeAnyList(scope, values, fixedSize = true)
}
companion object {
suspend fun listToMap(scope: Scope, list: List<Obj>): MutableMap<Obj, Obj> {
@@ -121,6 +130,13 @@ class ObjMap(val map: MutableMap<Obj, Obj> = mutableMapOf()) : Obj() {
override suspend fun callOn(scope: Scope): Obj {
return ObjMap(listToMap(scope, scope.args.list))
}
override suspend fun deserialize(scope: Scope, decoder: LynonDecoder, lynonType: LynonType?): Obj {
val keys = decoder.decodeAnyList(scope)
val values = decoder.decodeAnyList(scope,fixedSize = keys.size)
if( keys.size != values.size) scope.raiseIllegalArgument("map keys and values should be same size")
return ObjMap(keys.zip(values).toMap().toMutableMap())
}
}.apply {
addFn("getOrNull") {
val key = args.firstAndOnly(pos)
@@ -56,7 +56,7 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe
} ?: scope.raiseSymbolNotFound("can't deserialize: not found type $className")
}
suspend fun decodeAnyList(scope: Scope): MutableList<Obj> {
suspend fun decodeAnyList(scope: Scope,fixedSize: Int?=null): MutableList<Obj> {
return if (bin.getBit() == 1) {
// homogenous
val type = LynonType.entries[getBitsAsInt(4)]
@@ -64,7 +64,7 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe
val objClass = if (type == LynonType.Other)
decodeClassObj(scope).also { println("detected class obj: $it") }
else type.objClass
val size = bin.unpackUnsigned().toInt()
val size = fixedSize ?: bin.unpackUnsigned().toInt()
println("detected homogenous list type $type, $size items")
for (i in 0..<size) {
list += decodeObject(scope, objClass, type).also {
@@ -73,7 +73,7 @@ open class LynonDecoder(val bin: BitInput, val settings: LynonSettings = LynonSe
}
list
} else {
val size = unpackUnsigned().toInt()
val size = fixedSize ?: unpackUnsigned().toInt()
(0..<size).map { decodeAny(scope) }.toMutableList()
}
}
@@ -108,30 +108,38 @@ open class LynonEncoder(val bout: BitOutput, val settings: LynonSettings = Lynon
* for each item.
*
*/
suspend fun encodeAnyList(scope: Scope, list: List<Obj>) {
val objClass = list[0].objClass
var type = list[0].lynonType()
var isHomogeneous = true
for (i in list.drop(1))
if (i.objClass != objClass) {
isHomogeneous = false
break
} else {
// same class but type might need generalization
type = type.generalizeTo(i.lynonType())
?: scope.raiseError("inner error: can't generalize lynon type $type to ${i.lynonType()}")
}
if (isHomogeneous) {
putBit(1)
putTypeRecord(scope, list[0], type)
encodeUnsigned(list.size.toULong())
for (i in list) encodeObject(scope, i, type)
} else {
suspend fun encodeAnyList(scope: Scope, list: List<Obj>,fixedSize: Boolean = false) {
if( list.isEmpty()) {
// any-typed, empty, save space
putBit(0)
encodeUnsigned(list.size.toULong())
for (i in list) encodeAny(scope, i)
encodeUnsigned(0u)
}
else {
val objClass = list[0].objClass
var type = list[0].lynonType()
var isHomogeneous = true
for (i in list.drop(1))
if (i.objClass != objClass) {
isHomogeneous = false
break
} else {
// same class but type might need generalization
type = type.generalizeTo(i.lynonType())
?: scope.raiseError("inner error: can't generalize lynon type $type to ${i.lynonType()}")
}
if (isHomogeneous) {
putBit(1)
putTypeRecord(scope, list[0], type)
if (!fixedSize)
encodeUnsigned(list.size.toULong())
for (i in list) encodeObject(scope, i, type)
} else {
putBit(0)
if (!fixedSize)
encodeUnsigned(list.size.toULong())
for (i in list) encodeAny(scope, i)
}
}
}
/**