From 3a5fdfbe4467812c7df5c548b5a83774dd167275 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 16:07:37 +0200 Subject: [PATCH 1/6] Serialize via the shared pure-Kotlin SerializationCodec (no JNI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the per-element JNI serialization (serializeViaJNI) with the shared pure-Kotlin SerializationCodec. ZSerializer/ZDeserializer build a SerializationCodec.SerdeType from the Guava TypeToken's java.lang.reflect.Type (serdeTypeOfJava) and call the shared codec through the SAME throwZError0 error handler used for generated wrappers (the codec never throws — it invokes the handler, which throws ZError), so the hand-written serializer is wired exactly like a generated one. No duplication — the same codec zenoh-kotlin uses. Full jvmTest: 120 pass (the 10 ZBytes tests now run via pure Kotlin). The Type path's supported set is unchanged (signed/collection; Java can't express the unsigned/Pair/Triple types the KType path adds). Depends on the zenoh-flat-jni SerializationCodec commit. Co-Authored-By: Claude Opus 4.8 --- .../kotlin/io/zenoh/ext/JavaTypeSerde.kt | 55 +++++++++++++++++++ .../kotlin/io/zenoh/ext/ZDeserializer.kt | 4 +- .../kotlin/io/zenoh/ext/ZSerializer.kt | 4 +- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 zenoh-java/src/commonMain/kotlin/io/zenoh/ext/JavaTypeSerde.kt diff --git a/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/JavaTypeSerde.kt b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/JavaTypeSerde.kt new file mode 100644 index 00000000..c8d16e5c --- /dev/null +++ b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/JavaTypeSerde.kt @@ -0,0 +1,55 @@ +// +// Copyright (c) 2026 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.ext + +import io.zenoh.exceptions.ZError +import io.zenoh.jni.bytes.SerializationCodec +import java.lang.reflect.ParameterizedType +import java.lang.reflect.Type + +/** + * Build a [SerializationCodec.SerdeType] from a Guava `TypeToken`'s + * [java.lang.reflect.Type] — the reflection adapter for zenoh-java's serializer. + * Handles `Class` and `ParameterizedType` for `List`/`Map`; the Kotlin-only + * unsigned value classes and `Pair`/`Triple` erase in the Java reflection + * representation and are not expressible here. Throws [ZError] on an + * unsupported type (argument preparation — before the byte codec runs). + */ +internal fun serdeTypeOfJava(type: Type): SerializationCodec.SerdeType = when (type) { + is Class<*> -> when (type.name) { + "java.lang.Boolean", "boolean" -> SerializationCodec.SerdeType.Bool + "java.lang.Byte", "byte" -> SerializationCodec.SerdeType.I8 + "java.lang.Short", "short" -> SerializationCodec.SerdeType.I16 + "java.lang.Integer", "int" -> SerializationCodec.SerdeType.I32 + "java.lang.Long", "long" -> SerializationCodec.SerdeType.I64 + "java.lang.Float", "float" -> SerializationCodec.SerdeType.F32 + "java.lang.Double", "double" -> SerializationCodec.SerdeType.F64 + "java.lang.String" -> SerializationCodec.SerdeType.Str + "[B" -> SerializationCodec.SerdeType.Bytes + else -> throw ZError("Unsupported type: ${type.name}") + } + is ParameterizedType -> { + val raw = type.rawType as? Class<*> ?: throw ZError("Unsupported raw type: ${type.rawType}") + val args = type.actualTypeArguments + when { + List::class.java.isAssignableFrom(raw) && args.size == 1 -> + SerializationCodec.SerdeType.ZList(serdeTypeOfJava(args[0])) + Map::class.java.isAssignableFrom(raw) && args.size == 2 -> + SerializationCodec.SerdeType.ZMap(serdeTypeOfJava(args[0]), serdeTypeOfJava(args[1])) + else -> throw ZError("Unsupported parameterized type: ${raw.name}") + } + } + else -> throw ZError("Unsupported type: $type") +} diff --git a/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZDeserializer.kt b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZDeserializer.kt index 984778b0..91d8cbd7 100644 --- a/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZDeserializer.kt +++ b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZDeserializer.kt @@ -18,7 +18,7 @@ import com.google.common.reflect.TypeToken import io.zenoh.bytes.IntoZBytes import io.zenoh.bytes.ZBytes import io.zenoh.exceptions.throwZError0 -import io.zenoh.jni.bytes.deserializeViaJNI +import io.zenoh.jni.bytes.SerializationCodec /** * Zenoh deserializer. @@ -107,6 +107,6 @@ abstract class ZDeserializer: TypeToken() { */ fun deserialize(zbytes: IntoZBytes): T { @Suppress("UNCHECKED_CAST") - return deserializeViaJNI(zbytes.into().bytes, this.type, throwZError0) as T + return SerializationCodec.deserialize(zbytes.into().bytes, serdeTypeOfJava(this.type), throwZError0) as T } } diff --git a/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZSerializer.kt b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZSerializer.kt index 8a7a1b6e..98cf5ade 100644 --- a/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZSerializer.kt +++ b/zenoh-java/src/commonMain/kotlin/io/zenoh/ext/ZSerializer.kt @@ -17,7 +17,7 @@ package io.zenoh.ext import com.google.common.reflect.TypeToken import io.zenoh.bytes.ZBytes import io.zenoh.exceptions.throwZError0 -import io.zenoh.jni.bytes.serializeViaJNI +import io.zenoh.jni.bytes.SerializationCodec /** * Zenoh serializer. @@ -105,6 +105,6 @@ abstract class ZSerializer: TypeToken() { * Serialize [t] into a [ZBytes]. */ fun serialize(t: T): ZBytes { - return ZBytes.from(serializeViaJNI(t as Any, this.type, throwZError0)) + return ZBytes.from(SerializationCodec.serialize(t as Any, serdeTypeOfJava(this.type), throwZError0)) } } From ce7f32a465ffa752fa19fe2feb98f3a94d297756 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 16:40:07 +0200 Subject: [PATCH 2/6] ci: bump zenoh-flat-jni pin to the pure-Kotlin serializer commit The pure-Kotlin SerializationCodec this branch delegates to lives in zenoh-flat-jni#13 (db4fb2d). Point CI at it so the composite build has the shared codec. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3265d3f..d15a6a53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 with: repository: ZettaScaleLabs/zenoh-flat-jni - ref: 249fe9e34ac5d05bc442355fd216a324114e2621 + ref: db4fb2d257f8363fad7bdea87bb75c5e9baa7d94 path: zenoh-flat-jni - name: Check out zenoh-flat From e662bf597db621ae2145544af94aef54bbcd0991 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 18:00:47 +0200 Subject: [PATCH 3/6] ci: repoint zenoh-flat-jni pin to the rebased serializer commit The zenoh-flat-jni serialization PR was rebased onto main (conflict resolution), changing the SerializationCodec commit SHA. Repoint CI at the current commit. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d15a6a53..249aa55e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 with: repository: ZettaScaleLabs/zenoh-flat-jni - ref: db4fb2d257f8363fad7bdea87bb75c5e9baa7d94 + ref: ce08a4b4d1cc7a51bc4b93879342048446b22ac2 path: zenoh-flat-jni - name: Check out zenoh-flat From 52e926d1b190218aa43eacff06fe41f5a3508a2e Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 21:45:43 +0200 Subject: [PATCH 4/6] Drop correspondence tests moved down to zenoh-flat-jni MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Parameters/Encoding/ZenohId correspondence tests moved into zenoh-flat-jni's own test suite (it now self-verifies its pure implementations against the native oracle, which relocated to the internal io.zenoh.jni.test package). SDK production is unaffected — it uses the pure io.zenoh.jni.query.Parameters and the generated Encoding/ZenohId handles, all unchanged. Co-Authored-By: Claude Opus 4.8 --- .../io/zenoh/EncodingCorrespondenceTest.kt | 117 ------------ .../io/zenoh/ParametersCorrespondenceTest.kt | 167 ------------------ .../io/zenoh/ZenohIdCorrespondenceTest.kt | 58 ------ 3 files changed, 342 deletions(-) delete mode 100644 zenoh-java/src/jvmTest/kotlin/io/zenoh/EncodingCorrespondenceTest.kt delete mode 100644 zenoh-java/src/jvmTest/kotlin/io/zenoh/ParametersCorrespondenceTest.kt delete mode 100644 zenoh-java/src/jvmTest/kotlin/io/zenoh/ZenohIdCorrespondenceTest.kt diff --git a/zenoh-java/src/jvmTest/kotlin/io/zenoh/EncodingCorrespondenceTest.kt b/zenoh-java/src/jvmTest/kotlin/io/zenoh/EncodingCorrespondenceTest.kt deleted file mode 100644 index 143002f3..00000000 --- a/zenoh-java/src/jvmTest/kotlin/io/zenoh/EncodingCorrespondenceTest.kt +++ /dev/null @@ -1,117 +0,0 @@ -// -// 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.Encoding -import io.zenoh.exceptions.throwZError0 -import io.zenoh.jni.bytes.Encoding as JniEncoding -import org.junit.Assert.assertEquals -import org.junit.Test - -/** - * Correspondence tests for the pure-JVM [Encoding] implementation. - * - * The SDK implements the encoding string ↔ `(id, schema)` conversion in pure - * Kotlin (no JNI crossing), on the contract that any JVM-side reimplementation - * of zenoh-flat API must be verified against the native implementation. These - * tests drive both implementations — the pure one and the native one (the - * generated `Encoding` handle methods) — over the whole predefined id range - * plus the edge shapes of the parse/render rules, asserting equal results. - */ -class EncodingCorrespondenceTest { - - /** Native implementation: the canonical string of `(id, schema)`. */ - private fun nativeRender(id: Int, schema: String?): String { - val h = JniEncoding.newFromId(id, schema, throwZError0) - try { - return h.toStr(throwZError0) - } finally { - h.close() - } - } - - /** Native implementation: parse a string into `(id, schema, canonical string)`. */ - private fun nativeParse(s: String): Triple { - val h = JniEncoding.newFromString(s, throwZError0) - try { - return Triple(h.getId(throwZError0), h.getSchema(throwZError0), h.toStr(throwZError0)) - } finally { - h.close() - } - } - - @Test - fun renderMatchesNativeAcrossIdRange() { - // The whole predefined range, a gap past it (unknown ids), and the - // custom id — with and without a schema. - val ids = (0..64) + listOf(1000, 0xFFFE, 0xFFFF) - for (id in ids) { - for (schema in listOf(null, "utf-8")) { - assertEquals( - "render mismatch for (id=$id, schema=$schema)", - nativeRender(id, schema), - Encoding(id, schema).toString(), - ) - } - } - } - - @Test - fun parseMatchesNativeOnNamesAndEdges() { - // Every predefined canonical name (obtained FROM the native table so the - // corpus can't drift), plus the parse-rule edge shapes. - val names = (0..52).map { nativeRender(it, null) } - val edges = listOf( - "", - "text/plain", - "text/plain;utf-8", - "text/plain;", - "my_custom_encoding", - "custom;with;semicolons", - ";leading_separator", - "unknown_name;schema", - "zenoh/bytes;s", - ) - for (s in names + names.map { "$it;schema" } + edges) { - val (nid, nschema, nstr) = nativeParse(s) - val pure = Encoding.from(s) - assertEquals("id mismatch for \"$s\"", nid, pure.id) - assertEquals("schema mismatch for \"$s\"", nschema, pure.schema) - assertEquals("render mismatch for \"$s\"", nstr, pure.toString()) - } - } - - @Test - fun withSchemaMatchesNative() { - val bases = listOf( - Encoding.TEXT_PLAIN, - Encoding.ZENOH_BYTES, - Encoding.from("my_custom_encoding"), - Encoding.from("text/plain;old-schema"), - ) - for (base in bases) { - val pure = base.withSchema("new-schema") - // The `e` param crosses on the selector's value arm as its - // decomposed (id, schema) pair. - val w = JniEncoding.newWithSchema(0, base.id, base.schema, null, "new-schema", throwZError0) - val nativeStr = try { - w.toStr(throwZError0) - } finally { - w.close() - } - assertEquals("withSchema mismatch for $base", nativeStr, pure.toString()) - } - } -} diff --git a/zenoh-java/src/jvmTest/kotlin/io/zenoh/ParametersCorrespondenceTest.kt b/zenoh-java/src/jvmTest/kotlin/io/zenoh/ParametersCorrespondenceTest.kt deleted file mode 100644 index b56bfcf7..00000000 --- a/zenoh-java/src/jvmTest/kotlin/io/zenoh/ParametersCorrespondenceTest.kt +++ /dev/null @@ -1,167 +0,0 @@ -// -// Copyright (c) 2026 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.exceptions.throwZError0 -import io.zenoh.jni.query.Parameters as JniParameters -import io.zenoh.jni.query.parametersContainsKey -import io.zenoh.jni.query.parametersExtend -import io.zenoh.jni.query.parametersGet -import io.zenoh.jni.query.parametersInsert -import io.zenoh.jni.query.parametersIsWellFormed -import io.zenoh.jni.query.parametersRemove -import io.zenoh.jni.query.parametersValues -import org.junit.Assert.assertEquals -import org.junit.Test -import kotlin.random.Random - -/** - * Correspondence tests for the shared pure-JVM - * [io.zenoh.jni.query.Parameters] implementation. - * - * zenoh-flat exposes parameters processing as regular API (the `parameters*` - * functions in `io.zenoh.jni.query`, thin wrappers over - * `zenoh::query::Parameters`); the JVM production path runs the same - * semantics in pure Kotlin instead, because crossing JNI per string - * operation is expensive — a JNI peculiarity, not a zenoh-flat design - * choice. On the contract that any pure reimplementation of native - * semantics must be verified against the native implementation, these tests - * drive both over edge shapes and randomized inputs, asserting equal - * results. - */ -class ParametersCorrespondenceTest { - - /** Edge shapes of the format rules. */ - private val edgeCases = listOf( - "", - ";", - ";;", - "a", - "a=", - "=v", - "=", - "a=1", - "a=1;b=2", - "a=1;a=2", - "a=b=c", - "a==", - "k=%zz", - "k=%20", - "flag;a=1", - ";;a=1;;b=2;;", - "c=1|2|3", - "c=|", - "c=ified|", - "ключ=значение", - "a=1;=2;b=3", - " a = 1 ; b = 2 ", - "a;a;a", - "a=1;b;a=2", - ) - - private val keys = listOf("a", "b", "c", "k", "flag", "", "missing", "ключ", " a ") - - private fun assertCorrespondence(s: String) { - val pure = JniParameters.fromString(s) - for (k in keys) { - assertEquals( - "get(\"$k\") diverges for input \"$s\"", - parametersGet(s, k, throwZError0), - pure.get(k), - ) - assertEquals( - "values(\"$k\") diverges for input \"$s\"", - parametersValues(s, k, throwZError0), - pure.values(k), - ) - assertEquals( - "containsKey(\"$k\") diverges for input \"$s\"", - parametersContainsKey(s, k, throwZError0), - pure.containsKey(k), - ) - } - assertEquals( - "isWellFormed diverges for input \"$s\"", - parametersIsWellFormed(s, throwZError0), - pure.isWellFormed(), - ) - for (k in keys) { - assertEquals( - "insert(\"$k\", \"val\") diverges for input \"$s\"", - parametersInsert(s, k, "val", throwZError0), - JniParameters.fromString(s).also { it.insert(k, "val") }.asString(), - ) - } - assertEquals( - "extend diverges for input \"$s\"", - parametersExtend(s, "zk1=zv1;zk2", throwZError0), - JniParameters.fromString(s) - .also { it.extend(JniParameters.fromString("zk1=zv1;zk2")) } - .asString(), - ) - // `remove` is deliberately NOT compared against the native - // implementation: see [nativeRemoveBugCanary]. - } - - @Test - fun edgeCasesMatchNative() { - for (s in edgeCases) { - assertCorrespondence(s) - } - } - - @Test - fun randomizedInputsMatchNative() { - // Random strings over an alphabet dense in separators, so structural - // collisions (duplicate keys, empty chunks, '=' in values) are common. - val alphabet = "ab;=|%; =;" - val rng = Random(20260718) - repeat(500) { - val s = buildString { - repeat(rng.nextInt(0, 24)) { append(alphabet[rng.nextInt(alphabet.length)]) } - } - assertCorrespondence(s) - } - } - - /** The shared implementation follows Rust's DOCUMENTED remove contract - * ("preserving the insertion order"). */ - @Test - fun removeFollowsTheDocumentedContract() { - fun removed(s: String, k: String): String = - JniParameters.fromString(s).also { it.remove(k) }.asString() - - assertEquals("b=2;c=3", removed("b=2;a=1;c=3", "a")) - assertEquals("b=2", removed("a=1;b=2;a=3", "a")) - assertEquals("x=1;y=2", removed("x=1;y=2", "missing")) - assertEquals("", removed("a=1", "a")) - assertEquals("a=1", removed("flag;a=1", "flag")) - assertEquals("1", JniParameters.fromString("b=2;a=1").remove("a")) - } - - /** CANARY: upstream zenoh's `parameters::remove` has an - * iterator-consumption bug — `find` advances past every entry up to and - * including the first match before `filter` builds the result, so - * entries PRECEDING the match are dropped, and removing an absent key - * erases the whole string. The shared implementation intentionally - * diverges (see [removeFollowsTheDocumentedContract]). This test pins - * the buggy native behavior: when upstream fixes it, this test fails — - * then delete it and fold `remove` into [assertCorrespondence]. */ - @Test - fun nativeRemoveBugCanary() { - assertEquals("c=3", parametersRemove("b=2;a=1;c=3", "a", throwZError0)) - assertEquals("", parametersRemove("x=1;y=2", "missing", throwZError0)) - } -} diff --git a/zenoh-java/src/jvmTest/kotlin/io/zenoh/ZenohIdCorrespondenceTest.kt b/zenoh-java/src/jvmTest/kotlin/io/zenoh/ZenohIdCorrespondenceTest.kt deleted file mode 100644 index f531c240..00000000 --- a/zenoh-java/src/jvmTest/kotlin/io/zenoh/ZenohIdCorrespondenceTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -// -// 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.config.ZenohId -import io.zenoh.exceptions.throwZError0 -import io.zenoh.jni.config.ZenohId as JniZenohId -import kotlin.random.Random -import org.junit.Assert.assertEquals -import org.junit.Test - -/** - * Correspondence test for the pure-JVM [ZenohId.toString] — the id bytes read - * as a little-endian integer, rendered as lowercase hex without leading zeros - * (`"0"` for the zero id). Verified against the native formatter - * (`zenoh_id_to_string`) over edge patterns and a deterministic random corpus. - */ -class ZenohIdCorrespondenceTest { - - private fun assertCorresponds(bytes: ByteArray) { - val jni = JniZenohId(bytes) - assertEquals( - "zid render mismatch for ${bytes.joinToString(",")}", - jni.toStr(throwZError0), - ZenohId(jni).toString(), - ) - } - - @Test - fun rendersLikeNative() { - val edges = listOf( - ByteArray(16), // zero id - ByteArray(16).also { it[0] = 1 }, // smallest nonzero (LE low byte) - ByteArray(16).also { it[15] = 1 }, // highest byte only - ByteArray(16).also { it[0] = 0x0F }, // sub-0x10 low byte - ByteArray(16) { 0xFF.toByte() }, // all ones - ByteArray(16) { i -> i.toByte() }, // ascending with leading zero byte - ) - edges.forEach(::assertCorresponds) - - val rng = Random(20260716) - repeat(32) { - assertCorresponds(rng.nextBytes(16)) - } - } -} From a495244d621350ef260a68dc3f875f6832889c61 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 21:50:16 +0200 Subject: [PATCH 5/6] ci: bump zenoh-flat-jni pin to the test-package/self-verify commit zenoh-flat-jni moved its native oracle to the internal io.zenoh.jni.test package and added self-verifying correspondence tests. Point CI at that commit. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 249aa55e..81319f15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 with: repository: ZettaScaleLabs/zenoh-flat-jni - ref: ce08a4b4d1cc7a51bc4b93879342048446b22ac2 + ref: 2755c06921b14f7758d4fc485b256d3f5ccdf997 path: zenoh-flat-jni - name: Check out zenoh-flat From f8f17488873b96168549a8c3e534e49d2a0194f7 Mon Sep 17 00:00:00 2001 From: Michael Ilyin Date: Tue, 21 Jul 2026 23:37:58 +0200 Subject: [PATCH 6/6] ci: bump zenoh-flat-jni pin to merged main (71736f2) zenoh-flat-jni #13 squash-merged to main as 71736f2. Re-pin from the pre-merge branch commit 2755c06 (an orphan once the pure-kotlin-serde branch is deleted) to the permanent main commit, which also carries the final merged SerializationCodec (strict UTF-8). Co-Authored-By: Claude Opus 4.8 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 81319f15..685aeeef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 with: repository: ZettaScaleLabs/zenoh-flat-jni - ref: 2755c06921b14f7758d4fc485b256d3f5ccdf997 + ref: 71736f2bffcd9889f213dcc83b31a696e2abf51e path: zenoh-flat-jni - name: Check out zenoh-flat