diff --git a/package.json b/package.json index 68711295..d80798d9 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "private": true, "version": "0.0.3", "description": "Kotlin multi-platform distributed database", - "dependencies": { - }, + "dependencies": {}, "devDependencies": { - "mocha": "6.0.0" + "mocha": "6.0.0", + "text-encoding": "^0.7.0" } -} \ No newline at end of file +} diff --git a/qbit-core/src/commonMain/kotlin/qbit/index/Index.kt b/qbit-core/src/commonMain/kotlin/qbit/index/Index.kt index 37b10188..5a26333d 100644 --- a/qbit-core/src/commonMain/kotlin/qbit/index/Index.kt +++ b/qbit-core/src/commonMain/kotlin/qbit/index/Index.kt @@ -41,6 +41,9 @@ internal val aveCmp = Comparator { o1, o2 -> } internal fun compareValues(v1: Any, v2: Any): Int { + if (v1 is Number && v2 is Number) { + return v1.toLong().compareTo(v2.toLong()) + } @Suppress("UNCHECKED_CAST") return (v1 as Comparable).compareTo(v2) } diff --git a/qbit-core/src/commonMain/kotlin/qbit/index/IndexDb.kt b/qbit-core/src/commonMain/kotlin/qbit/index/IndexDb.kt index 4bed7b39..e70fc1b1 100644 --- a/qbit-core/src/commonMain/kotlin/qbit/index/IndexDb.kt +++ b/qbit-core/src/commonMain/kotlin/qbit/index/IndexDb.kt @@ -138,7 +138,7 @@ class IndexDb( .map { val e: Map> = index.entityById(it)!! val name = e.getValue(name.name)[0] as String - val type = e.getValue(type.name)[0] as Byte + val type = (e.getValue(type.name)[0] as? Long)?.toByte() ?: e.getValue(type.name)[0] as Byte val unique = e[unique.name]?.firstOrNull() as? Boolean ?: false val list = e[list.name]?.firstOrNull() as? Boolean ?: false val attr = Attr(it, name, type, unique, list) diff --git a/qbit-core/src/commonMain/kotlin/qbit/serialization/Simple.kt b/qbit-core/src/commonMain/kotlin/qbit/serialization/Simple.kt index 9a1f9373..a7bb520b 100644 --- a/qbit-core/src/commonMain/kotlin/qbit/serialization/Simple.kt +++ b/qbit-core/src/commonMain/kotlin/qbit/serialization/Simple.kt @@ -41,10 +41,10 @@ object SimpleSerialization : Serialization { override fun deserializeNode(ins: Input): NodeVal { val parent1 = Hash(deserialize(ins, QBytes) as ByteArray) val parent2 = Hash(deserialize(ins, QBytes) as ByteArray) - val iid = deserialize(ins, QInt) as Int - val instanceBits = deserialize(ins, QByte) as Byte + val iid = deserialize(ins, QLong) as Long + val instanceBits = deserialize(ins, QLong) as Long val timestamp = deserialize(ins, QLong) as Long - val factsCount = deserialize(ins, QInt) as Int + val factsCount = deserialize(ins, QLong) as Long val facts = (1..factsCount).asSequence().map { val eid = deserialize(ins, QGid) as Gid val attr = deserialize(ins, QString) as String @@ -53,9 +53,9 @@ object SimpleSerialization : Serialization { } val nodeData = NodeData(facts.toList().toTypedArray()) return when { - parent1 == nullHash && parent2 == nullHash -> Root(null, DbUuid(Iid(iid, instanceBits)), timestamp, nodeData) - parent1 == nullHash && parent2 != nullHash -> Leaf(null, NodeRef(parent2), DbUuid(Iid(iid, instanceBits)), timestamp, nodeData) - parent1 != nullHash && parent2 != nullHash -> Merge(null, NodeRef(parent1), NodeRef(parent2), DbUuid(Iid(iid, instanceBits)), timestamp, nodeData) + parent1 == nullHash && parent2 == nullHash -> Root(null, DbUuid(Iid(iid.toInt(), instanceBits.toByte())), timestamp, nodeData) + parent1 == nullHash && parent2 != nullHash -> Leaf(null, NodeRef(parent2), DbUuid(Iid(iid.toInt(), instanceBits.toByte())), timestamp, nodeData) + parent1 != nullHash && parent2 != nullHash -> Merge(null, NodeRef(parent1), NodeRef(parent2), DbUuid(Iid(iid.toInt(), instanceBits.toByte())), timestamp, nodeData) else -> throw DeserializationException("Corrupted node data: parent1: $parent1, parent2: $parent2") } } @@ -66,19 +66,21 @@ object SimpleSerialization : Serialization { @OptIn(ExperimentalIoApi::class) internal fun serialize(vararg anys: Any): ByteArray { val bytes = anys.map { a -> - when (a) { - is Node<*> -> serialize(a.hash!!.bytes) - is DbUuid -> byteArray(serialize(a.iid.value), serialize(a.iid.instanceBits)) - is Boolean -> byteArray(QBoolean.code, if (a) 1.toByte() else 0.toByte()) - is Byte -> byteArray(QByte.code, a) - is Int -> byteArray(QInt.code, serializeInt(a)) - is Long -> byteArray(QLong.code, serializeLong(a)) - is String -> byteArray(QString.code, byteArray(a)) - is NodeData -> byteArray(serialize(a.trxes.size), *a.trxes.map { serialize(it) }.toTypedArray()) - is Eav -> serialize(a.gid, a.attr, a.value) - is Gid -> byteArray(QGid.code, serializeLong(a.value())) - is ByteArray -> byteArray(QBytes.code, serializeInt(a.size), a) - else -> throw AssertionError("Should never happen, a is $a") + if (a as? Number != null) { + byteArray(QLong.code, serializeLong(a.toLong())) + } else { + when (a) { + is Node<*> -> serialize(a.hash!!.bytes) + is DbUuid -> byteArray(serialize(a.iid.value), serialize(a.iid.instanceBits)) + is Boolean -> byteArray(QBoolean.code, if (a) 1.toByte() else 0.toByte()) + is Number -> byteArray(QLong.code, a) + is String -> byteArray(QString.code, byteArray(a)) + is NodeData -> byteArray(serialize(a.trxes.size), *a.trxes.map { serialize(it) }.toTypedArray()) + is Eav -> serialize(a.gid, a.attr, a.value) + is Gid -> byteArray(QGid.code, serializeLong(a.value())) + is ByteArray -> byteArray(QBytes.code, serializeLong(a.size.toLong()), a) + else -> throw AssertionError("Should never happen, a is $a: ${a::class}") + } } } return byteArray(*bytes.toTypedArray()) @@ -86,7 +88,7 @@ internal fun serialize(vararg anys: Any): ByteArray { @ExperimentalIoApi private fun byteArray(str: String): ByteArray = - byteArray(serializeInt(str.encodeToUtf8().size), str.encodeToUtf8()) + byteArray(serializeLong(str.encodeToUtf8().size.toLong()), str.encodeToUtf8()) @OptIn(ExperimentalIoApi::class) private fun encodeToUtf8(c: Char): ByteArray = @@ -161,16 +163,14 @@ internal fun deserialize(ins: Input): Any { private fun readMark(ins: Input, expectedMark: DataType): Any { return when (expectedMark) { QBoolean -> (ins.readByte() == 1.toByte()) as T - QByte -> ins.readByte() as T - QInt -> readInt(ins) as T - QLong -> readLong(ins) as T + QByte, QInt, QLong -> readLong(ins) as T - QBytes -> readInt(ins).let { count -> - readBytes(ins, count) as T + QBytes -> readLong(ins).let { count -> + readBytes(ins, count.toInt()) as T } - QString -> readInt(ins).let { count -> - readBytes(ins, count).decodeUtf8() as T + QString -> readLong(ins).let { count -> + readBytes(ins, count.toInt()).decodeUtf8() as T } QGid -> Gid(readLong(ins)) as T QRef -> throw AssertionError("Should never happen") diff --git a/qbit-core/src/commonTest/kotlin/qbit/serialization/SimpleSerializationTest.kt b/qbit-core/src/commonTest/kotlin/qbit/serialization/SimpleSerializationTest.kt index ba66e21a..54e729d3 100644 --- a/qbit-core/src/commonTest/kotlin/qbit/serialization/SimpleSerializationTest.kt +++ b/qbit-core/src/commonTest/kotlin/qbit/serialization/SimpleSerializationTest.kt @@ -13,33 +13,15 @@ import qbit.platform.currentTimeMillis import qbit.random import qbit.randomBytes import qbit.randomString -import kotlin.js.JsName import kotlin.test.* @OptIn(ExperimentalIoApi::class) -@Ignore class SimpleSerializationTest { private val intValues: List = listOf(0, 1, -1, Int.MAX_VALUE, Int.MIN_VALUE, Byte.MAX_VALUE.toInt(), Byte.MIN_VALUE.toInt()) private val longValues: List = listOf(Long.MAX_VALUE, Long.MIN_VALUE, *(intValues.map { it.toLong() }.toTypedArray())) - @JsName("Test_byte_serializatoin") - @Test - fun `Test byte serializatoin`() { - // Given a byte - val byte: Byte = 1.toByte() - println("$byte: ${byte::class}") - - // When it is serialized - val serial = serialize(byte) - - // Then result is [, ] - assertEquals(QByte.code, serial[0]) - assertEquals(2, serial.size) - assertEquals(byte, serial[1]) - } - @Test fun testReadLong() { testValues(longValues, ::serializeLong, ::readLong) @@ -55,6 +37,7 @@ class SimpleSerializationTest { testValues(longValues, { serialize(it) }, { deserialize(it, QLong) as Long }) } + @Ignore @Test fun testMaxInt() { assertEquals(Int.MAX_VALUE, deserialize(serialize(Int.MAX_VALUE).asInput(), QInt)) @@ -72,6 +55,7 @@ class SimpleSerializationTest { assertArrayEquals(byteArrayOf(-128, 0, 0, 0), minRes) } + @Ignore @Test fun testDeserializeInt() { testValues(intValues, { serialize(it) }, { deserialize(it, QInt) as Int }) @@ -89,6 +73,7 @@ class SimpleSerializationTest { assertEquals(false, deserialize(serialize(false).asInput(), QBoolean)) } + @Ignore @Test fun testN() { assertEquals(nullHash, Hash(deserialize(serialize(NodeRef(nullHash)).asInput(), QBytes) as ByteArray)) @@ -112,7 +97,7 @@ class SimpleSerializationTest { ) assertArrayEquals(random, deserialize(serialize(random).asInput(), QBytes) as ByteArray) - val twoBytes = byteArrayOf(QBytes.code, 0, 0, 0, 3, 0, 0) + val twoBytes = byteArrayOf(QBytes.code, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0) try { deserialize(twoBytes.asInput(), QBytes) fail("eof error expected") @@ -140,13 +125,14 @@ class SimpleSerializationTest { fun testRoot() { val iid = Iid(1, 4) val root = Root(null, DbUuid(iid), currentTimeMillis(), NodeData(arrayOf(Eav(Gid(iid, 1), "test", 0)))) - val res = SimpleSerialization.deserializeNode(SimpleSerialization.serializeNode(root).asInput()) + val serializeNode = SimpleSerialization.serializeNode(root) + val res = SimpleSerialization.deserializeNode(serializeNode.asInput()) assertEquals(root.hash, res.hash) assertEquals(root.source, res.source) assertEquals(root.timestamp, res.timestamp) assertEquals(root.data.trxes[0].gid, res.data.trxes[0].gid) assertEquals(root.data.trxes[0].attr, res.data.trxes[0].attr) - assertEquals(root.data.trxes[0].value, res.data.trxes[0].value) + assertEquals((root.data.trxes[0].value as Int).toLong(), res.data.trxes[0].value) } @Test @@ -165,7 +151,7 @@ class SimpleSerializationTest { assertEquals(root.timestamp, res.timestamp) assertEquals(root.data.trxes[0].gid, res.data.trxes[0].gid) assertEquals(root.data.trxes[0].attr, res.data.trxes[0].attr) - assertEquals(root.data.trxes[0].value, res.data.trxes[0].value) + assertEquals((root.data.trxes[0].value as Int).toLong(), res.data.trxes[0].value) } @Test @@ -184,7 +170,7 @@ class SimpleSerializationTest { assertEquals(root.timestamp, res.timestamp) assertEquals(root.data.trxes[0].gid, res.data.trxes[0].gid) assertEquals(root.data.trxes[0].attr, res.data.trxes[0].attr) - assertEquals(root.data.trxes[0].value, res.data.trxes[0].value) + assertEquals((root.data.trxes[0].value as Int).toLong(), res.data.trxes[0].value) } } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 45da2d91..032379e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1324,6 +1324,11 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +text-encoding@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.7.0.tgz#f895e836e45990624086601798ea98e8f36ee643" + integrity sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA== + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"