Skip to main content

supports_matcher

Function supports_matcher 

Source
pub fn supports_matcher(
    draft: DraftVersion,
    kind: MatchKind,
    field: MatcherKey,
) -> bool
Expand description

Whether a rule keyed on field can ever claim a unit arriving as kind, on draft, in this build.

A shaping rule keyed on something the negotiated draft does not carry arms, matches nothing, and reports success — the silent no-op this crate exists to make loud. Before this predicate the only way to learn it was to run the session and read Impairment{ShapeRuleUnmatchable} out of the report, which requires a run, traffic of the right shape, and a reader. The answer needs nothing but the draft and the compiled feature set, so it is answerable before the run, and Capabilities::admit_profile turns it into a refusal.

§Why the second argument is a MatchKind and not a Site

Shaping only ever sees framed objects. Site spans the control frame, the two stream decisions and the stream end, none of which a Matcher can be aimed at, and it does not distinguish the two things that decide this question — a subgroup stream from a fetch one. MatchKind is the axis the answer actually varies on, and it is the axis a rule is written against.

§The three facts, in the order they are read

  1. A draft this build did not compile frames nothing at all. The stream header decode returns UnsupportedDraft, the framer latches BypassReason::DecodeError and forwards the stream uninterpreted, so no ObjectMeta is ever built and no key can match — see draft_is_compiled, which is reachable by default rather than only under exotic flags. This is why the predicate answers for a build and not only for a draft, exactly as classify does.
  2. A fetch stream carries no track alias, and a datagram carries no subgroup ID, on any draft. A fetch header carries a request ID where a subgroup header carries an alias, and no datagram of any draft belongs to a subgroup. These are the two answers that vary by kind rather than by draft, and they are why the predicate takes the kind at all.

§What it deliberately does not refuse, and why

Matcher::subgroup_id and Matcher::priority are the two keys whose absence can be a property of one header rather than of the draft — a header in subgroup ID is the first object’s ID mode (eight drafts) or drafts 17-20’s reserved mode 3 carries no subgroup ID, and drafts 15-20 omit the publisher priority whenever the header sets the default-priority bit, on a subgroup header and on a datagram alike. Neither is a draft fact. Every one of the fourteen drafts also has header shapes that carry both — modes 0 and 2 on 17-20, an explicit subgroup ID field elsewhere, and a clear default-priority bit — and every fetch object on the drafts that frame one carries both unconditionally. So a rule keyed on either can match on every draft, and this predicate answers true.

There is deliberately no fact about a stream kind that yields no unit at all. There used to be one — a MatchKind::Fetch class on drafts 18 and 19, refused before the run because no fetch stream there could be framed — and it went when those streams became readable; see fetch_group_order_is_needed. A fetch stream the session cannot resolve is now one stream rather than a draft, and it reports itself as Impairment { FramerBypass { FetchGroupOrderUnknown } } while it happens.

The one place subgroup_id crosses the line is a rule aimed at MatchKind::Datagram, which fact 2 above refuses: there the absence is not a header’s but the carrier’s, and no draft has a datagram shape that carries one. A rule that names no kind and keys on subgroup_id is still admitted, because it is a working subgroup rule that datagram traffic simply walks past.

Refusing them would reject rules that work, which is a worse failure than the one being fixed: a run that shapes nothing can at least be observed, while a configuration rejected at startup cannot run at all. A key the wire withheld from one unit stays what it already was — Impairment{ShapeRuleUnmatchable}, reported per class per field, once per session — because that answer depends on the traffic and nothing before the run can know it.