replyBytes method

void replyBytes(
  1. String keyExpr,
  2. ZBytes payload, {
  3. Encoding? encoding,
  4. ZBytes? attachment,
})

Sends a reply to this query with a ZBytes payload.

The keyExpr should match the queryable's key expression. The payload is consumed by this call (ownership transferred to zenoh). Optionally specify an encoding for the payload and a binary attachment carried alongside the reply sample. The attachment, if provided, is also consumed by this call.

Throws StateError if the query has been disposed. Throws ZenohException if the reply fails.

Implementation

void replyBytes(
  String keyExpr,
  ZBytes payload, {
  Encoding? encoding,
  ZBytes? attachment,
}) {
  // PRE-move early-return guards. Both run BEFORE any z_bytes_move, so on
  // these paths the caller retains ownership of payload/attachment and we
  // must NOT mark them consumed:
  //   (1) a disposed query throws StateError here;
  //   (2) an invalid key expression throws ZenohException here.
  // zd_query_reply's own z_view_keyexpr_from_str -1 is a pre-move backstop,
  // but the Dart caller cannot distinguish that rc from a post-move failure,
  // so we validate up front (mirroring Session.get / Querier.get) to keep
  // the markConsumed discipline correct.
  _ensureNotDisposed();
  KeyExpr(keyExpr).dispose();

  final keyExprNative = keyExpr.toNativeUtf8();

  Pointer<Utf8> encodingNative = nullptr;
  if (encoding != null) {
    encodingNative = encoding.mimeType.toNativeUtf8();
  }

  try {
    final rc = bindings.zd_query_reply(
      Pointer.fromAddress(_handle).cast(),
      keyExprNative.cast(),
      payload.nativePtr.cast(),
      encoding != null ? encodingNative.cast() : nullptr,
      attachment != null ? attachment.nativePtr.cast() : nullptr,
    );

    // Mark payload + attachment ZBytes consumed UNCONDITIONALLY: once we
    // reach this FFI call the pre-move guards above have passed, so
    // zd_query_reply has moved both into zenoh-c regardless of the return
    // code (its encoding-error path drops the already-moved bytes). Marking
    // before the rc-throw prevents a later use-after-move.
    payload.markConsumed();
    attachment?.markConsumed();

    if (rc != 0) {
      throw ZenohException('Failed to reply to query', rc);
    }
  } finally {
    calloc.free(keyExprNative);
    if (encoding != null) {
      calloc.free(encodingNative);
    }
  }
}