pub enum Predicate {
Show 17 variants
Exists {
key: TagKey,
},
Equals {
key: TagKey,
value: String,
},
NumericAtLeast {
key: TagKey,
threshold: f64,
},
NumericAtMost {
key: TagKey,
threshold: f64,
},
NumericInRange {
key: TagKey,
min: f64,
max: f64,
},
SemverAtLeast {
key: TagKey,
version: String,
},
SemverAtMost {
key: TagKey,
version: String,
},
SemverCompatible {
key: TagKey,
version: String,
},
StringPrefix {
key: TagKey,
prefix: String,
},
StringMatches {
key: TagKey,
pattern: String,
},
MetadataExists {
key: String,
},
MetadataEquals {
key: String,
value: String,
},
MetadataMatches {
key: String,
pattern: String,
},
MetadataNumericAtLeast {
key: String,
threshold: f64,
},
And(Vec<Predicate>),
Or(Vec<Predicate>),
Not(Box<Predicate>),
}Expand description
AST for capability queries. Pure data — clones, equality, and serde round-trip are the basis of cross-binding wire format.
See module docs for the variant taxonomy.
Variants§
Exists
Tag with this (axis, key) is present (regardless of value).
Equals
Tag’s value matches exactly. Presence-only tags don’t match
(use Predicate::Exists for that).
NumericAtLeast
Tag’s value parses to f64 and is >= threshold.
NumericAtMost
Tag’s value parses to f64 and is <= threshold.
NumericInRange
Tag’s value parses to f64 and lies in [min, max] inclusive.
SemverAtLeast
Tag’s value parses to MAJOR.MINOR.PATCH and is >= version.
SemverAtMost
Tag’s value parses to MAJOR.MINOR.PATCH and is <= version.
SemverCompatible
Tag’s value parses to MAJOR.MINOR.PATCH and is in the same
compatibility band: same major for >= 1.0.0, same minor for
0.x.y. Mirrors the standard semver caret-compatibility rule.
StringPrefix
Tag’s value starts with prefix.
StringMatches
Tag’s value contains pattern as a substring. Phase E will
upgrade to regex behind the regex feature gate; semantics
today are substring-only.
MetadataExists
Metadata key is present.
MetadataEquals
Metadata value matches exactly.
MetadataMatches
Metadata value contains pattern as a substring (same
substring-only semantics as Predicate::StringMatches).
MetadataNumericAtLeast
Metadata value parses to f64 and is >= threshold.
And(Vec<Predicate>)
Conjunction. Empty Vec evaluates to true (vacuous match —
matches the standard math/logic convention; pin in tests).
Or(Vec<Predicate>)
Disjunction. Empty Vec evaluates to false (vacuous miss).
Not(Box<Predicate>)
Negation.
Implementations§
Source§impl Predicate
impl Predicate
Sourcepub fn to_wire(&self) -> PredicateWire
pub fn to_wire(&self) -> PredicateWire
Convert to the flat wire format. Post-order serialization: leaves land first, the root has the highest index.
Output is byte-stable across calls — two to_wire()s on
equal predicates produce identical PredicateWire values
(and identical bytes through any serde encoder).
Source§impl Predicate
impl Predicate
Sourcepub fn matches_capability_set(&self, caps: &CapabilitySet) -> bool
pub fn matches_capability_set(&self, caps: &CapabilitySet) -> bool
True if this predicate evaluates to true against the
given super::capability::CapabilitySet’s tags + metadata.
Materializes caps.tags (a HashSet<Tag>) as a Vec<Tag>
for the slice-based EvalContext. The cost is a single
allocation per call; for hot loops over many capability
sets, callers may prefer to materialize tags once and
invoke Self::evaluate directly.
Source§impl Predicate
impl Predicate
Sourcepub fn exists(key: TagKey) -> Self
pub fn exists(key: TagKey) -> Self
Build Predicate::Exists from a TagKey.
Sourcepub fn equals(key: TagKey, value: impl Into<String>) -> Self
pub fn equals(key: TagKey, value: impl Into<String>) -> Self
Build Predicate::Equals from a key + value.
Sourcepub fn numeric_at_least(key: TagKey, threshold: f64) -> Self
pub fn numeric_at_least(key: TagKey, threshold: f64) -> Self
Build Predicate::NumericAtLeast.
Sourcepub fn numeric_at_most(key: TagKey, threshold: f64) -> Self
pub fn numeric_at_most(key: TagKey, threshold: f64) -> Self
Build Predicate::NumericAtMost.
Sourcepub fn numeric_in_range(key: TagKey, min: f64, max: f64) -> Self
pub fn numeric_in_range(key: TagKey, min: f64, max: f64) -> Self
Build Predicate::NumericInRange.
Sourcepub fn semver_at_least(key: TagKey, version: impl Into<String>) -> Self
pub fn semver_at_least(key: TagKey, version: impl Into<String>) -> Self
Build Predicate::SemverAtLeast.
Sourcepub fn semver_at_most(key: TagKey, version: impl Into<String>) -> Self
pub fn semver_at_most(key: TagKey, version: impl Into<String>) -> Self
Build Predicate::SemverAtMost.
Sourcepub fn semver_compatible(key: TagKey, version: impl Into<String>) -> Self
pub fn semver_compatible(key: TagKey, version: impl Into<String>) -> Self
Build Predicate::SemverCompatible.
Sourcepub fn string_prefix(key: TagKey, prefix: impl Into<String>) -> Self
pub fn string_prefix(key: TagKey, prefix: impl Into<String>) -> Self
Build Predicate::StringPrefix.
Sourcepub fn string_matches(key: TagKey, pattern: impl Into<String>) -> Self
pub fn string_matches(key: TagKey, pattern: impl Into<String>) -> Self
Build Predicate::StringMatches.
Sourcepub fn metadata_exists(key: impl Into<String>) -> Self
pub fn metadata_exists(key: impl Into<String>) -> Self
Build Predicate::MetadataExists.
Sourcepub fn metadata_equals(key: impl Into<String>, value: impl Into<String>) -> Self
pub fn metadata_equals(key: impl Into<String>, value: impl Into<String>) -> Self
Build Predicate::MetadataEquals.
Sourcepub fn metadata_matches(
key: impl Into<String>,
pattern: impl Into<String>,
) -> Self
pub fn metadata_matches( key: impl Into<String>, pattern: impl Into<String>, ) -> Self
Build Predicate::MetadataMatches.
Sourcepub fn metadata_numeric_at_least(key: impl Into<String>, threshold: f64) -> Self
pub fn metadata_numeric_at_least(key: impl Into<String>, threshold: f64) -> Self
Sourcepub fn and(clauses: Vec<Predicate>) -> Self
pub fn and(clauses: Vec<Predicate>) -> Self
Build Predicate::And from a Vec of clauses.
Sourcepub fn or(clauses: Vec<Predicate>) -> Self
pub fn or(clauses: Vec<Predicate>) -> Self
Build Predicate::Or from a Vec of clauses.
Sourcepub fn not(inner: Predicate) -> Self
pub fn not(inner: Predicate) -> Self
Build Predicate::Not wrapping a single clause.
Named not to match and / or as a constructor —
not an Op<Output = Predicate> impl. Implementing
std::ops::Not would force callers to depend on
Predicate: Not for the ! operator, which requires
Predicate: Sized + Not<Output = ?> boilerplate without
any expressivity gain over the explicit constructor.
Source§impl Predicate
impl Predicate
Sourcepub fn evaluate(&self, ctx: &EvalContext<'_>) -> bool
pub fn evaluate(&self, ctx: &EvalContext<'_>) -> bool
Evaluate against (tags, metadata). Pure function.
Phase 4 of CAPABILITY_ENHANCEMENTS_PLAN.md: at every
And / Or node, children are evaluated in cost-ascending
order so cheap+selective clauses short-circuit first. The
reordering is a pure local optimization — semantics are
identical to Self::evaluate_unplanned. Pinned by the
planned_evaluate_matches_unplanned_* property tests.
Numeric / semver parse failures yield false (a malformed
tag value shouldn’t fault a federated query).
Sourcepub fn evaluate_unplanned(&self, ctx: &EvalContext<'_>) -> bool
pub fn evaluate_unplanned(&self, ctx: &EvalContext<'_>) -> bool
Evaluate without the planner — children of And / Or run
in declaration order.
Phase 4 escape hatch for benchmarking and the planner-
equivalence property tests. Production callers should use
Self::evaluate; this is a diagnostic surface only.
Sourcepub fn evaluate_with_index<P: CardinalityProvider>(
&self,
ctx: &EvalContext<'_>,
index: &P,
) -> bool
pub fn evaluate_with_index<P: CardinalityProvider>( &self, ctx: &EvalContext<'_>, index: &P, ) -> bool
Evaluate against ctx, using index’s per-key cardinality
data to refine the planner’s clause ordering at every
And / Or node.
Phase 4 follow-on of CAPABILITY_ENHANCEMENTS_PLAN.md.
Produces the same boolean result as
Self::evaluate_unplanned for any (ast, ctx); the index
only changes execution order, not semantics. Pinned in the
index_planner_evaluate_matches_unplanned_* property tests.
When the index is available, prefer this entry point over
Self::evaluate (static-cost planner) — cardinality data
catches selective clauses the static planner misses (e.g.,
a MetadataEquals happens to be the cheapest leaf
statically, but a high-cardinality Equals on an axis tag
is even more selective in this index’s data).
When the index is unavailable or unhelpful (zero-cardinality
for every key — empty index), this falls back to behavior
equivalent to Self::evaluate.
Source§impl Predicate
impl Predicate
Sourcepub fn evaluate_with_trace(&self, ctx: &EvalContext<'_>) -> (bool, ClauseTrace)
pub fn evaluate_with_trace(&self, ctx: &EvalContext<'_>) -> (bool, ClauseTrace)
Evaluate against ctx, also producing a tree of per-clause
traces.
The result equals self.evaluate(ctx); this entry point adds
the ClauseTrace tree as a side channel for debug
inspection. Composite clauses retain the planner’s
short-circuit behavior — descendants that didn’t run aren’t
in the trace.
Phase 6 of CAPABILITY_ENHANCEMENTS_PLAN.md. Opt-in only;
production callers use Predicate::evaluate.