diff --git a/examples/src/main/kotlin/io.zenoh/ZBytes.kt b/examples/src/main/kotlin/io.zenoh/ZBytes.kt index 7aace67a8..37cf5724b 100644 --- a/examples/src/main/kotlin/io.zenoh/ZBytes.kt +++ b/examples/src/main/kotlin/io.zenoh/ZBytes.kt @@ -1,6 +1,5 @@ package io.zenoh -import io.zenoh.bytes.* import io.zenoh.ext.zDeserialize import io.zenoh.ext.zSerialize @@ -12,126 +11,74 @@ fun main() { /** Numeric: byte, short, int, float, double */ val intInput = 1234 - var payload = ZBytes.from(intInput) - var intOutput = zDeserialize(payload).getOrThrow() - check(intInput == intOutput) - - // Alternatively you can serialize into the type. - payload = zSerialize(intInput).getOrThrow() - intOutput = zDeserialize(payload).getOrThrow() - check(intInput == intOutput) - - // Alternatively, `Numeric.into()`: ZBytes can be used - payload = intInput.into() - intOutput = zDeserialize(payload).getOrThrow() + var payload = zSerialize(intInput).getOrThrow() + val intOutput = zDeserialize(payload).getOrThrow() check(intInput == intOutput) // Another example with float val floatInput = 3.1415f - payload = ZBytes.from(floatInput) + payload = zSerialize(floatInput).getOrThrow() val floatOutput = zDeserialize(payload).getOrThrow() check(floatInput == floatOutput) /** String serialization and deserialization. */ val stringInput = "example" - payload = ZBytes.from(stringInput) - // Alternatively, you can also call `String.into()` to convert - // a string into a ZBytes object: - // payload = stringInput.into() + payload = zSerialize(stringInput).getOrThrow() var stringOutput = zDeserialize(payload).getOrThrow() check(stringInput == stringOutput) - // For the case of strings, ZBytes::toString() is equivalent: - stringOutput = payload.toString() - check(stringInput == stringOutput) - /** ByteArray serialization and deserialization. */ val byteArrayInput = "example".toByteArray() - payload = ZBytes.from(byteArrayInput) // Equivalent to `byteArrayInput.into()` - var byteArrayOutput = zDeserialize(payload).getOrThrow() - check(byteArrayInput.contentEquals(byteArrayOutput)) - // Alternatively, we can directly access the bytes of property of ZBytes: - byteArrayOutput = payload.toByteArray() + payload = zSerialize(byteArrayInput).getOrThrow() + val byteArrayOutput = zDeserialize(payload).getOrThrow() check(byteArrayInput.contentEquals(byteArrayOutput)) - /** List serialization and deserialization. + /** + * List serialization and deserialization. * - * Supported types: String, ByteArray, ZBytes, Byte, Short, Int, Long, Float and Double. + * Supported types: String, ByteArray, Byte, Short, Int, Long, Float and Double. */ val inputList = listOf("sample1", "sample2", "sample3") payload = zSerialize(inputList).getOrThrow() val outputList = zDeserialize>(payload).getOrThrow() check(inputList == outputList) - val inputListZBytes = inputList.map { value -> value.into() } - payload = zSerialize(inputListZBytes).getOrThrow() - val outputListZBytes = zDeserialize>(payload).getOrThrow() - check(inputListZBytes == outputListZBytes) + val inputListInt = listOf(1, 2, 3) + payload = zSerialize(inputListInt).getOrThrow() + val outputListInt = zDeserialize>(payload).getOrThrow() + check(inputListInt == outputListInt) val inputListByteArray = inputList.map { value -> value.toByteArray() } payload = zSerialize(inputListByteArray).getOrThrow() val outputListByteArray = zDeserialize>(payload).getOrThrow() check(compareByteArrayLists(inputListByteArray, outputListByteArray)) + /** Nested lists */ + val nestedList = listOf(listOf(1, 2, 3)) + payload = zSerialize(nestedList).getOrThrow() + val outputNestedList = zDeserialize>>(payload).getOrThrow() + check(nestedList == outputNestedList) + + /** Combined types */ + val combinedList = listOf(mapOf("a" to 1, "b" to 2)) + payload = zSerialize(combinedList).getOrThrow() + val outputCombinedList = zDeserialize>>(payload).getOrThrow() + check(combinedList == outputCombinedList) + /** * Map serialization and deserialization. * - * Maps with the following Type combinations are supported: String, ByteArray, ZBytes, Byte, Short, Int, Long, Float and Double. + * Maps with the following Type combinations are supported: String, ByteArray, Byte, Short, Int, Long, Float and Double. */ val inputMap = mapOf("key1" to "value1", "key2" to "value2", "key3" to "value3") payload = zSerialize(inputMap).getOrThrow() val outputMap = zDeserialize>(payload).getOrThrow() check(inputMap == outputMap) - val combinedInputMap = mapOf("key1" to ZBytes.from("zbytes1"), "key2" to ZBytes.from("zbytes2")) + val combinedInputMap = mapOf("key1" to 1, "key2" to 2) payload = zSerialize(combinedInputMap).getOrThrow() - val combinedOutputMap = zDeserialize>(payload).getOrThrow() + val combinedOutputMap = zDeserialize>(payload).getOrThrow() check(combinedInputMap == combinedOutputMap) - - /********************************************* - * Custom serialization and deserialization. * - *********************************************/ - - /** - * The examples below use [MyZBytes], an example class that implements the [IntoZBytes] interface. - * - * In order for the serialization to be successful on a custom class, - * the class itself must override the `into(): ZBytes` function. - * - * Regarding deserialization for custom objects, for the time being (this API will be expanded to - * provide further utilities) you need to manually convert the ZBytes into the type you want. - * - * @see MyZBytes - */ - val inputMyZBytes = MyZBytes("example") - payload = zSerialize(inputMyZBytes).getOrThrow() - val outputMyZBytes = MyZBytes.from(payload) - check(inputMyZBytes == outputMyZBytes) - - /** List of MyZBytes. */ - val inputListMyZBytes = inputList.map { value -> MyZBytes(value) } - payload = zSerialize>(inputListMyZBytes).getOrThrow() - val outputListMyZBytes = zDeserialize>(payload).getOrThrow().map { zbytes -> MyZBytes.from(zbytes) } - check(inputListMyZBytes == outputListMyZBytes) - - /** Map of MyZBytes. */ - val inputMapMyZBytes = inputMap.map { (k, v) -> MyZBytes(k) to MyZBytes(v) }.toMap() - payload = zSerialize>(inputMapMyZBytes).getOrThrow() - val outputMapMyZBytes = zDeserialize>(payload).getOrThrow() - .map { (key, value) -> MyZBytes.from(key) to MyZBytes.from(value) }.toMap() - check(inputMapMyZBytes == outputMapMyZBytes) - -} - -data class MyZBytes(val content: String) : IntoZBytes { - - override fun into(): ZBytes = content.into() - - companion object { - fun from(zbytes: ZBytes): MyZBytes { - return MyZBytes(zbytes.toString()) - } - } } /** Utils for this example. */ diff --git a/examples/src/main/kotlin/io.zenoh/ZGet.kt b/examples/src/main/kotlin/io.zenoh/ZGet.kt index 29292f6d1..6951dcaf9 100644 --- a/examples/src/main/kotlin/io.zenoh/ZGet.kt +++ b/examples/src/main/kotlin/io.zenoh/ZGet.kt @@ -17,8 +17,8 @@ package io.zenoh import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.types.long +import io.zenoh.bytes.ZBytes import io.zenoh.sample.SampleKind -import io.zenoh.bytes.into import io.zenoh.query.QueryTarget import io.zenoh.query.intoSelector import kotlinx.coroutines.channels.Channel @@ -39,9 +39,9 @@ class ZGet(private val emptyArgs: Boolean) : CliktCommand( selector.intoSelector().onSuccess { selector -> session.get(selector, channel = Channel(), - payload = payload?.into(), + payload = payload?.let { ZBytes.from(it) }, target = target?.let { QueryTarget.valueOf(it.uppercase()) } ?: QueryTarget.BEST_MATCHING, - attachment = attachment?.into(), + attachment = attachment?.let { ZBytes.from(it) }, timeout = Duration.ofMillis(timeout)) .onSuccess { channelReceiver -> runBlocking { diff --git a/examples/src/main/kotlin/io.zenoh/ZPub.kt b/examples/src/main/kotlin/io.zenoh/ZPub.kt index 994aedf05..ab00354f4 100644 --- a/examples/src/main/kotlin/io.zenoh/ZPub.kt +++ b/examples/src/main/kotlin/io.zenoh/ZPub.kt @@ -16,8 +16,8 @@ package io.zenoh import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.* +import io.zenoh.bytes.ZBytes import io.zenoh.keyexpr.intoKeyExpr -import io.zenoh.bytes.into class ZPub(private val emptyArgs: Boolean) : CliktCommand( help = "Zenoh Pub example" @@ -45,8 +45,8 @@ class ZPub(private val emptyArgs: Boolean) : CliktCommand( "Putting Data ('$keyExpr': '$payload')..." ) attachment?.let { - pub.put(payload, attachment = it.into()) - } ?: let { pub.put(payload) } + pub.put(ZBytes.from(payload), attachment = ZBytes.from(it) ) + } ?: let { pub.put(ZBytes.from(payload)) } idx++ } } diff --git a/examples/src/main/kotlin/io.zenoh/ZPubThr.kt b/examples/src/main/kotlin/io.zenoh/ZPubThr.kt index 8dccbbb4d..c2342624f 100644 --- a/examples/src/main/kotlin/io.zenoh/ZPubThr.kt +++ b/examples/src/main/kotlin/io.zenoh/ZPubThr.kt @@ -21,11 +21,11 @@ import com.github.ajalt.clikt.parameters.options.* import com.github.ajalt.clikt.parameters.types.boolean import com.github.ajalt.clikt.parameters.types.int import com.github.ajalt.clikt.parameters.types.ulong +import io.zenoh.bytes.ZBytes import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.qos.CongestionControl import io.zenoh.qos.Priority import io.zenoh.qos.QoS -import io.zenoh.bytes.into class ZPubThr(private val emptyArgs: Boolean) : CliktCommand( help = "Zenoh Throughput example" @@ -38,7 +38,7 @@ class ZPubThr(private val emptyArgs: Boolean) : CliktCommand( for (i in 0.. keyExpr.use { - session.put(keyExpr, value.into(), attachment = attachment?.into()) + session.put(keyExpr, ZBytes.from(value), attachment = attachment?.let { ZBytes.from(it) }) .onSuccess { println("Putting Data ('$keyExpr': '$value')...") } } } diff --git a/examples/src/main/kotlin/io.zenoh/ZQueryable.kt b/examples/src/main/kotlin/io.zenoh/ZQueryable.kt index b96c20713..630bb0e67 100644 --- a/examples/src/main/kotlin/io.zenoh/ZQueryable.kt +++ b/examples/src/main/kotlin/io.zenoh/ZQueryable.kt @@ -16,8 +16,8 @@ package io.zenoh import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.* +import io.zenoh.bytes.ZBytes import io.zenoh.keyexpr.intoKeyExpr -import io.zenoh.bytes.into import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.runBlocking import org.apache.commons.net.ntp.TimeStamp @@ -42,7 +42,7 @@ class ZQueryable(private val emptyArgs: Boolean) : CliktCommand( println(">> [Queryable] Received Query '${query.selector}' $valueInfo") query.reply( keyExpr, - payload = value.into(), + payload = ZBytes.from(value), timestamp = TimeStamp.getCurrentTime() ).onFailure { println(">> [Queryable ] Error sending reply: $it") } } diff --git a/examples/src/main/kotlin/io.zenoh/ZSub.kt b/examples/src/main/kotlin/io.zenoh/ZSub.kt index 4df36998e..43c742382 100644 --- a/examples/src/main/kotlin/io.zenoh/ZSub.kt +++ b/examples/src/main/kotlin/io.zenoh/ZSub.kt @@ -16,6 +16,7 @@ package io.zenoh import com.github.ajalt.clikt.core.CliktCommand import com.github.ajalt.clikt.parameters.options.* +import io.zenoh.ext.zDeserialize import io.zenoh.keyexpr.intoKeyExpr import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.runBlocking diff --git a/zenoh-jni/Cargo.lock b/zenoh-jni/Cargo.lock index fa2712805..d4bdd7738 100644 --- a/zenoh-jni/Cargo.lock +++ b/zenoh-jni/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -110,7 +110,7 @@ checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "synstructure", ] @@ -122,7 +122,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -133,13 +133,13 @@ checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -239,9 +239,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cache-padded" @@ -251,9 +251,9 @@ checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" [[package]] name = "cc" -version = "1.1.20" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bcde016d64c21da4be18b655631e5ab6d3107607e71a73a9f53eb48aae23fb" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "shlex", ] @@ -477,7 +477,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -582,9 +582,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -592,15 +592,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -609,38 +609,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -679,9 +679,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "git-version" @@ -700,7 +700,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -719,6 +719,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -765,9 +771,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "humantime" @@ -797,12 +803,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.15.0", ] [[package]] @@ -876,9 +882,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.70" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -929,9 +935,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" [[package]] name = "libloading" @@ -1148,9 +1154,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] @@ -1166,9 +1172,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" @@ -1218,7 +1224,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.4", + "redox_syscall 0.5.7", "smallvec", "windows-targets 0.52.6", ] @@ -1246,9 +1252,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.12" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" +checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", "thiserror", @@ -1257,9 +1263,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.12" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" +checksum = "d214365f632b123a47fd913301e14c946c61d1c183ee245fa76eb752e59a02dd" dependencies = [ "pest", "pest_generator", @@ -1267,22 +1273,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.12" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" +checksum = "eb55586734301717aea2ac313f50b2eb8f60d2fc3dc01d190eefa2e625f60c4e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] name = "pest_meta" -version = "2.7.12" +version = "2.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" +checksum = "b75da2a70cf4d9cb76833c990ac9cd3923c9a8905a8929789ce347c84564d03d" dependencies = [ "once_cell", "pest", @@ -1296,7 +1302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.5.0", + "indexmap 2.6.0", ] [[package]] @@ -1329,7 +1335,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1343,22 +1349,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1443,9 +1449,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" dependencies = [ "unicode-ident", ] @@ -1549,9 +1555,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] @@ -1569,14 +1575,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -1590,13 +1596,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -1607,9 +1613,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ring" @@ -1700,9 +1706,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.13" +version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" +checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ "log", "once_cell", @@ -1728,19 +1734,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" +checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" [[package]] name = "rustls-platform-verifier" @@ -1797,9 +1802,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -1826,7 +1831,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1861,9 +1866,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -1892,7 +1897,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1903,7 +1908,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -1924,7 +1929,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.5.0", + "indexmap 2.6.0", "itoa", "ryu", "serde", @@ -2078,9 +2083,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2095,7 +2100,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2115,22 +2120,22 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2222,7 +2227,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2283,7 +2288,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] @@ -2374,9 +2379,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "uhlc" @@ -2394,9 +2399,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -2406,18 +2411,18 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unsafe-libyaml" @@ -2461,9 +2466,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom", ] @@ -2528,9 +2533,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -2539,24 +2544,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2564,28 +2569,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.93" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "webpki-roots" -version = "0.26.5" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -2855,7 +2860,7 @@ dependencies = [ [[package]] name = "zenoh" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "ahash", "async-trait", @@ -2901,7 +2906,7 @@ dependencies = [ [[package]] name = "zenoh-buffers" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "zenoh-collections", ] @@ -2909,7 +2914,7 @@ dependencies = [ [[package]] name = "zenoh-codec" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "tracing", "uhlc", @@ -2920,12 +2925,12 @@ dependencies = [ [[package]] name = "zenoh-collections" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" [[package]] name = "zenoh-config" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "json5", "num_cpus", @@ -2946,7 +2951,7 @@ dependencies = [ [[package]] name = "zenoh-core" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "lazy_static", "tokio", @@ -2957,7 +2962,7 @@ dependencies = [ [[package]] name = "zenoh-crypto" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "aes", "hmac", @@ -2970,7 +2975,7 @@ dependencies = [ [[package]] name = "zenoh-ext" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "bincode", "flume 0.11.0", @@ -2987,7 +2992,7 @@ dependencies = [ [[package]] name = "zenoh-keyexpr" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "hashbrown 0.14.5", "keyed-set", @@ -3001,7 +3006,7 @@ dependencies = [ [[package]] name = "zenoh-link" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "zenoh-config", "zenoh-link-commons", @@ -3018,7 +3023,7 @@ dependencies = [ [[package]] name = "zenoh-link-commons" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "flume 0.11.0", @@ -3041,7 +3046,7 @@ dependencies = [ [[package]] name = "zenoh-link-quic" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "base64 0.22.1", @@ -3066,7 +3071,7 @@ dependencies = [ [[package]] name = "zenoh-link-tcp" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "socket2", @@ -3083,7 +3088,7 @@ dependencies = [ [[package]] name = "zenoh-link-tls" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "base64 0.22.1", @@ -3110,7 +3115,7 @@ dependencies = [ [[package]] name = "zenoh-link-udp" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "socket2", @@ -3129,7 +3134,7 @@ dependencies = [ [[package]] name = "zenoh-link-unixsock_stream" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "nix", @@ -3147,7 +3152,7 @@ dependencies = [ [[package]] name = "zenoh-link-ws" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "futures-util", @@ -3167,18 +3172,18 @@ dependencies = [ [[package]] name = "zenoh-macros" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", "zenoh-keyexpr", ] [[package]] name = "zenoh-plugin-trait" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "git-version", "libloading", @@ -3194,7 +3199,7 @@ dependencies = [ [[package]] name = "zenoh-protocol" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "const_format", "rand", @@ -3208,7 +3213,7 @@ dependencies = [ [[package]] name = "zenoh-result" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "anyhow", ] @@ -3216,7 +3221,7 @@ dependencies = [ [[package]] name = "zenoh-runtime" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "lazy_static", "ron", @@ -3229,7 +3234,7 @@ dependencies = [ [[package]] name = "zenoh-sync" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "event-listener", "futures", @@ -3242,7 +3247,7 @@ dependencies = [ [[package]] name = "zenoh-task" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "futures", "tokio", @@ -3255,7 +3260,7 @@ dependencies = [ [[package]] name = "zenoh-transport" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "crossbeam-utils", @@ -3288,7 +3293,7 @@ dependencies = [ [[package]] name = "zenoh-util" version = "1.0.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#4fbe04ab8d27f4792da9d2460bf120694aec2877" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#363e817ca511c764eb38212e2c4957f34a6c879e" dependencies = [ "async-trait", "const_format", @@ -3346,7 +3351,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.77", + "syn 2.0.79", ] [[package]] diff --git a/zenoh-jni/Cargo.toml b/zenoh-jni/Cargo.toml index a38606df3..08246e283 100644 --- a/zenoh-jni/Cargo.toml +++ b/zenoh-jni/Cargo.toml @@ -37,7 +37,7 @@ uhlc = "0.8.0" json5 = "0.4.1" serde_yaml = "0.9.19" zenoh = { version = "1.0.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["unstable", "internal"], default-features = false } -zenoh-ext = { version = "1.0.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", default-features = false, optional = true } +zenoh-ext = { version = "1.0.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["internal"], default-features = false, optional = true } tracing = { version = "0.1" , features = ["log"] } [lib] name = "zenoh_jni" diff --git a/zenoh-jni/src/zbytes.rs b/zenoh-jni/src/zbytes.rs index 978e0e448..0a1b04439 100644 --- a/zenoh-jni/src/zbytes.rs +++ b/zenoh-jni/src/zbytes.rs @@ -12,191 +12,560 @@ // ZettaScale Zenoh Team, // -use std::collections::HashMap; - use jni::{ - objects::{JByteArray, JClass, JList, JMap, JObject}, - sys::{jbyteArray, jobject}, + objects::{AutoLocal, JByteArray, JClass, JList, JMap, JObject, JString, JValue}, + sys::jobject, JNIEnv, }; use zenoh::bytes::ZBytes; -use zenoh_ext::{z_deserialize, z_serialize}; - -use crate::{errors::ZResult, utils::bytes_to_java_array, zerror}; -use crate::{throw_exception, utils::decode_byte_array}; - -/// -/// Map serialization and deserialization -/// - -/// Serializes a Map, returning the resulting ByteArray. -/// -/// # Parameters -/// - `env``: the JNI environment. -/// - `_class`: The java class. -/// - `map`: A Java bytearray map. -/// -/// # Returns: -/// - Returns the serialized map as a byte array. -#[no_mangle] -#[allow(non_snake_case)] -pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_serializeIntoMapViaJNI( - mut env: JNIEnv, - _class: JClass, - map: JObject, -) -> jbyteArray { - || -> ZResult { - let zbytes = java_map_to_zbytes(&mut env, &map).map_err(|err| zerror!(err))?; - let byte_array = bytes_to_java_array(&env, &zbytes)?; - Ok(byte_array.as_raw()) - }() - .unwrap_or_else(|err| { - throw_exception!(env, err); - JObject::null().as_raw() - }) +use zenoh_ext::{VarInt, ZDeserializeError, ZDeserializer, ZSerializer}; + +use crate::{ + errors::ZResult, + throw_exception, + utils::{bytes_to_java_array, decode_byte_array}, + zerror, +}; + +enum KotlinType { + Boolean, + String, + ByteArray, + Byte, + Short, + Int, + Long, + Float, + Double, + UByte, + UShort, + UInt, + ULong, + List(Box), + Map(Box, Box), + Pair(Box, Box), + Triple(Box, Box, Box), } -fn java_map_to_zbytes(env: &mut JNIEnv, map: &JObject) -> jni::errors::Result { - let jmap = JMap::from_env(env, map)?; - let mut iterator = jmap.iter(env)?; - let mut rust_map: HashMap, Vec> = HashMap::new(); - while let Some((key, value)) = iterator.next(env)? { - let key_bytes = env.convert_byte_array(env.auto_local(JByteArray::from(key)))?; - let value_bytes = env.convert_byte_array(env.auto_local(JByteArray::from(value)))?; - rust_map.insert(key_bytes, value_bytes); +fn decode_ktype(env: &mut JNIEnv, ktype: JObject) -> ZResult { + let classifier_obj = env + .call_method( + &ktype, + "getClassifier", + "()Lkotlin/reflect/KClassifier;", + &[], + ) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let classifier_obj = AutoLocal::new(classifier_obj, env); + + let kclass_class = env + .find_class("kotlin/reflect/KClass") + .map_err(|err| zerror!(err))?; + let is_kclass = env + .is_instance_of(&classifier_obj, kclass_class) + .map_err(|err| zerror!(err))?; + if is_kclass { + let qualified_name_jobject = env + .call_method( + &classifier_obj, + "getQualifiedName", + "()Ljava/lang/String;", + &[], + ) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + + let qualified_name: String = env + .get_string(&JString::from(qualified_name_jobject)) + .map_err(|err| zerror!(err))? + .into(); + + match qualified_name.as_str() { + "kotlin.Boolean" => Ok(KotlinType::Boolean), + "kotlin.String" => Ok(KotlinType::String), + "kotlin.ByteArray" => Ok(KotlinType::ByteArray), + "kotlin.Byte" => Ok(KotlinType::Byte), + "kotlin.Short" => Ok(KotlinType::Short), + "kotlin.Int" => Ok(KotlinType::Int), + "kotlin.Long" => Ok(KotlinType::Long), + "kotlin.Float" => Ok(KotlinType::Float), + "kotlin.Double" => Ok(KotlinType::Double), + "kotlin.UByte" => Ok(KotlinType::UByte), + "kotlin.UShort" => Ok(KotlinType::UShort), + "kotlin.UInt" => Ok(KotlinType::UInt), + "kotlin.ULong" => Ok(KotlinType::ULong), + "kotlin.collections.List" => Ok(KotlinType::List(Box::new(decode_ktype_arg( + env, &ktype, 0, + )?))), + "kotlin.collections.Map" => Ok(KotlinType::Map( + Box::new(decode_ktype_arg(env, &ktype, 0)?), + Box::new(decode_ktype_arg(env, &ktype, 1)?), + )), + "kotlin.Pair" => Ok(KotlinType::Pair( + Box::new(decode_ktype_arg(env, &ktype, 0)?), + Box::new(decode_ktype_arg(env, &ktype, 1)?), + )), + "kotlin.Triple" => Ok(KotlinType::Triple( + Box::new(decode_ktype_arg(env, &ktype, 0)?), + Box::new(decode_ktype_arg(env, &ktype, 1)?), + Box::new(decode_ktype_arg(env, &ktype, 2)?), + )), + _ => Err(zerror!("Unsupported type: {}", qualified_name)), + } + } else { + Err(zerror!("Classifier is not a KClass")) } - Ok(z_serialize(&rust_map)) } -/// Deserializes a serialized bytearray map, returning the original map. -/// -/// # Parameters: -/// - `env`: The JNI environment. -/// - `_class`: The Java class. -/// - `serialized_map`: The byte array resulting of the serialization of a bytearray map. -/// -/// # Returns -/// - The original byte array map before serialization. -/// +fn decode_ktype_arg(env: &mut JNIEnv, ktype: &JObject, idx: i32) -> ZResult { + let arguments = env + .call_method(ktype, "getArguments", "()Ljava/util/List;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let arg = env + .call_method( + &arguments, + "get", + "(I)Ljava/lang/Object;", + &[JValue::Int(idx)], + ) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let ktype = env + .call_method(arg, "getType", "()Lkotlin/reflect/KType;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + decode_ktype(env, ktype) +} + #[no_mangle] #[allow(non_snake_case)] -pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_deserializeIntoMapViaJNI( +pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_serializeViaJNI( mut env: JNIEnv, _class: JClass, - serialized_map: JByteArray, + any: JObject, + ktype: JObject, ) -> jobject { || -> ZResult { - let payload = decode_byte_array(&env, serialized_map)?; - let zbytes = ZBytes::from(payload); - let deserialization: HashMap, Vec> = - z_deserialize(&zbytes).map_err(|err| zerror!(err))?; - hashmap_to_java_map(&mut env, &deserialization).map_err(|err| zerror!(err)) + let mut serializer = ZSerializer::new(); + let ktype = decode_ktype(&mut env, ktype)?; + serialize(&mut env, &mut serializer, any, &ktype)?; + let zbytes = serializer.finish(); + + let byte_array = bytes_to_java_array(&env, &zbytes).map_err(|err| zerror!(err))?; + let zbytes_obj = env + .new_object( + "io/zenoh/bytes/ZBytes", + "([B)V", + &[JValue::Object(&JObject::from(byte_array))], + ) + .map_err(|err| zerror!(err))?; + + Ok(zbytes_obj.as_raw()) }() .unwrap_or_else(|err| { throw_exception!(env, err); - JObject::null().as_raw() + JObject::default().as_raw() }) } -fn hashmap_to_java_map( +fn serialize( env: &mut JNIEnv, - hashmap: &HashMap, Vec>, -) -> jni::errors::Result { - let map = env.new_object("java/util/HashMap", "()V", &[])?; - let jmap = JMap::from_env(env, &map)?; - - for (k, v) in hashmap.iter() { - let key = env.byte_array_from_slice(k.as_slice())?; - let value = env.byte_array_from_slice(v.as_slice())?; - jmap.put(env, &key, &value)?; - } - Ok(map.as_raw()) -} + serializer: &mut ZSerializer, + any: JObject, + ktype: &KotlinType, +) -> ZResult<()> { + match ktype { + KotlinType::Byte => { + let byte_value = env + .call_method(any, "byteValue", "()B", &[]) + .map_err(|err| zerror!(err))? + .b() + .map_err(|err| zerror!(err))?; + serializer.serialize(byte_value); + } + KotlinType::Short => { + let short_value = env + .call_method(any, "shortValue", "()S", &[]) + .map_err(|err| zerror!(err))? + .s() + .map_err(|err| zerror!(err))?; + serializer.serialize(short_value); + } + KotlinType::Int => { + let int_value = env + .call_method(any, "intValue", "()I", &[]) + .map_err(|err| zerror!(err))? + .i() + .map_err(|err| zerror!(err))?; + serializer.serialize(int_value); + } + KotlinType::Long => { + let long_value = env + .call_method(any, "longValue", "()J", &[]) + .map_err(|err| zerror!(err))? + .j() + .map_err(|err| zerror!(err))?; + serializer.serialize(long_value); + } + KotlinType::Float => { + let float_value = env + .call_method(any, "floatValue", "()F", &[]) + .map_err(|err| zerror!(err))? + .f() + .map_err(|err| zerror!(err))?; + serializer.serialize(float_value); + } + KotlinType::Double => { + let double_value = env + .call_method(any, "doubleValue", "()D", &[]) + .map_err(|err| zerror!(err))? + .d() + .map_err(|err| zerror!(err))?; + serializer.serialize(double_value); + } + KotlinType::Boolean => { + let boolean_value = env + .call_method(any, "booleanValue", "()Z", &[]) + .map_err(|err| zerror!(err))? + .z() + .map_err(|err| zerror!(err))?; + serializer.serialize(boolean_value); + } + KotlinType::String => { + let jstring = JString::from(any); + let string_value: String = env.get_string(&jstring).map_err(|err| zerror!(err))?.into(); + serializer.serialize(string_value); + } + KotlinType::ByteArray => { + let jbyte_array = JByteArray::from(any); + let bytes = decode_byte_array(env, jbyte_array).map_err(|err| zerror!(err))?; + serializer.serialize(bytes); + } + KotlinType::UByte => { + let byte = env + .get_field(any, "data", "B") + .map_err(|err| zerror!(err))? + .b() + .map_err(|err| zerror!(err))?; + serializer.serialize(byte as u8); + } + KotlinType::UShort => { + let short = env + .get_field(any, "data", "S") + .map_err(|err| zerror!(err))? + .s() + .map_err(|err| zerror!(err))?; + serializer.serialize(short as u16); + } + KotlinType::UInt => { + let int = env + .get_field(any, "data", "I") + .map_err(|err| zerror!(err))? + .i() + .map_err(|err| zerror!(err))?; + serializer.serialize(int as u32); + } + KotlinType::ULong => { + let long = env + .get_field(any, "data", "J") + .map_err(|err| zerror!(err))? + .j() + .map_err(|err| zerror!(err))?; + serializer.serialize(long as u64); + } + KotlinType::List(kotlin_type) => { + let jlist: JList<'_, '_, '_> = + JList::from_env(env, &any).map_err(|err| zerror!(err))?; + let mut iterator = jlist.iter(env).map_err(|err| zerror!(err))?; + let list_size = jlist.size(env).unwrap(); + serializer.serialize(zenoh_ext::VarInt(list_size as usize)); + while let Some(value) = iterator.next(env).map_err(|err| zerror!(err))? { + serialize(env, serializer, value, kotlin_type)?; + } + } + KotlinType::Map(key_type, value_type) => { + let jmap = JMap::from_env(env, &any).map_err(|err| zerror!(err))?; -/// -/// List serialization and deserialization -/// - -/// Serializes a list of byte arrays, returning a byte array. -/// -/// # Parameters: -/// - `env`: The JNI environment. -/// - `_class`: The Java class. -/// - `list`: The Java list of byte arrays to serialize. -/// -/// # Returns: -/// - The serialized list as a ByteArray. -/// -#[no_mangle] -#[allow(non_snake_case)] -pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_serializeIntoListViaJNI( - mut env: JNIEnv, - _class: JClass, - list: JObject, -) -> jbyteArray { - || -> ZResult { - let zbytes = java_list_to_zbytes(&mut env, &list).map_err(|err| zerror!(err))?; - let byte_array = bytes_to_java_array(&env, &zbytes)?; - Ok(byte_array.as_raw()) - }() - .unwrap_or_else(|err| { - throw_exception!(env, err); - JObject::null().as_raw() - }) -} + let map_size = env + .call_method(&jmap, "size", "()I", &[]) + .map_err(|err| zerror!(err))? + .i() + .map_err(|err| zerror!(err))?; + + serializer.serialize(zenoh_ext::VarInt(map_size as usize)); -fn java_list_to_zbytes(env: &mut JNIEnv, list: &JObject) -> jni::errors::Result { - let jmap = JList::from_env(env, list)?; - let mut iterator = jmap.iter(env)?; - let mut rust_vec: Vec> = Vec::new(); - while let Some(value) = iterator.next(env)? { - let value_bytes = env.auto_local(JByteArray::from(value)); - let value_bytes = env.convert_byte_array(value_bytes)?; - rust_vec.push(value_bytes); + let mut iterator = jmap.iter(env).map_err(|err| zerror!(err))?; + while let Some((key, value)) = iterator.next(env).map_err(|err| zerror!(err))? { + serialize(env, serializer, key, key_type)?; + serialize(env, serializer, value, value_type)?; + } + } + KotlinType::Pair(first_type, second_type) => { + let first = env + .call_method(&any, "getFirst", "()Ljava/lang/Object;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let second = env + .call_method(&any, "getSecond", "()Ljava/lang/Object;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + serialize(env, serializer, first, first_type)?; + serialize(env, serializer, second, second_type)?; + } + KotlinType::Triple(first_type, second_type, third_type) => { + let first = env + .call_method(&any, "getFirst", "()Ljava/lang/Object;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let second = env + .call_method(&any, "getSecond", "()Ljava/lang/Object;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + let third = env + .call_method(&any, "getThird", "()Ljava/lang/Object;", &[]) + .map_err(|err| zerror!(err))? + .l() + .map_err(|err| zerror!(err))?; + serialize(env, serializer, first, first_type)?; + serialize(env, serializer, second, second_type)?; + serialize(env, serializer, third, third_type)?; + } } - let zbytes = z_serialize(&rust_vec); - Ok(zbytes) + Ok(()) } -/// Deserializes a serialized list of byte arrrays, returning the original list. -/// -/// # Parameters: -/// - `env`: The JNI environment. -/// - `_class`: The Java class. -/// - `serialized_list`: The byte array resulting of the serialization of a bytearray list. -/// -/// # Returns: -/// - The original list of byte arrays prior to serialization. -/// #[no_mangle] #[allow(non_snake_case)] -pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_deserializeIntoListViaJNI( +pub extern "C" fn Java_io_zenoh_jni_JNIZBytes_deserializeViaJNI( mut env: JNIEnv, _class: JClass, - serialized_list: JByteArray, + zbytes: JObject, + ktype: JObject, ) -> jobject { || -> ZResult { - let payload = decode_byte_array(&env, serialized_list)?; - let zbytes = ZBytes::from(payload); - zbytes_to_java_list(&mut env, &zbytes).map_err(|err| zerror!(err)) + let payload = env + .get_field(zbytes, "bytes", "[B") + .map_err(|err| zerror!(err))?; + let decoded_bytes: Vec = + decode_byte_array(&env, JByteArray::from(payload.l().unwrap()))?; + let zbytes = ZBytes::from(decoded_bytes); + let mut deserializer = ZDeserializer::new(&zbytes); + let ktype = decode_ktype(&mut env, ktype)?; + let obj = deserialize(&mut env, &mut deserializer, &ktype)?; + if !deserializer.done() { + return Err(zerror!(ZDeserializeError)); + } + Ok(obj) }() .unwrap_or_else(|err| { throw_exception!(env, err); - JObject::null().as_raw() + JObject::default().as_raw() }) } -fn zbytes_to_java_list(env: &mut JNIEnv, zbytes: &ZBytes) -> ZResult { - let array_list = env - .new_object("java/util/ArrayList", "()V", &[]) - .map_err(|err| zerror!(err))?; - let jlist = JList::from_env(env, &array_list).map_err(|err| zerror!(err))?; - let values: Vec> = z_deserialize(zbytes).map_err(|err| zerror!(err))?; - for value in values { - let value = &mut env - .byte_array_from_slice(&value) - .map_err(|err| zerror!(err))?; - jlist.add(env, value).map_err(|err| zerror!(err))?; +fn deserialize( + env: &mut JNIEnv, + deserializer: &mut ZDeserializer, + ktype: &KotlinType, +) -> ZResult { + match ktype { + KotlinType::Byte => { + let byte = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let byte_obj = env + .new_object("java/lang/Byte", "(B)V", &[JValue::Byte(byte)]) + .map_err(|err| zerror!(err))?; + Ok(byte_obj.as_raw()) + } + KotlinType::Short => { + let short = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let short_obj = env + .new_object("java/lang/Short", "(S)V", &[JValue::Short(short)]) + .map_err(|err| zerror!(err))?; + Ok(short_obj.as_raw()) + } + KotlinType::Int => { + let integer = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let integer_obj = env + .new_object("java/lang/Integer", "(I)V", &[JValue::Int(integer)]) + .map_err(|err| zerror!(err))?; + Ok(integer_obj.as_raw()) + } + KotlinType::Long => { + let long = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let long_obj = env + .new_object("java/lang/Long", "(J)V", &[JValue::Long(long)]) + .map_err(|err| zerror!(err))?; + Ok(long_obj.as_raw()) + } + KotlinType::Float => { + let float = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let float_obj = env + .new_object("java/lang/Float", "(F)V", &[JValue::Float(float)]) + .map_err(|err| zerror!(err))?; + Ok(float_obj.as_raw()) + } + KotlinType::Double => { + let double = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let double_obj = env + .new_object("java/lang/Double", "(D)V", &[JValue::Double(double)]) + .map_err(|err| zerror!(err))?; + Ok(double_obj.as_raw()) + } + KotlinType::Boolean => { + let boolean_value = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let jboolean = if boolean_value { 1u8 } else { 0u8 }; + let boolean_obj = env + .new_object("java/lang/Boolean", "(Z)V", &[JValue::Bool(jboolean)]) + .map_err(|err| zerror!(err))?; + Ok(boolean_obj.as_raw()) + } + KotlinType::String => { + let deserialized_string = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let jstring = env + .new_string(&deserialized_string) + .map_err(|err| zerror!(err))?; + Ok(jstring.into_raw()) + } + KotlinType::ByteArray => { + let deserialized_bytes = deserializer + .deserialize::>() + .map_err(|err| zerror!(err))?; + let jbytes = env + .byte_array_from_slice(deserialized_bytes.as_slice()) + .map_err(|err| zerror!(err))?; + Ok(jbytes.into_raw()) + } + KotlinType::UByte => { + let ubyte = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let ubyte_obj = env + .new_object("kotlin/UByte", "(B)V", &[JValue::Byte(ubyte as i8)]) + .map_err(|err| zerror!(err))?; + Ok(ubyte_obj.as_raw()) + } + KotlinType::UShort => { + let ushort = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let ushort_obj = env + .new_object("kotlin/UShort", "(S)V", &[JValue::Short(ushort as i16)]) + .map_err(|err| zerror!(err))?; + Ok(ushort_obj.as_raw()) + } + KotlinType::UInt => { + let uint = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let uint_obj = env + .new_object("kotlin/UInt", "(I)V", &[JValue::Int(uint as i32)]) + .map_err(|err| zerror!(err))?; + Ok(uint_obj.as_raw()) + } + KotlinType::ULong => { + let ulong = deserializer + .deserialize::() + .map_err(|err| zerror!(err))?; + let ulong_obj = env + .new_object("kotlin/ULong", "(J)V", &[JValue::Long(ulong as i64)]) + .map_err(|err| zerror!(err))?; + Ok(ulong_obj.as_raw()) + } + KotlinType::List(kotlin_type) => { + let list_size = deserializer + .deserialize::>() + .map_err(|err| zerror!(err))? + .0; + let array_list = env + .new_object("java/util/ArrayList", "()V", &[]) + .map_err(|err| zerror!(err))?; + let jlist = JList::from_env(env, &array_list).map_err(|err| zerror!(err))?; + + for _ in 0..list_size { + let item = deserialize(env, deserializer, kotlin_type)?; + let item_obj = unsafe { JObject::from_raw(item) }; + jlist.add(env, &item_obj).map_err(|err| zerror!(err))?; + } + Ok(array_list.as_raw()) + } + KotlinType::Map(key_type, value_type) => { + let map_size = deserializer + .deserialize::>() + .map_err(|err| zerror!(err))? + .0; + let map = env + .new_object("java/util/HashMap", "()V", &[]) + .map_err(|err| zerror!(err))?; + let jmap = JMap::from_env(env, &map).map_err(|err| zerror!(err))?; + + for _ in 0..map_size { + let key = deserialize(env, deserializer, key_type)?; + let key_obj = unsafe { JObject::from_raw(key) }; + let value = deserialize(env, deserializer, value_type)?; + let value_obj = unsafe { JObject::from_raw(value) }; + jmap.put(env, &key_obj, &value_obj) + .map_err(|err| zerror!(err))?; + } + Ok(map.as_raw()) + } + KotlinType::Pair(first_type, second_type) => { + let first = deserialize(env, deserializer, first_type)?; + let second = deserialize(env, deserializer, second_type)?; + let pair = env + .new_object( + "kotlin/Pair", + "(Ljava/lang/Object;Ljava/lang/Object;)V", + &[ + JValue::Object(&unsafe { JObject::from_raw(first) }), + JValue::Object(&unsafe { JObject::from_raw(second) }), + ], + ) + .map_err(|err| zerror!(err))?; + Ok(pair.as_raw()) + } + KotlinType::Triple(first_type, second_type, third_type) => { + let first = deserialize(env, deserializer, first_type)?; + let second = deserialize(env, deserializer, second_type)?; + let third = deserialize(env, deserializer, third_type)?; + let triple = env + .new_object( + "kotlin/Triple", + "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", + &[ + JValue::Object(&unsafe { JObject::from_raw(first) }), + JValue::Object(&unsafe { JObject::from_raw(second) }), + JValue::Object(&unsafe { JObject::from_raw(third) }), + ], + ) + .map_err(|err| zerror!(err))?; + Ok(triple.as_raw()) + } } - Ok(array_list.as_raw()) } diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt index 3508e755f..670d400c3 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/bytes/ZBytes.kt @@ -14,262 +14,118 @@ package io.zenoh.bytes -import io.zenoh.exceptions.ZError -import java.nio.ByteBuffer -import java.nio.ByteOrder -import kotlin.reflect.KType -import kotlin.reflect.full.* -import kotlin.reflect.typeOf - /** * The ZBytes class (Zenoh bytes) represents the bytes received through the Zenoh network. * - * It provides many utilities to serialize an object into a ZBytes, as well as to deserialize from a ZBytes instance. - * - * # Serialization + * To serialize a type into a ZBytes it must be done through [io.zenoh.ext.zSerialize], while for deserialization + * [io.zenoh.ext.zDeserialize] must be called. * * Supported types: + * - Boolean + * - Byte + * - Short + * - Int + * - Long + * - Float + * - Double + * - List + * - Map + * - Pair + * - Triple + * + * Checkout the example below from the ZBytes example: * - * ## Raw types - * - * * Numeric: Byte, Short, Int, Long, Float and Double.** - * * String - * * ByteArray - * - * For the raw types, there are basically three ways to serialize them into a ZBytes, for instance let's suppose - * we want to serialize an `Int`, we could achieve it by:: - * * using the `into()` syntax: - * ```kotlin - * val exampleInt: Int = 256 - * val zbytes: ZBytes = exampleInt.into() - * ``` - * - * * using the `from()` syntax: - * ```kotlin - * val exampleInt: Int = 256 - * val zbytes: ZBytes = ZBytes.from(exampleInt) - * ``` - * - * * using the serialize syntax: - * ```kotlin - * val exampleInt: Int = 256 - * val zbytes: ZBytes = zSerialize(exampleInt).getOrThrow() - * ``` - * This approach works as well for the other mentioned types. - * - * ## Lists - * - * Lists are supported, but they must be either: - * - List of [Number] (Byte, Short, Int, Long, Float or Double) - * - List of [String] - * - List of [ByteArray] - * - List of [IntoZBytes] - * - * The serialize syntax must be used: - * ```kotlin - * val myList = listOf(1, 2, 5, 8, 13, 21) - * val zbytes = zSerialize>(myList).getOrThrow() - * ``` - * - * ## Maps - * - * Maps are supported as well, with the restriction that their inner types must be either: - * - [Number] - * - [String] - * - [ByteArray] - * - [IntoZBytes] - * - * ```kotlin - * val myMap: Map = mapOf("foo" to 1, "bar" to 2) - * val zbytes = zSerialize>(myMap).getOrThrow() - * ``` - * - * # Deserialization - * - * ## Raw types - * - * * Numeric: Byte, Short, Int, Long, Float and Double - * * String - * * ByteArray - * - * Example: - * - * For these raw types, you can use the functions `to`, that is - * - [toByte] - * - [toShort] - * - [toInt] - * - [toLong] - * - [toDouble] - * - [toString] - * - [toByteArray] - * - * For instance, for an Int: - * ```kotlin - * val example: Int = 256 - * val zbytes: ZBytes = exampleInt.into() - * val deserializedInt = zbytes.toInt() - * ``` - * - * Alternatively, the deserialize syntax can be used as well: - * ```kotlin - * val exampleInt: Int = 256 - * val zbytes: ZBytes = exampleInt.into() - * val deserializedInt = zDeserializeInt>(zbytes).getOrThrow() - * ``` - * - * ## Lists - * - * Lists are supported, but they must be deserialized either into a: - * - List of [Number] (Byte, Short, Int, Long, Float or Double) - * - List of [String] - * - List of [ByteArray] - * - * To deserialize into a list, we need to use the deserialize syntax as follows: * ```kotlin + * /*********************************************** + * * Standard serialization and deserialization. * + * ***********************************************/ + * + * /** Numeric: byte, short, int, float, double */ + * val intInput = 1234 + * var payload = zSerialize(intInput).getOrThrow() + * val intOutput = zDeserialize(payload).getOrThrow() + * check(intInput == intOutput) + * + * // Another example with float + * val floatInput = 3.1415f + * payload = zSerialize(floatInput).getOrThrow() + * val floatOutput = zDeserialize(payload).getOrThrow() + * check(floatInput == floatOutput) + * + * /** String serialization and deserialization. */ + * val stringInput = "example" + * payload = zSerialize(stringInput).getOrThrow() + * var stringOutput = zDeserialize(payload).getOrThrow() + * check(stringInput == stringOutput) + * + * /** ByteArray serialization and deserialization. */ + * val byteArrayInput = "example".toByteArray() + * payload = zSerialize(byteArrayInput).getOrThrow() + * val byteArrayOutput = zDeserialize(payload).getOrThrow() + * check(byteArrayInput.contentEquals(byteArrayOutput)) + * + * /** + * * List serialization and deserialization. + * * + * * Supported types: String, ByteArray, Byte, Short, Int, Long, Float and Double. + * */ * val inputList = listOf("sample1", "sample2", "sample3") - * payload = serialize(inputList).getOrThrow() - * val outputList = zDeserializeList>(payload).getOrThrow() - * ``` - * - * ## Maps - * - * Maps are supported as well, with the restriction that their inner types must be either: - * - [Number] - * - [String] - * - [ByteArray] - * - * ```kotlin + * payload = zSerialize(inputList).getOrThrow() + * val outputList = zDeserialize>(payload).getOrThrow() + * check(inputList == outputList) + * + * val inputListInt = listOf(1, 2, 3) + * payload = zSerialize(inputListInt).getOrThrow() + * val outputListInt = zDeserialize>(payload).getOrThrow() + * check(inputListInt == outputListInt) + * + * val inputListByteArray = inputList.map { value -> value.toByteArray() } + * payload = zSerialize(inputListByteArray).getOrThrow() + * val outputListByteArray = zDeserialize>(payload).getOrThrow() + * check(compareByteArrayLists(inputListByteArray, outputListByteArray)) + * + * /** Nested lists */ + * val nestedList = listOf(listOf(1, 2, 3)) + * payload = zSerialize(nestedList).getOrThrow() + * val outputNestedList = zDeserialize>>(payload).getOrThrow() + * check(nestedList == outputNestedList) + * + * /** Combined types */ + * val combinedList = listOf(mapOf("a" to 1, "b" to 2)) + * payload = zSerialize(combinedList).getOrThrow() + * val outputCombinedList = zDeserialize>>(payload).getOrThrow() + * check(combinedList == outputCombinedList) + * + * /** + * * Map serialization and deserialization. + * * + * * Maps with the following Type combinations are supported: String, ByteArray, Byte, Short, Int, Long, Float and Double. + * */ * val inputMap = mapOf("key1" to "value1", "key2" to "value2", "key3" to "value3") - * payload = serialize(inputMap).getOrThrow() - * val outputMap = zDeserializeMap>(payload).getOrThrow() + * payload = zSerialize(inputMap).getOrThrow() + * val outputMap = zDeserialize>(payload).getOrThrow() * check(inputMap == outputMap) - * ``` - * - * # Custom serialization and deserialization - * - * ## Serialization - * - * For custom serialization, classes to be serialized need to implement the [IntoZBytes] interface. - * For instance: - * - * ```kotlin - * class Foo(val content: String) : IntoZBytes { - * - * /*Inherits: IntoZBytes*/ - * override fun into(): ZBytes = content.into() - * } - * ``` * - * This way, we can do: - * ```kotlin - * val foo = Foo("bar") - * val serialization = zSerialize(foo).getOrThrow() - * ``` - * - * Implementing the [IntoZBytes] interface on a class enables the possibility of serializing lists and maps - * of that type, for instance: - * ```kotlin - * val list = listOf(Foo("bar"), Foo("buz"), Foo("fizz")) - * val zbytes = zSerialize>(list) - * ``` - * - * ## Deserialization - * - * In order for the serialization to be successful on a custom class, - * it must override the `into(): ZBytes` function from the [IntoZBytes] interface. - * - * Regarding deserialization for custom objects, for the time being (this API will be expanded to - * provide further utilities) you need to manually convert the ZBytes into the type you want. - * - * ```kotlin - * val inputFoo = Foo("example") - * payload = serialize(inputFoo).getOrThrow() - * val outputFoo = Foo.from(payload) - * check(inputFoo == outputFoo) - * - * // List of Foo. - * val inputListFoo = inputList.map { value -> Foo(value) } - * payload = zSerialize>(inputListFoo).getOrThrow() - * val outputListFoo = zDeserializeList>(payload).getOrThrow().map { zbytes -> Foo.from(zbytes) } - * check(inputListFoo == outputListFoo) - * - * // Map of Foo. - * val inputMapFoo = inputMap.map { (k, v) -> Foo(k) to Foo(v) }.toMap() - * payload = zSerialize>(inputMapFoo).getOrThrow() - * val outputMapFoo = zDeserializeMap>(payload).getOrThrow() - * .map { (key, value) -> Foo.from(key) to Foo.from(value) }.toMap() - * check(inputMapFoo == outputMapFoo) + * val combinedInputMap = mapOf("key1" to 1, "key2" to 2) + * payload = zSerialize(combinedInputMap).getOrThrow() + * val combinedOutputMap = zDeserialize>(payload).getOrThrow() + * check(combinedInputMap == combinedOutputMap) * ``` */ class ZBytes internal constructor(internal val bytes: ByteArray) : IntoZBytes { companion object { - fun from(intoZBytes: IntoZBytes) = intoZBytes.into() - fun from(string: String) = ZBytes(string.toByteArray()) - fun from(byteArray: ByteArray) = ZBytes(byteArray) - fun from(number: Number): ZBytes { - val byteArray = when (number) { - is Byte -> byteArrayOf(number) - is Short -> ByteBuffer.allocate(Short.SIZE_BYTES).apply { - order(ByteOrder.LITTLE_ENDIAN) - putShort(number) - }.array() - - is Int -> ByteBuffer.allocate(Int.SIZE_BYTES).apply { - order(ByteOrder.LITTLE_ENDIAN) - putInt(number) - }.array() - - is Long -> ByteBuffer.allocate(Long.SIZE_BYTES).apply { - order(ByteOrder.LITTLE_ENDIAN) - putLong(number) - }.array() - - is Float -> ByteBuffer.allocate(Float.SIZE_BYTES).apply { - order(ByteOrder.LITTLE_ENDIAN) - putFloat(number) - }.array() - - is Double -> ByteBuffer.allocate(Double.SIZE_BYTES).apply { - order(ByteOrder.LITTLE_ENDIAN) - putDouble(number) - }.array() - - else -> throw IllegalArgumentException("Unsupported number type") - } - return ZBytes(byteArray) - } - + fun from(string: String) = ZBytes(string.encodeToByteArray()) + fun from(bytes: ByteArray) = ZBytes(bytes) } - fun toByteArray() = bytes + fun toBytes(): ByteArray = bytes - fun toByte(): Byte { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).get() - } - - fun toShort(): Short { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).short - } - - fun toInt(): Int { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).int - } - - fun toLong(): Long { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).long - } - - fun toFloat(): Float { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).float - } - - fun toDouble(): Double { - return ByteBuffer.wrap(this.bytes).order(ByteOrder.LITTLE_ENDIAN).double - } + fun tryToString(): Result = + runCatching { bytes.decodeToString(throwOnInvalidSequence = true) } - override fun toString() = bytes.decodeToString() + override fun toString(): String = bytes.decodeToString() override fun into(): ZBytes = this @@ -278,41 +134,6 @@ class ZBytes internal constructor(internal val bytes: ByteArray) : IntoZBytes { override fun hashCode() = bytes.contentHashCode() } -fun Number.into(): ZBytes { - return ZBytes.from(this) -} - -fun String.into(): ZBytes { - return ZBytes.from(this) -} - -fun ByteArray.into(): ZBytes { +internal fun ByteArray.into(): ZBytes { return ZBytes(this) } - -@Throws(ZError::class) -internal fun Any?.into(): ZBytes { - return when (this) { - is String -> this.into() - is Number -> this.into() - is ByteArray -> this.into() - is IntoZBytes -> this.into() - else -> throw IllegalArgumentException("Unsupported serializable type") - } -} - -@Throws(ZError::class) -internal fun ZBytes.intoAny(type: KType): Any { - return when (type) { - typeOf() -> this.toString() - typeOf() -> this.toByte() - typeOf() -> this.toShort() - typeOf() -> this.toInt() - typeOf() -> this.toLong() - typeOf() -> this.toFloat() - typeOf() -> this.toDouble() - typeOf() -> this.toByteArray() - typeOf() -> this - else -> throw IllegalArgumentException("Unsupported type '$type' for deserialization.") - } -} diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZDeserialize.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZDeserialize.kt index e39a49681..ce2b261f9 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZDeserialize.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZDeserialize.kt @@ -1,117 +1,15 @@ package io.zenoh.ext import io.zenoh.bytes.ZBytes -import io.zenoh.bytes.intoAny -import io.zenoh.jni.JNIZBytes -import kotlin.reflect.KClass -import kotlin.reflect.KFunction1 -import kotlin.reflect.KType -import kotlin.reflect.full.createType -import kotlin.reflect.full.isSupertypeOf -import kotlin.reflect.jvm.jvmErasure +import io.zenoh.jni.JNIZBytes.deserializeViaJNI import kotlin.reflect.typeOf /** * Deserialize the [ZBytes] instance into an element of type [T]. * - * Supported types: - * - [Number]: Byte, Short, Int, Long, Float, Double - * - [String] - * - [ByteArray] - * - Lists and Maps of the above-mentioned types. - * * @see ZBytes * @return a [Result] with the deserialization. */ -inline fun zDeserialize(zbytes: ZBytes): Result { - val type = typeOf() - when { - typeOf>().isSupertypeOf(type) -> { - val itemsClass = type.arguments.firstOrNull()?.type?.jvmErasure - return zDeserialize(zbytes, T::class, arg1clazz = itemsClass) - } - typeOf>().isSupertypeOf(type) -> { - val keyClass = type.arguments.getOrNull(0)?.type?.jvmErasure - val valueClass = type.arguments.getOrNull(1)?.type?.jvmErasure - return zDeserialize(zbytes, T::class, arg1clazz = keyClass, arg2clazz = valueClass) - } - typeOf().isSupertypeOf(type) -> { - return zDeserialize(zbytes, T::class) - } - } - throw IllegalArgumentException("Unsupported type for deserialization: '$type'.") -} - -/** - * Deserialize the [ZBytes] into an element of class [clazz]. - * - * It's generally preferable to use the [zDeserialize] function with reification, however - * this function is exposed for cases when reification needs to be avoided. - * - * Example: - * ```kotlin - * val list = listOf("value1", "value2", "value3") - * val zbytes = serialize(list).getOrThrow() - * val deserializedList = deserialize(zbytes, clazz = List::class, arg1clazz = String::class).getOrThrow() - * check(list == deserializedList) - * ``` - * - * Supported types: - * - [Number]: Byte, Short, Int, Long, Float, Double - * - [String] - * - [ByteArray] - * - Lists and Maps of the above-mentioned types. - * - * @see [zDeserialize] - * - * - * @param clazz: the [KClass] of the type to be serialized. - * @param arg1clazz Optional first nested parameter of the provided clazz, for instance when trying to deserialize - * into a `List`, arg1clazz should be set to `String::class`, when trying to deserialize into a - * `Map`, arg1clazz should be set to `Int::class`. Can be null if providing a basic type. - * @param arg2clazz Optional second nested parameter of the provided clazz, to be used for the cases of maps. - * For instance, when trying to deserialize into a `Map`, arg2clazz should be set to `String::class`. - * Can be null if providing a basic type. - */ -@Suppress("UNCHECKED_CAST") -fun zDeserialize( - zbytes: ZBytes, - clazz: KClass, - arg1clazz: KClass<*>? = null, - arg2clazz: KClass<*>? = null, -): Result { - val type: KType = when (clazz) { - List::class -> typeOf>() - Map::class -> typeOf>() - else -> clazz.createType() - } - return when { - typeOf>().isSupertypeOf(type) -> { - val typeElement = arg1clazz?.createType() - if (typeElement != null) { - Result.success(JNIZBytes.deserializeIntoList(zbytes).map { it.intoAny(typeElement) } as T) - } else { - Result.failure(IllegalArgumentException("Unsupported list type for deserialization: $type")) - } - } - - typeOf>().isSupertypeOf(type) -> { - val keyType = arg1clazz?.createType() - val valueType = arg2clazz?.createType() - if (keyType != null && valueType != null) { - Result.success( - JNIZBytes.deserializeIntoMap(zbytes) - .map { (k, v) -> k.intoAny(keyType) to v.intoAny(valueType) }.toMap() as T - ) - } else { - Result.failure(IllegalArgumentException("Unsupported map type for deserialization: $type")) - } - } - - typeOf().isSupertypeOf(type) -> { - Result.success(zbytes.intoAny(type) as T) - } - - else -> Result.failure(IllegalArgumentException("Unsupported type for deserialization: $type")) - } +inline fun zDeserialize(zbytes: ZBytes): Result = runCatching { + deserializeViaJNI(zbytes, typeOf()) as T } diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZSerialize.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZSerialize.kt index 71a0a3243..8d468a7d7 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZSerialize.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/ext/ZSerialize.kt @@ -1,54 +1,15 @@ package io.zenoh.ext import io.zenoh.bytes.ZBytes -import io.zenoh.bytes.into -import io.zenoh.jni.JNIZBytes -import kotlin.reflect.KClass -import kotlin.reflect.KType -import kotlin.reflect.full.createType -import kotlin.reflect.full.isSupertypeOf +import io.zenoh.jni.JNIZBytes.serializeViaJNI import kotlin.reflect.typeOf /** * Serialize an element of type [T] into a [ZBytes]. * - * Supported types: - * - [Number]: Byte, Short, Int, Long, Float, Double - * - [String] - * - [ByteArray] - * - [IntoZBytes] - * - Lists and Maps of the above-mentioned types. - * * @see ZBytes * @return a [Result] with the serialized [ZBytes]. */ inline fun zSerialize(t: T): Result = runCatching { - return zSerialize(t, T::class) -} - -fun zSerialize(t: T, clazz: KClass): Result = runCatching { - val type: KType = when (clazz) { - List::class -> typeOf>() - Map::class -> typeOf>() - else -> clazz.createType() - } - when { - typeOf>().isSupertypeOf(type) -> { - val list = t as List<*> - val zbytesList = list.map { it.into() } - return Result.success(JNIZBytes.serializeIntoList(zbytesList)) - } - - typeOf>().isSupertypeOf(type) -> { - val map = t as Map<*, *> - val zbytesMap = map.map { (k, v) -> k.into() to v.into() }.toMap() - return Result.success(JNIZBytes.serializeIntoMap(zbytesMap)) - } - - typeOf().isSupertypeOf(type) -> { - return Result.success((t as Any).into()) - } - - else -> throw IllegalArgumentException("Unsupported type '$type' for serialization.") - } + serializeViaJNI(t, typeOf()) } diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIZBytes.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIZBytes.kt index 31c6bfff0..8e9e94b2f 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIZBytes.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/jni/JNIZBytes.kt @@ -16,35 +16,16 @@ package io.zenoh.jni import io.zenoh.ZenohLoad import io.zenoh.bytes.ZBytes -import io.zenoh.bytes.into +import kotlin.reflect.KType +@PublishedApi internal object JNIZBytes { init { ZenohLoad } - fun serializeIntoList(list: List): ZBytes { - return serializeIntoListViaJNI(list.map { it.bytes }).into() - } - - fun deserializeIntoList(zbytes: ZBytes): List { - return deserializeIntoListViaJNI(zbytes.bytes).map { it.into() }.toList() - } - - fun serializeIntoMap(map: Map): ZBytes { - return serializeIntoMapViaJNI(map.map { (k, v) -> k.bytes to v.bytes }.toMap()).into() - } - - fun deserializeIntoMap(bytes: ZBytes): Map { - return deserializeIntoMapViaJNI(bytes.bytes).map { (k, v) -> k.into() to v.into() }.toMap() - } - - private external fun serializeIntoMapViaJNI(map: Map): ByteArray - - private external fun serializeIntoListViaJNI(list: List): ByteArray - - private external fun deserializeIntoMapViaJNI(payload: ByteArray): Map + external fun serializeViaJNI(any: Any, kType: KType): ZBytes - private external fun deserializeIntoListViaJNI(payload: ByteArray): List + external fun deserializeViaJNI(zBytes: ZBytes, kType: KType): Any } diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/pubsub/Publisher.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/pubsub/Publisher.kt index 9c8910b0c..04c248dae 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/pubsub/Publisher.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/pubsub/Publisher.kt @@ -83,9 +83,6 @@ class Publisher internal constructor( /** Performs a PUT operation on the specified [keyExpr] with the specified [payload]. */ fun put(payload: IntoZBytes, encoding: Encoding? = null, attachment: IntoZBytes? = null) = jniPublisher?.put(payload, encoding ?: this.encoding, attachment) ?: InvalidPublisherResult - /** Performs a PUT operation on the specified [keyExpr] with the specified string [message]. */ - fun put(message: String, encoding: Encoding? = null, attachment: IntoZBytes? = null) = jniPublisher?.put(message.into(), encoding ?: this.encoding, attachment) ?: InvalidPublisherResult - /** * Performs a DELETE operation on the specified [keyExpr] */ diff --git a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt index 34af6608c..0f7a49e83 100644 --- a/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt +++ b/zenoh-kotlin/src/commonMain/kotlin/io/zenoh/sample/Sample.kt @@ -39,5 +39,10 @@ data class Sample( val kind: SampleKind, val timestamp: TimeStamp?, val qos: QoS, - val attachment: ZBytes? = null -): ZenohType + val attachment: ZBytes? = null, +): ZenohType { + + val express = qos.express + val congestionControl = qos.congestionControl + val priority = qos.priority +} diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ConfigTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ConfigTest.kt index 9801b5f20..475705ef6 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ConfigTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ConfigTest.kt @@ -14,8 +14,8 @@ package io.zenoh import io.zenoh.exceptions.ZError +import io.zenoh.ext.zSerialize import io.zenoh.keyexpr.intoKeyExpr -import io.zenoh.bytes.into import io.zenoh.sample.Sample import kotlinx.coroutines.runBlocking import kotlinx.coroutines.delay @@ -142,7 +142,7 @@ class ConfigTest { receivedSample = sample }).getOrThrow() - val payload = "example message".into() + val payload = zSerialize("example message").getOrThrow() sessionClient.put(TEST_KEY_EXP, payload).getOrThrow() delay(1000) diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/EncodingTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/EncodingTest.kt index 02436b77f..963a1c7bf 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/EncodingTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/EncodingTest.kt @@ -3,7 +3,7 @@ package io.zenoh import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.bytes.Encoding import io.zenoh.bytes.ZBytes -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.query.ReplyError import io.zenoh.sample.Sample import io.zenoh.query.intoSelector @@ -14,6 +14,13 @@ class EncodingTest { private val without_schema = Encoding.TEXT_CSV private val with_schema = Encoding.APPLICATION_JSON.withSchema("test_schema") + private lateinit var payload: ZBytes + + @BeforeTest + fun setUp() { + payload = zSerialize("test").getOrThrow() + } + @Test fun encoding_subscriberTest() { val session = Session.open(Config.default()).getOrThrow() @@ -26,7 +33,7 @@ class EncodingTest { }).getOrThrow() session.put( keyExpr, - payload = "test".into(), + payload = payload, encoding = with_schema ) Thread.sleep(200) @@ -35,7 +42,7 @@ class EncodingTest { // Testing null schema receivedSample = null - session.put(keyExpr, payload = "test2".into(), encoding = without_schema) + session.put(keyExpr, payload, encoding = without_schema) Thread.sleep(200) assertEquals(receivedSample?.encoding, without_schema) @@ -55,13 +62,13 @@ class EncodingTest { when (query.keyExpr) { test1.keyExpr -> query.reply( query.keyExpr, - payload = "test".into(), + payload = payload, encoding = without_schema ) test2.keyExpr -> query.reply( query.keyExpr, - payload = "test".into(), + payload = payload, encoding = with_schema ) } @@ -99,10 +106,11 @@ class EncodingTest { val test1 = "example/testing/reply_error".intoSelector().getOrThrow() val test2 = "example/testing/reply_error_with_schema".intoSelector().getOrThrow() + val replyPayload = zSerialize("test").getOrThrow() val queryable = session.declareQueryable(keyExpr, callback = { query -> when (query.keyExpr) { - test1.keyExpr -> query.replyErr("test".into(), without_schema) - test2.keyExpr -> query.replyErr("test".into(), with_schema) + test1.keyExpr -> query.replyErr(replyPayload, without_schema) + test2.keyExpr -> query.replyErr(replyPayload, with_schema) } }).getOrThrow() @@ -156,7 +164,7 @@ class EncodingTest { }).getOrThrow() // Testing with null schema - session.get(selector, callback = {}, payload = "test".into(), encoding = without_schema) + session.get(selector, callback = {}, payload = payload, encoding = without_schema) Thread.sleep(200) assertEquals(receivedEncoding, without_schema) @@ -165,7 +173,7 @@ class EncodingTest { // Testing non-null schema receivedEncoding = null - session.get(selector, callback = {}, payload = "test".into(), encoding = with_schema) + session.get(selector, callback = {}, payload = payload, encoding = with_schema) Thread.sleep(200) assertEquals(receivedEncoding, with_schema) diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt index 11395fa9e..daea93a35 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/GetTest.kt @@ -16,7 +16,7 @@ package io.zenoh import io.zenoh.handlers.Handler import io.zenoh.sample.SampleKind -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.query.Reply import io.zenoh.query.Queryable import io.zenoh.query.Parameters @@ -30,7 +30,7 @@ import kotlin.test.* class GetTest { companion object { - val payload = "Test".into() + val payload = zSerialize("Test").getOrThrow() val timestamp = TimeStamp.getCurrentTime() val kind = SampleKind.PUT } diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt index 500267a83..6cb5bb48b 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PublisherTest.kt @@ -18,7 +18,7 @@ import io.zenoh.keyexpr.KeyExpr import io.zenoh.bytes.Encoding import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.sample.SampleKind -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.pubsub.Publisher import io.zenoh.sample.Sample import io.zenoh.pubsub.Subscriber @@ -55,9 +55,9 @@ class PublisherTest { fun putTest() { val testPayloads = arrayListOf( - Pair("Test 1".into(), Encoding.TEXT_PLAIN), - Pair("Test 2".into(), Encoding.TEXT_JSON), - Pair("Test 3".into(), Encoding.TEXT_CSV), + Pair(zSerialize("Test 1").getOrThrow(), Encoding.TEXT_PLAIN), + Pair(zSerialize("Test 2").getOrThrow(), Encoding.TEXT_JSON), + Pair(zSerialize("Test 3").getOrThrow(), Encoding.TEXT_CSV), ) testPayloads.forEach() { value -> publisher.put(value.first, encoding = value.second) } @@ -78,7 +78,7 @@ class PublisherTest { @Test fun `when encoding is not provided a put should fallback to the publisher encoding`() { - publisher.put("Test") + publisher.put(zSerialize("Test").getOrThrow()) assertEquals(1, receivedSamples.size) assertEquals(Encoding.ZENOH_STRING, receivedSamples[0].encoding) } diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt index b70ae8e5d..022f4b8d5 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/PutTest.kt @@ -16,7 +16,7 @@ package io.zenoh import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.bytes.Encoding -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.sample.Sample import kotlin.test.Test import kotlin.test.assertEquals @@ -26,7 +26,7 @@ class PutTest { companion object { const val TEST_KEY_EXP = "example/testing/keyexpr" - val TEST_PAYLOAD = "Hello".into() + val TEST_PAYLOAD = zSerialize("Hello").getOrThrow() } @Test diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt index 04d358f71..b3f54618e 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/QueryableTest.kt @@ -18,7 +18,7 @@ import io.zenoh.bytes.Encoding import io.zenoh.handlers.Handler import io.zenoh.keyexpr.KeyExpr import io.zenoh.keyexpr.intoKeyExpr -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.qos.CongestionControl import io.zenoh.qos.Priority import io.zenoh.qos.QoS @@ -42,7 +42,7 @@ import kotlin.test.* class QueryableTest { companion object { - val testPayload = "Hello queryable".into() + val testPayload = zSerialize("Hello queryable").getOrThrow() } private lateinit var session: Session @@ -121,8 +121,8 @@ class QueryableTest { assertNull(receivedQuery!!.attachment) receivedQuery = null - val payload = "Test value".into() - val attachment = "Attachment".into() + val payload = zSerialize("Test value").getOrThrow() + val attachment = zSerialize("Attachment").getOrThrow() session.get(Selector(testKeyExpr), callback = {}, payload = payload, encoding = Encoding.ZENOH_STRING, attachment = attachment) delay(100) @@ -136,7 +136,7 @@ class QueryableTest { @Test fun queryReplySuccessTest() { - val message = "Test message".into() + val message = zSerialize("Test message").getOrThrow() val timestamp = TimeStamp.getCurrentTime() val qos = QoS(priority = Priority.DATA_HIGH, express = true, congestionControl = CongestionControl.DROP) val priority = Priority.DATA_HIGH @@ -162,7 +162,7 @@ class QueryableTest { @Test fun queryReplyErrorTest() { - val errorMessage = "Error message".into() + val errorMessage = zSerialize("Error message").getOrThrow() val queryable = session.declareQueryable(testKeyExpr, callback = { query -> query.replyErr(error = errorMessage) }).getOrThrow() @@ -233,7 +233,7 @@ private class QueryHandler : Handler { override fun onClose() {} fun reply(query: Query) { - val payload = "Hello queryable $counter!".into() + val payload = zSerialize("Hello queryable $counter!").getOrThrow() counter++ val sample = Sample( query.keyExpr, diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt index 6d0308b8e..1e82232fb 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SessionTest.kt @@ -15,6 +15,7 @@ package io.zenoh import io.zenoh.exceptions.ZError +import io.zenoh.ext.zSerialize import io.zenoh.keyexpr.KeyExpr import io.zenoh.keyexpr.intoKeyExpr import kotlinx.coroutines.runBlocking @@ -65,7 +66,7 @@ class SessionTest { assertFalse(publisher.isValid()) assertFalse(subscriber.isValid()) - assertTrue(publisher.put("Test").isFailure) + assertTrue(publisher.put(zSerialize("Test").getOrThrow()).isFailure) } @Test diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt index 497d85d65..4266c91ee 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/SubscriberTest.kt @@ -18,11 +18,11 @@ import io.zenoh.handlers.Handler import io.zenoh.keyexpr.KeyExpr import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.bytes.Encoding +import io.zenoh.ext.zSerialize import io.zenoh.sample.Sample import io.zenoh.qos.CongestionControl import io.zenoh.qos.Priority import io.zenoh.qos.QoS -import io.zenoh.bytes.into import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.runBlocking @@ -38,9 +38,9 @@ class SubscriberTest { val TEST_CONGESTION_CONTROL = CongestionControl.BLOCK val testValues = arrayListOf( - Pair("Test 1".into(), Encoding.TEXT_PLAIN), - Pair("Test 2".into(), Encoding.TEXT_JSON), - Pair("Test 3".into(), Encoding.TEXT_CSV), + Pair(zSerialize("Test 1").getOrThrow(), Encoding.TEXT_PLAIN), + Pair(zSerialize("Test 2").getOrThrow(), Encoding.TEXT_JSON), + Pair(zSerialize("Test 3").getOrThrow(), Encoding.TEXT_CSV), ) } diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/UserAttachmentTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/UserAttachmentTest.kt index 256b95c44..6a869f927 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/UserAttachmentTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/UserAttachmentTest.kt @@ -18,7 +18,7 @@ import io.zenoh.keyexpr.KeyExpr import io.zenoh.keyexpr.intoKeyExpr import io.zenoh.bytes.ZBytes import io.zenoh.ext.zDeserialize -import io.zenoh.bytes.into +import io.zenoh.ext.zSerialize import io.zenoh.query.Reply import io.zenoh.sample.Sample import io.zenoh.query.Selector @@ -31,10 +31,10 @@ class UserAttachmentTest { private lateinit var keyExpr: KeyExpr companion object { - val payload = "test".into() + val payload = zSerialize("test").getOrThrow() const val keyExprString = "example/testing/attachment" const val attachment = "mock_attachment" - val attachmentZBytes = ZBytes.from(attachment) + val attachmentZBytes = zSerialize(attachment).getOrThrow() } @BeforeTest @@ -60,7 +60,7 @@ class UserAttachmentTest { assertNotNull(receivedSample) { val receivedAttachment = it.attachment!! - assertEquals(attachment, receivedAttachment.toString()) + assertEquals(attachment, zDeserialize(receivedAttachment).getOrThrow()) } } @@ -72,7 +72,7 @@ class UserAttachmentTest { receivedSample = sample }).getOrThrow() - publisher.put("test", attachment = attachmentZBytes) + publisher.put(payload, attachment = attachmentZBytes) publisher.close() subscriber.close() @@ -90,7 +90,7 @@ class UserAttachmentTest { val subscriber = session.declareSubscriber(keyExpr, callback = { sample -> receivedSample = sample }).getOrThrow() - publisher.put("test") + publisher.put(payload) publisher.close() subscriber.close() @@ -114,7 +114,7 @@ class UserAttachmentTest { assertNotNull(receivedSample) { val receivedAttachment = it.attachment!! - assertEquals(attachment, receivedAttachment.toString()) + assertEquals(attachment, zDeserialize(receivedAttachment).getOrThrow()) } } @@ -172,7 +172,7 @@ class UserAttachmentTest { assertNotNull(reply) val receivedAttachment = reply!!.result.getOrThrow().attachment!! - assertEquals(attachment, receivedAttachment.toString()) + assertEquals(attachment, zDeserialize(receivedAttachment).getOrThrow()) } @Test diff --git a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ZBytesTest.kt b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ZBytesTest.kt index 44c0b509e..cdbdb8c72 100644 --- a/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ZBytesTest.kt +++ b/zenoh-kotlin/src/commonTest/kotlin/io/zenoh/ZBytesTest.kt @@ -1,251 +1,28 @@ +//// +//// Copyright (c) 2023 ZettaScale Technology +//// +//// This program and the accompanying materials are made available under the +//// terms of the Eclipse Public License 2.0 which is available at +//// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +//// which is available at https://www.apache.org/licenses/LICENSE-2.0. +//// +//// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +//// +//// Contributors: +//// ZettaScale Zenoh Team, +//// // -// Copyright (c) 2023 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - package io.zenoh -import io.zenoh.bytes.ZBytes import io.zenoh.ext.zDeserialize -import io.zenoh.bytes.into import io.zenoh.ext.zSerialize -import org.junit.jupiter.api.Assertions.assertArrayEquals import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.MethodSource -import java.nio.ByteBuffer -import java.nio.ByteOrder -import kotlin.reflect.KClass -import kotlin.reflect.typeOf import kotlin.test.Test import kotlin.test.assertTrue -data class SimpleTestCase( - val originalItem: T, - val clazz: KClass -) - -data class ListTestCase( - val originalList: List, - val itemclazz: KClass -) - -data class MapTestCase( - val originalMap: Map, - val keyclazz: KClass, - val valueclazz: KClass, -) - class ZBytesTests { - companion object { - @JvmStatic - fun simpleTestCases(): List> { - return listOf( - SimpleTestCase(1.toByte(), Byte::class), - SimpleTestCase(1.toShort(), Short::class), - SimpleTestCase(1, Int::class), - SimpleTestCase(1L, Long::class), - SimpleTestCase(1.0f, Float::class), - SimpleTestCase(1.0, Double::class), - SimpleTestCase("value1", String::class), - SimpleTestCase(byteArrayOf(1, 2, 3), ByteArray::class), - ) - } - - @JvmStatic - fun listTestCases(): List> { - return listOf( - // Byte Lists - ListTestCase(listOf(1.toByte(), 2.toByte(), 3.toByte()), Byte::class), - // Short Lists - ListTestCase(listOf(1.toShort(), 2.toShort(), 3.toShort()), Short::class), - // Int Lists - ListTestCase(listOf(1, 2, 3), Int::class), - // Long Lists - ListTestCase(listOf(1L, 2L, 3L), Long::class), - // Float Lists - ListTestCase(listOf(1.0f, 2.0f, 3.0f), Float::class), - // Double Lists - ListTestCase(listOf(1.0, 2.0, 3.0), Double::class), - // String Lists - ListTestCase(listOf("value1", "value2", "value3"), String::class), - // ByteArray Lists - ListTestCase(listOf(byteArrayOf(1, 2, 3), byteArrayOf(4, 5, 6)), ByteArray::class), - ) - } - - @JvmStatic - fun mapTestCases(): List> { - return listOf( - // Byte Keys - MapTestCase(mapOf(1.toByte() to "value1", 2.toByte() to "value2"), Byte::class, String::class), - MapTestCase(mapOf(1.toByte() to 1.toByte(), 2.toByte() to 2.toByte()), Byte::class, Byte::class), - MapTestCase(mapOf(1.toByte() to 1.toShort(), 2.toByte() to 2.toShort()), Byte::class, Short::class), - MapTestCase(mapOf(1.toByte() to 1, 2.toByte() to 2), Byte::class, Int::class), - MapTestCase(mapOf(1.toByte() to 1L, 2.toByte() to 2L), Byte::class, Long::class), - MapTestCase(mapOf(1.toByte() to 1.0f, 2.toByte() to 2.0f), Byte::class, Float::class), - MapTestCase(mapOf(1.toByte() to 1.0, 2.toByte() to 2.0), Byte::class, Double::class), - MapTestCase(mapOf(1.toByte() to byteArrayOf(1, 2, 3), 2.toByte() to byteArrayOf(4, 5, 6)), Byte::class, ByteArray::class), - - // Short Keys - MapTestCase(mapOf(1.toShort() to "value1", 2.toShort() to "value2"), Short::class, String::class), - MapTestCase(mapOf(1.toShort() to 1.toByte(), 2.toShort() to 2.toByte()), Short::class, Byte::class), - MapTestCase(mapOf(1.toShort() to 1.toShort(), 2.toShort() to 2.toShort()), Short::class, Short::class), - MapTestCase(mapOf(1.toShort() to 1, 2.toShort() to 2), Short::class, Int::class), - MapTestCase(mapOf(1.toShort() to 1L, 2.toShort() to 2L), Short::class, Long::class), - MapTestCase(mapOf(1.toShort() to 1.0f, 2.toShort() to 2.0f), Short::class, Float::class), - MapTestCase(mapOf(1.toShort() to 1.0, 2.toShort() to 2.0), Short::class, Double::class), - MapTestCase(mapOf(1.toShort() to byteArrayOf(1, 2, 3), 2.toShort() to byteArrayOf(4, 5, 6)), Short::class, ByteArray::class), - - // Int Keys - MapTestCase(mapOf(1 to "value1", 2 to "value2"), Int::class, String::class), - MapTestCase(mapOf(1 to 1.toByte(), 2 to 2.toByte()), Int::class, Byte::class), - MapTestCase(mapOf(1 to 1.toShort(), 2 to 2.toShort()), Int::class, Short::class), - MapTestCase(mapOf(1 to 1, 2 to 2), Int::class, Int::class), - MapTestCase(mapOf(1 to 1L, 2 to 2L), Int::class, Long::class), - MapTestCase(mapOf(1 to 1.0f, 2 to 2.0f), Int::class, Float::class), - MapTestCase(mapOf(1 to 1.0, 2 to 2.0), Int::class, Double::class), - MapTestCase(mapOf(1 to byteArrayOf(1, 2, 3), 2 to byteArrayOf(4, 5, 6)), Int::class, ByteArray::class), - - // Long Keys - MapTestCase(mapOf(1L to "value1", 2L to "value2"), Long::class, String::class), - MapTestCase(mapOf(1L to 1.toByte(), 2L to 2.toByte()), Long::class, Byte::class), - MapTestCase(mapOf(1L to 1.toShort(), 2L to 2.toShort()), Long::class, Short::class), - MapTestCase(mapOf(1L to 1, 2L to 2), Long::class, Int::class), - MapTestCase(mapOf(1L to 1L, 2L to 2L), Long::class, Long::class), - MapTestCase(mapOf(1L to 1.0f, 2L to 2.0f), Long::class, Float::class), - MapTestCase(mapOf(1L to 1.0, 2L to 2.0), Long::class, Double::class), - MapTestCase(mapOf(1L to byteArrayOf(1, 2, 3), 2L to byteArrayOf(4, 5, 6)), Long::class, ByteArray::class), - - // Float Keys - MapTestCase(mapOf(1.0f to "value1", 2.0f to "value2"), Float::class, String::class), - MapTestCase(mapOf(1.0f to 1.toByte(), 2.0f to 2.toByte()), Float::class, Byte::class), - MapTestCase(mapOf(1.0f to 1.toShort(), 2.0f to 2.toShort()), Float::class, Short::class), - MapTestCase(mapOf(1.0f to 1, 2.0f to 2), Float::class, Int::class), - MapTestCase(mapOf(1.0f to 1L, 2.0f to 2L), Float::class, Long::class), - MapTestCase(mapOf(1.0f to 1.0f, 2.0f to 2.0f), Float::class, Float::class), - MapTestCase(mapOf(1.0f to 1.0, 2.0f to 2.0), Float::class, Double::class), - MapTestCase(mapOf(1.0f to byteArrayOf(1, 2, 3), 2.0f to byteArrayOf(4, 5, 6)), Float::class, ByteArray::class), - - // Double Keys - MapTestCase(mapOf(1.0 to "value1", 2.0 to "value2"), Double::class, String::class), - MapTestCase(mapOf(1.0 to 1.toByte(), 2.0 to 2.toByte()), Double::class, Byte::class), - MapTestCase(mapOf(1.0 to 1.toShort(), 2.0 to 2.toShort()), Double::class, Short::class), - MapTestCase(mapOf(1.0 to 1, 2.0 to 2), Double::class, Int::class), - MapTestCase(mapOf(1.0 to 1L, 2.0 to 2L), Double::class, Long::class), - MapTestCase(mapOf(1.0 to 1.0f, 2.0 to 2.0f), Double::class, Float::class), - MapTestCase(mapOf(1.0 to 1.0, 2.0 to 2.0), Double::class, Double::class), - MapTestCase(mapOf(1.0 to byteArrayOf(1, 2, 3), 2.0 to byteArrayOf(4, 5, 6)), Double::class, ByteArray::class), - - // String Keys - MapTestCase(mapOf("key1" to "value1", "key2" to "value2"), String::class, String::class), - MapTestCase(mapOf("key1" to 1.toByte(), "key2" to 2.toByte()), String::class, Byte::class), - MapTestCase(mapOf("key1" to 1.toShort(), "key2" to 2.toShort()), String::class, Short::class), - MapTestCase(mapOf("key1" to 1, "key2" to 2), String::class, Int::class), - MapTestCase(mapOf("key1" to 1L, "key2" to 2L), String::class, Long::class), - MapTestCase(mapOf("key1" to 1.0f, "key2" to 2.0f), String::class, Float::class), - MapTestCase(mapOf("key1" to 1.0, "key2" to 2.0), String::class, Double::class), - MapTestCase(mapOf("key1" to byteArrayOf(1, 2, 3), "key2" to byteArrayOf(4, 5, 6)), String::class, ByteArray::class), - - // ByteArray Keys - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to "value1", byteArrayOf(4, 5, 6) to "value2"), ByteArray::class, String::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1.toByte(), byteArrayOf(4, 5, 6) to 2.toByte()), ByteArray::class, Byte::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1.toShort(), byteArrayOf(4, 5, 6) to 2.toShort()), ByteArray::class, Short::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1, byteArrayOf(4, 5, 6) to 2), ByteArray::class, Int::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1L, byteArrayOf(4, 5, 6) to 2L), ByteArray::class, Long::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1.0f, byteArrayOf(4, 5, 6) to 2.0f), ByteArray::class, Float::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to 1.0, byteArrayOf(4, 5, 6) to 2.0), ByteArray::class, Double::class), - MapTestCase(mapOf(byteArrayOf(1, 2, 3) to byteArrayOf(1, 2, 3), byteArrayOf(4, 5, 6) to byteArrayOf(4, 5, 6)), ByteArray::class, ByteArray::class), - ) - } - } - - @ParameterizedTest - @MethodSource("simpleTestCases") - fun serializationAndDeserialization_simpleTest(testCase: SimpleTestCase) { - val originalItem = testCase.originalItem - val clazz = testCase.clazz - - val bytes = zSerialize(originalItem, clazz = clazz).getOrThrow() - val deserializedItem = zDeserialize(bytes, clazz = clazz).getOrThrow() - - if (originalItem is ByteArray) { - assertArrayEquals(originalItem, deserializedItem as ByteArray) - } else { - assertEquals(originalItem, deserializedItem) - } - } - - @ParameterizedTest - @MethodSource("listTestCases") - fun serializationAndDeserialization_listTest(testCase: ListTestCase) { - val originalList = testCase.originalList - val itemClass = testCase.itemclazz - - val bytes = zSerialize(originalList).getOrThrow() - - val deserializedList = zDeserialize(bytes, clazz = List::class, arg1clazz = itemClass).getOrThrow() - - if (originalList.isNotEmpty() && originalList[0] is ByteArray) { - originalList.forEachIndexed { index, value -> - assertArrayEquals(value as ByteArray, deserializedList[index] as ByteArray) - } - } else { - assertEquals(originalList, deserializedList) - } - } - - @ParameterizedTest - @MethodSource("mapTestCases") - fun serializationAndDeserialization_mapTest(testCase: MapTestCase) { - val originalMap = testCase.originalMap - val keyClass = testCase.keyclazz - val valueClass = testCase.valueclazz - - val bytes = zSerialize(originalMap).getOrThrow() - - val deserializedMap = zDeserialize( - bytes, - clazz = Map::class, - arg1clazz = keyClass, - arg2clazz = valueClass - ).getOrThrow() - - if (keyClass == ByteArray::class && valueClass != ByteArray::class) { - val map1 = originalMap.map { (k, v) -> (k as ByteArray).toList() to v }.toMap() - val map2 = originalMap.map { (k, v) -> (k as ByteArray).toList() to v }.toMap() - assertEquals(map1, map2) - return - } - - if (keyClass != ByteArray::class && valueClass == ByteArray::class) { - val map1 = originalMap.map { (k, v) -> k to (v as ByteArray).toList() }.toMap() - val map2 = originalMap.map { (k, v) -> k to (v as ByteArray).toList() }.toMap() - assertEquals(map1, map2) - return - } - - if (keyClass == ByteArray::class && valueClass == ByteArray::class) { - val map1 = originalMap.map { (k, v) -> (k as ByteArray).toList() to (v as ByteArray).toList() }.toMap() - val map2 = originalMap.map { (k, v) -> (k as ByteArray).toList() to (v as ByteArray).toList() }.toMap() - assertEquals(map1, map2) - return - } - - assertEquals(originalMap, deserializedMap) - } - /** * A series of tests to verify the correct functioning of the [zDeserialize] function. * @@ -253,216 +30,187 @@ class ZBytesTests { * it uses reified parameters which causes the testing framework (designed for Java) to fail to properly * set up the tests. */ - @Test - fun serializationAndDeserializationWithReification() { - /*********************************************** - * Standard serialization and deserialization. * - ***********************************************/ - /** Numeric: byte, short, int, float, double */ + /*********************************************** + * Standard serialization and deserialization. * + ***********************************************/ + + @Test + fun `test int serialization and deserialization`() { val intInput = 1234 - var payload = ZBytes.from(intInput) + val payload = zSerialize(intInput).getOrThrow() val intOutput = zDeserialize(payload).getOrThrow() assertEquals(intInput, intOutput) + } - // Another example with float + @Test + fun `test float serialization and deserialization`() { val floatInput = 3.1415f - payload = ZBytes.from(floatInput) + val payload = zSerialize(floatInput).getOrThrow() val floatOutput = zDeserialize(payload).getOrThrow() assertEquals(floatInput, floatOutput) + } - /** String serialization and deserialization. */ + @Test + fun `test string serialization and deserialization`() { val stringInput = "example" - payload = ZBytes.from(stringInput) + val payload = zSerialize(stringInput).getOrThrow() val stringOutput = zDeserialize(payload).getOrThrow() assertEquals(stringInput, stringOutput) + } - /** ByteArray serialization and deserialization. */ + @Test + fun `test byte array serialization and deserialization`() { val byteArrayInput = "example".toByteArray() - payload = ZBytes.from(byteArrayInput) // Equivalent to `byteArrayInput.into()` + val payload = zSerialize(byteArrayInput).getOrThrow() val byteArrayOutput = zDeserialize(payload).getOrThrow() assertTrue(byteArrayInput.contentEquals(byteArrayOutput)) + } + @Test + fun `test list of strings serialization and deserialization`() { val inputList = listOf("sample1", "sample2", "sample3") - payload = zSerialize(inputList).getOrThrow() + val payload = zSerialize(inputList).getOrThrow() val outputList = zDeserialize>(payload).getOrThrow() assertEquals(inputList, outputList) + } - val inputListZBytes = inputList.map { value -> value.into() } - payload = zSerialize(inputListZBytes).getOrThrow() - val outputListZBytes = zDeserialize>(payload).getOrThrow() - assertEquals(inputListZBytes, outputListZBytes) - - val inputListByteArray = inputList.map { value -> value.toByteArray() } - payload = zSerialize(inputListByteArray).getOrThrow() + @Test + fun `test list of byte arrays serialization and deserialization`() { + val inputListByteArray = listOf("sample1", "sample2", "sample3").map { it.toByteArray() } + val payload = zSerialize(inputListByteArray).getOrThrow() val outputListByteArray = zDeserialize>(payload).getOrThrow() assertTrue(compareByteArrayLists(inputListByteArray, outputListByteArray)) + } + @Test + fun `test map of strings serialization and deserialization`() { val inputMap = mapOf("key1" to "value1", "key2" to "value2", "key3" to "value3") - payload = zSerialize(inputMap).getOrThrow() + val payload = zSerialize(inputMap).getOrThrow() val outputMap = zDeserialize>(payload).getOrThrow() assertEquals(inputMap, outputMap) - - val combinedInputMap = mapOf("key1" to ZBytes.from("zbytes1"), "key2" to ZBytes.from("zbytes2")) - payload = zSerialize(combinedInputMap).getOrThrow() - val combinedOutputMap = zDeserialize>(payload).getOrThrow() - assertEquals(combinedInputMap, combinedOutputMap) } - /***************** - * Testing utils * - *****************/ - - /** Example class for the deserialization map examples. */ - class Foo(val content: String) { - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Foo + /********************************************** + * Additional test cases for new Kotlin types * + **********************************************/ - return content == other.content - } - - override fun hashCode(): Int { - return content.hashCode() - } + @Test + fun `test boolean serialization and deserialization`() { + val booleanInput = true + val payload = zSerialize(booleanInput).getOrThrow() + val booleanOutput = zDeserialize(payload).getOrThrow() + assertEquals(booleanInput, booleanOutput) } - private fun compareByteArrayLists(list1: List, list2: List): Boolean { - if (list1.size != list2.size) { - return false - } - for (i in list1.indices) { - if (!list1[i].contentEquals(list2[i])) { - return false - } - } - return true + @Test + fun `test UByte serialization and deserialization`() { + val ubyteInput: UByte = 100u + val payload = zSerialize(ubyteInput).getOrThrow() + val ubyteOutput = zDeserialize(payload).getOrThrow() + assertEquals(ubyteInput, ubyteOutput) } - - /********************************************************************************** - * Serializers and deserializers for testing the functionality of deserialization * - * with deserializer functions. * - **********************************************************************************/ - - private fun serializeFooMap(testMap: Map): ByteArray { - return testMap.map { - val key = it.key.content.toByteArray() - val keyLength = ByteBuffer.allocate(Int.SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(key.size).array() - val value = it.value.content.toByteArray() - val valueLength = - ByteBuffer.allocate(Int.SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(value.size).array() - keyLength + key + valueLength + value - }.reduce { acc, bytes -> acc + bytes } + @Test + fun `test UShort serialization and deserialization`() { + val ushortInput: UShort = 300u + val payload = zSerialize(ushortInput).getOrThrow() + val ushortOutput = zDeserialize(payload).getOrThrow() + assertEquals(ushortInput, ushortOutput) } - private fun deserializeFooMap(serializedMap: ZBytes): Map { - var idx = 0 - var sliceSize: Int - val bytes = serializedMap.toByteArray() - val decodedMap = mutableMapOf() - while (idx < bytes.size) { - sliceSize = ByteBuffer.wrap(bytes.sliceArray(IntRange(idx, idx + Int.SIZE_BYTES - 1))) - .order(ByteOrder.LITTLE_ENDIAN).int - idx += Int.SIZE_BYTES - - val key = bytes.sliceArray(IntRange(idx, idx + sliceSize - 1)) - idx += sliceSize - - sliceSize = ByteBuffer.wrap(bytes.sliceArray(IntRange(idx, idx + Int.SIZE_BYTES - 1))).order( - ByteOrder.LITTLE_ENDIAN - ).int - idx += Int.SIZE_BYTES - - val value = bytes.sliceArray(IntRange(idx, idx + sliceSize - 1)) - idx += sliceSize - - decodedMap[Foo(key.decodeToString())] = Foo(value.decodeToString()) - } - return decodedMap + @Test + fun `test UInt serialization and deserialization`() { + val uintInput: UInt = 123456789u + val payload = zSerialize(uintInput).getOrThrow() + val uintOutput = zDeserialize(payload).getOrThrow() + assertEquals(uintInput, uintOutput) } - private fun serializeZBytesMap(testMap: Map): ZBytes { - return testMap.map { - val key = it.key.bytes - val keyLength = ByteBuffer.allocate(Int.SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(key.size).array() - val value = it.value.bytes - val valueLength = - ByteBuffer.allocate(Int.SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(value.size).array() - keyLength + key + valueLength + value - }.reduce { acc, bytes -> acc + bytes }.into() + @Test + fun `test ULong serialization and deserialization`() { + val ulongInput: ULong = 9876543210uL + val payload = zSerialize(ulongInput).getOrThrow() + val ulongOutput = zDeserialize(payload).getOrThrow() + assertEquals(ulongInput, ulongOutput) } - private fun deserializeIntoZBytesMap(serializedMap: ZBytes): Map { - var idx = 0 - var sliceSize: Int - val decodedMap = mutableMapOf() - while (idx < serializedMap.bytes.size) { - sliceSize = ByteBuffer.wrap(serializedMap.bytes.sliceArray(IntRange(idx, idx + Int.SIZE_BYTES - 1))) - .order(ByteOrder.LITTLE_ENDIAN).int - idx += Int.SIZE_BYTES - - val key = serializedMap.bytes.sliceArray(IntRange(idx, idx + sliceSize - 1)) - idx += sliceSize + @Test + fun `test Pair serialization and deserialization`() { + val pairInput = Pair(42, 0.5) + val payload = zSerialize(pairInput).getOrThrow() + val pairOutput = zDeserialize>(payload).getOrThrow() + assertEquals(pairInput, pairOutput) + } - sliceSize = ByteBuffer.wrap(serializedMap.bytes.sliceArray(IntRange(idx, idx + Int.SIZE_BYTES - 1))).order( - ByteOrder.LITTLE_ENDIAN - ).int - idx += Int.SIZE_BYTES + @Test + fun `test Triple serialization and deserialization`() { + val tripleInput = Triple(42, 0.5, listOf(true, false)) + val payload = zSerialize(tripleInput).getOrThrow() + val tripleOutput = zDeserialize>>(payload).getOrThrow() + assertEquals(tripleInput, tripleOutput) + } - val value = serializedMap.bytes.sliceArray(IntRange(idx, idx + sliceSize - 1)) - idx += sliceSize + /********************************************** + * Tests for collections with new types * + **********************************************/ - decodedMap[key.into()] = value.into() - } - return decodedMap + @Test + fun `test list of booleans serialization and deserialization`() { + val listBooleanInput = listOf(true, false, true) + val payload = zSerialize(listBooleanInput).getOrThrow() + val listBooleanOutput = zDeserialize>(payload).getOrThrow() + assertEquals(listBooleanInput, listBooleanOutput) } - private fun serializeIntoIntMap(intMap: Map): ZBytes { - val zBytesMap = intMap.map { (k, v) -> k.into() to v.into() }.toMap() - return serializeZBytesMap(zBytesMap) + @Test + fun `test map of string to ULong serialization and deserialization`() { + val mapStringULongInput = mapOf("key1" to 1uL, "key2" to 2uL, "key3" to 3uL) + val payload = zSerialize(mapStringULongInput).getOrThrow() + val mapStringULongOutput = zDeserialize>(payload).getOrThrow() + assertEquals(mapStringULongInput, mapStringULongOutput) } - private fun deserializeIntoStringMap(serializerMap: ZBytes): Map { - return deserializeIntoZBytesMap(serializerMap).map { (k, v) -> k.toString() to v.toString() }.toMap() + @Test + fun `test list of maps serialization and deserialization`() { + val listOfMapsInput = listOf( + mapOf("key1" to 1uL, "key2" to 2uL), + mapOf("key3" to 3uL, "key4" to 4uL) + ) + val payload = zSerialize(listOfMapsInput).getOrThrow() + val listOfMapsOutput = zDeserialize>>(payload).getOrThrow() + assertEquals(listOfMapsInput, listOfMapsOutput) } - private fun deserializeIntoIntMap(serializerMap: ZBytes): Map { - return deserializeIntoZBytesMap(serializerMap).map { (k, v) -> - zDeserialize(k).getOrThrow() to zDeserialize(v).getOrThrow() - }.toMap() + @Test + fun `test map of string to list of int serialization and deserialization`() { + val mapOfListInput = mapOf("numbers" to listOf(1, 2, 3, 4, 5)) + val payload = zSerialize(mapOfListInput).getOrThrow() + val mapOfListOutput = zDeserialize>>(payload).getOrThrow() + assertEquals(mapOfListInput, mapOfListOutput) } - private fun serializeZBytesList(list: List): ZBytes { - return list.map { - val item = it.bytes - val itemLength = - ByteBuffer.allocate(Int.SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN).putInt(item.size).array() - itemLength + item - }.reduce { acc, bytes -> acc + bytes }.into() + @Test + fun `test nested pairs serialization and deserialization`() { + val pairInput = Pair(42, Pair(0.5, true)) + val payload = zSerialize(pairInput).getOrThrow() + val pairOutput = zDeserialize>>(payload).getOrThrow() + assertEquals(pairInput, pairOutput) } - private fun deserializeIntoZBytesList(serializedList: ZBytes): List { - var idx = 0 - var sliceSize: Int - val decodedList = mutableListOf() - while (idx < serializedList.bytes.size) { - sliceSize = ByteBuffer.wrap(serializedList.bytes.sliceArray(IntRange(idx, idx + Int.SIZE_BYTES - 1))) - .order(ByteOrder.LITTLE_ENDIAN).int - idx += Int.SIZE_BYTES - - val item = serializedList.bytes.sliceArray(IntRange(idx, idx + sliceSize - 1)) - idx += sliceSize + /***************** + * Testing utils * + *****************/ - decodedList.add(item.into()) + private fun compareByteArrayLists(list1: List, list2: List): Boolean { + if (list1.size != list2.size) { + return false } - return decodedList - } - - private fun deserializeIntoListOfPairs(serializedList: ZBytes): List> { - return deserializeIntoZBytesMap(serializedList).map { (k, v) -> k to v } + for (i in list1.indices) { + if (!list1[i].contentEquals(list2[i])) { + return false + } + } + return true } }