KeyExpr.autocanonize constructor

KeyExpr.autocanonize(
  1. String expr
)

Creates a KeyExpr from expr, canonizing it first.

The additive door beside the strict default. Where KeyExpr(expr) rejects a non-canon expression, this rewrites it into canon form and constructs from the result — so KeyExpr.autocanonize('a/**/**/c') is the key expression a/**/c, and its value reads back the canonized form, not the input. See canonize for the four rewrite rules.

Canonize-then-validate, exactly as canon composes it: an expression that is still invalid after the rewrite throws ZenohException carrying canon's code — the same exception the strict constructor throws, for the same inputs.

The result is an ordinary KeyExpr in every respect: it delivers, answers intersects/includes/equals, clones and disposes identically to one built any other way, and nothing on it reports whether canonization actually happened — canon carries no such signal.

Canonization is construction-and-validation only, so non-ASCII input is safe here — but the resulting handle is not safe to use: see the non-ASCII warning in this class's documentation. expr is judged as bytes, with the encode-boundary caveat described there.

The caller must dispose the result.

Implementation

factory KeyExpr.autocanonize(String expr) {
  final encoded = utf8.encode(expr);
  // Canon COPIES this before canonizing — the buffer is `const` on its side
  // and is never written — so unlike `canonize` there is no in-place
  // rewrite here. It must still be non-NULL at length 0.
  final exprPtr = _copyToNative(encoded);
  // Canon writes the canonized length back; nothing below reads it, because
  // the owned key expression carries its own bytes. The cell exists because
  // canon's signature takes one, and it is released either way.
  final lenCell = calloc<Size>();
  // Allocate-last: the slot is the final block taken, after everything that
  // could have thrown, and it is freed on the rc-failure path.
  final slot = calloc.allocate<Void>(bindings.zd_keyexpr_sizeof());
  try {
    lenCell.value = encoded.length;
    final rc = bindings.zd_keyexpr_from_substr_autocanonize(
      slot.cast(),
      exprPtr.cast(),
      lenCell,
    );
    if (rc != 0) {
      calloc.free(slot);
      throw ZenohException('Invalid key expression: "$expr"', rc);
    }
    return KeyExpr._owned(slot);
  } finally {
    malloc.free(exprPtr);
    calloc.free(lenCell);
  }
}