clone method

KeyExpr clone()

Returns an independent copy of this key expression.

Whatever this handle's backing, the clone is an owned key expression with an independent lifetime: dispose this one and the clone still reads back, still delivers, and still answers relations.

A clone of a declared key expression is itself a declared key expression: it can be undeclared in its own right, and undeclaring it leaves this handle untouched.

The caller must dispose the returned handle.

Throws StateError if this key expression is no longer alive.

Implementation

KeyExpr clone() {
  final loaned = loanedKeyExpr;
  if (_isOwned) {
    final slot = calloc.allocate<Void>(bindings.zd_keyexpr_sizeof());
    bindings.zd_keyexpr_clone(slot.cast(), loaned.cast());
    return KeyExpr._owned(slot);
  }
  // ⚠️ A view backing does not own its bytes -- it borrows the buffer this
  // object allocated -- and canon's `z_keyexpr_clone` clones what the source
  // HOLDS, which for a view is the borrow. Measured: clone a view-backed
  // handle, dispose the source, and the clone reads freed memory. So the
  // view path goes through canon's COPYING constructor instead. The two
  // branches are canon's semantics, not a preference.
  final viewStr = calloc.allocate<Void>(bindings.zd_view_string_sizeof());
  try {
    bindings.zd_keyexpr_as_view_string(loaned.cast(), viewStr.cast());
    final data = bindings.zd_view_string_data(viewStr.cast());
    final len = bindings.zd_view_string_len(viewStr.cast());
    final slot = calloc.allocate<Void>(bindings.zd_keyexpr_sizeof());
    final rc = bindings.zd_keyexpr_from_substr(slot.cast(), data, len);
    if (rc != 0) {
      calloc.free(slot);
      throw ZenohException('Failed to clone key expression', rc);
    }
    return KeyExpr._owned(slot);
  } finally {
    calloc.free(viewStr);
  }
}