Skip to content

Commit f885561

Browse files
committed
nested output
1 parent c5a5353 commit f885561

4 files changed

Lines changed: 50 additions & 11 deletions

File tree

zenoh-flat-jni/build.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ fn main() {
122122
.package_fun(pq!(z_encoding_to_string))
123123
.package_fun(pq!(z_encoding_clone))
124124
.package_fun(pq!(z_encoding_from_string))
125+
// Combined ACCESSOR for ZEncoding (output expansion): decompose to its
126+
// canonical string (`z_encoding_to_string`), nested by the ZSample
127+
// combined accessor below to build the SDK `Encoding(string)`.
128+
.combined_accessor(pq!(ZEncoding))
129+
.combined_accessor_record(pq!(z_encoding_to_string))
125130
// Single constructor for ZEncoding: encoding params accept a `String`
126131
// (built via z_encoding_from_string) directly — the SDK passes its
127132
// canonical `repr` String, no per-call `zEncodingFromString` + close.
@@ -207,6 +212,22 @@ fn main() {
207212
.package_fun(pq!(z_sample_congestion_control))
208213
.package_fun(pq!(z_sample_attachment))
209214
.expand_output() // Option<&ZZBytes> → builder (ByteArray) → R?
215+
// Combined ACCESSOR for ZSample (output expansion, M3): the full sample
216+
// decomposed in ONE crossing — NESTS the ZKeyExpr (handle+string),
217+
// ZZBytes (payload bytes), ZEncoding (string) and ZTimestamp (ntp64,
218+
// nullable) combined accessors, plus enum leaves (kind/priority/
219+
// congestion → Int) and `express` (bool). Record order = builder arg
220+
// order. Used by `z_reply_sample` below to build a full SDK `Sample`.
221+
.combined_accessor(pq!(ZSample))
222+
.combined_accessor_record_nested(pq!(z_sample_key_expr)) // → (ZKeyExpr, String)
223+
.combined_accessor_record_nested(pq!(z_sample_payload)) // → ByteArray
224+
.combined_accessor_record_nested(pq!(z_sample_encoding)) // → String
225+
.combined_accessor_record(pq!(z_sample_kind)) // enum → Int
226+
.combined_accessor_record_nested(pq!(z_sample_timestamp)) // Option → Long?
227+
.combined_accessor_record(pq!(z_sample_express)) // bool → Boolean
228+
.combined_accessor_record(pq!(z_sample_priority)) // enum → Int
229+
.combined_accessor_record(pq!(z_sample_congestion_control)) // enum → Int
230+
.combined_accessor_record_nested(pq!(z_sample_attachment)) // Option → ByteArray?
210231
.package("pubsub")
211232
.ptr_class(pq!(ZPublisher))
212233
.package_fun(pq!(z_publisher_put))
@@ -249,6 +270,7 @@ fn main() {
249270
.package_fun(pq!(z_reply_replier_eid))
250271
.package_fun(pq!(z_reply_is_ok))
251272
.package_fun(pq!(z_reply_sample))
273+
.expand_output() // Option<&ZSample> → builder(full Sample leaves) → R?
252274
.package_fun(pq!(z_reply_error_payload))
253275
.package_fun(pq!(z_reply_error_encoding))
254276
.package("liveliness")

zenoh-flat-jni/generated-kotlin/io/zenoh/jni/JNINative.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import io.zenoh.jni.query.ReplyKeyExpr
2222
import io.zenoh.jni.query.ZQuerier
2323
import io.zenoh.jni.query.ZQueryable
2424
import io.zenoh.jni.sample.SampleKind
25-
import io.zenoh.jni.sample.ZSample
2625
import io.zenoh.jni.scouting.ZScout
2726
import io.zenoh.jni.session.ZSession
2827

@@ -130,7 +129,7 @@ internal object JNINative {
130129
external fun zReplyIsOk(r: Long, errorSink: Any): Boolean
131130
external fun zReplyReplierEid(r: Long, errorSink: Any): Int
132131
external fun zReplyReplierZid(r: Long, errorSink: Any): ByteArray?
133-
external fun zReplySample(r: Long, errorSink: Any): Long
132+
external fun zReplySample(r: Long, build: Any, errorSink: Any): Any?
134133
external fun zSampleAttachment(s: Long, build: Any, errorSink: Any): Any?
135134
external fun zSampleCongestionControl(s: Long, errorSink: Any): Int
136135
external fun zSampleEncoding(s: Long, errorSink: Any): Long

zenoh-flat-jni/generated-kotlin/io/zenoh/jni/query/JNIquery.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import io.zenoh.jni.query.ReplyKeyExpr
1515
import io.zenoh.jni.query.ZQuerier
1616
import io.zenoh.jni.query.ZQuery
1717
import io.zenoh.jni.query.ZReply
18-
import io.zenoh.jni.sample.ZSample
1918
import io.zenoh.jni.withSortedHandleLocks
2019
import io.zenoh.jni.JNINative
2120

@@ -185,13 +184,14 @@ public fun zReplyIsOk(r: ZReply): Boolean {
185184
return __ret
186185
}
187186

188-
public fun zReplySample(r: ZReply): ZSample? {
187+
@Suppress("UNCHECKED_CAST")
188+
public fun <R> zReplySample(r: ZReply, build: (ZKeyExpr, String, ByteArray, String, Int, Long?, Boolean, Int, Int, ByteArray?) -> R): R? {
189189
val __err = ErrorHolder()
190190
val __sink = ErrorSink { __m -> __err.message = __m }
191191
val __ret = withSortedHandleLocks(r) {
192192
val r_ptr = r.ptr
193193
if (r_ptr == 0L) throw ZException("Operation on a closed native handle.")
194-
JNINative.zReplySample(r_ptr, __sink).let { if (it == 0L) null else ZSample(it) }
194+
(JNINative.zReplySample(r_ptr, build, __sink) as R?)
195195
}
196196
__err.message?.let { throw ZException(it) }
197197
return __ret

zenoh-java/src/commonMain/kotlin/io/zenoh/query/Reply.kt

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ import io.zenoh.bytes.IntoZBytes
2020
import io.zenoh.bytes.ZBytes
2121
import io.zenoh.config.EntityGlobalId
2222
import io.zenoh.config.ZenohId
23+
import io.zenoh.keyexpr.KeyExpr
2324
import io.zenoh.sample.Sample
25+
import io.zenoh.sample.toPublic
2426
import io.zenoh.qos.CongestionControl
2527
import io.zenoh.qos.Priority
2628
import io.zenoh.qos.QoS
@@ -46,12 +48,28 @@ sealed class Reply private constructor(val replierId: EntityGlobalId?) : ZenohTy
4648
EntityGlobalId(ZenohId(it), io.zenoh.jni.query.zReplyReplierEid(zr).toUInt())
4749
}
4850
return if (io.zenoh.jni.query.zReplyIsOk(zr)) {
49-
val zs = io.zenoh.jni.query.zReplySample(zr)!!
50-
try {
51-
Success(replierId, Sample.from(zs))
52-
} finally {
53-
zs.close()
54-
}
51+
// Output expansion (M3): the full sample is decomposed into its
52+
// leaves and built here in ONE JNI crossing — no per-field
53+
// `z_sample_*` calls, no transient ZSample handle to close. The
54+
// ZSample combined accessor nests the ZKeyExpr / ZZBytes /
55+
// ZEncoding / ZTimestamp accessors; enums cross as `Int`.
56+
val sample = io.zenoh.jni.query.zReplySample(zr) {
57+
keH, keStr, payload, encStr, kindInt, ntp64, express, prioInt, ccInt, attach ->
58+
Sample(
59+
KeyExpr(keH, keStr),
60+
ZBytes(payload),
61+
Encoding(encStr),
62+
io.zenoh.jni.sample.SampleKind.fromInt(kindInt).toPublic(),
63+
ntp64?.let { TimeStamp(it) },
64+
QoS(
65+
CongestionControl.fromJni(io.zenoh.jni.qos.CongestionControl.fromInt(ccInt)),
66+
Priority.fromJni(io.zenoh.jni.qos.Priority.fromInt(prioInt)),
67+
express
68+
),
69+
attach?.let { ZBytes(it) }
70+
)
71+
}!!
72+
Success(replierId, sample)
5573
} else {
5674
val payload = ZBytes.fromHandle(io.zenoh.jni.query.zReplyErrorPayload(zr)!!)
5775
val encoding = io.zenoh.jni.query.zReplyErrorEncoding(zr)

0 commit comments

Comments
 (0)