#[non_exhaustive]pub struct Matcher {
pub side: Option<ProxySide>,
pub track_alias: Option<RangeSet>,
pub group_id: Option<RangeSet>,
pub subgroup_id: Option<RangeSet>,
pub object_id: Option<RangeSet>,
pub priority: Option<RangeInclusive<u8>>,
pub stream_kind: Option<MatchKind>,
pub every_nth: Option<(u64, u64)>,
}Expand description
Which units a ClassRule claims.
All present fields must match (AND). An absent field matches
everything. A field the wire did not carry — None on
ObjectMeta — does not match.
#[non_exhaustive] with a Default, exactly as
EgressConfig is. The pairing is
load-bearing: #[non_exhaustive] alone would make this type
unconstructible from an integration-test crate or from a scenario
author’s code, because struct-expression and functional-update syntax
are both illegal outside the defining crate. Note what that leaves:
..Matcher::default() is also illegal there (E0639), so an
outside caller writes let mut m = Matcher::default(); and then assigns
per field — which is what tests/actions_shaping.rs does. Inside this
crate both forms compile, which is why the unit tests below use the
shorter one. The Default is all-None — a matcher that claims every
unit.
In the written form every key defaults to absent, so a matcher naming one
field is one line, and an unknown key is refused rather than skipped — a
misspelled group_id would otherwise widen the rule to claim every unit
on the stream instead of the ten groups it named.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.side: Option<ProxySide>The direction the unit arrived on.
Only ClientToProxy and RelayToProxy are ever seen at a hook
site; the two egress labels are used for teardown reporting. Naming
an egress side here is rejected by
ShapeProfile::try_new rather than
left to match nothing.
Written as the variant’s own name in kebab-case —
"client-to-proxy" — by a mapping in the scenario module rather than
by a derive, because ProxySide lives in a module that carries no
serde dependency of its own.
track_alias: Option<RangeSet>Track alias from the stream header. None on every fetch stream,
so a rule keyed here never claims fetch units.
group_id: Option<RangeSet>Group ID. Always present on a framed object.
subgroup_id: Option<RangeSet>Subgroup ID. None on eight drafts in first-object mode and on
17-19 in reserved mode 3, so a rule keyed here claims nothing there.
object_id: Option<RangeSet>Absolute object ID. Always present on a framed object.
priority: Option<RangeInclusive<u8>>MoQT publisher_priority. None on drafts 15-19 whenever the
header set the default-priority bit.
stream_kind: Option<MatchKind>Which kind of stream the unit came from.
every_nth: Option<(u64, u64)>(n, offset) over a counter of hook-visible units on this
stream, scoped per stream and not per class, never
ObjectMeta::index_in_stream — which counts oversized objects
that never reach the hook and would silently shift the pattern.
Matches when unit_index % n == offset % n. n == 0 names no
units, so ShapeProfile::try_new
rejects it as ShapeError::InertMatcher
rather than accepting a class that can never claim anything.
Implementations§
Source§impl Matcher
impl Matcher
Sourcepub fn matches(
&self,
side: ProxySide,
meta: &ObjectMeta,
unit_index: u64,
) -> bool
pub fn matches( &self, side: ProxySide, meta: &ObjectMeta, unit_index: u64, ) -> bool
Whether this matcher claims one unit.
side is the forwarding task’s own direction label — ObjectMeta
has no side field. unit_index is the per-stream count of
hook-visible units described on Matcher::every_nth, supplied by
the caller for the same reason charge takes now: this function
owns no state and reads no counter, so it can be tested exhaustively
from a table.
Sourcepub fn matches_datagram(
&self,
side: ProxySide,
meta: &AnyDatagramMeta,
unit_index: u64,
) -> bool
pub fn matches_datagram( &self, side: ProxySide, meta: &AnyDatagramMeta, unit_index: u64, ) -> bool
Whether this matcher claims one datagram.
Self::matches’s sibling, and the two answer through one
conjunction — see the private Keys it is written over. What differs
is what fills that in: a
datagram states its own track alias, Group ID, Object ID and (from
draft-15, conditionally) priority, and states no subgroup ID on
any draft, so a rule keyed there claims no datagram. That last one is
a fact about the carrier rather than about one header, so it is
refused before the run by
Capabilities::admit_class
rather than discovered from one.
unit_index counts hook-visible datagrams per forwarding
direction, which is the only scope a datagram has: it belongs to no
stream, so Matcher::every_nth’s per-stream reading has nothing to
key against here and the session’s two directions count separately.
Sourcepub fn inert_key(&self) -> Option<&'static str>
pub fn inert_key(&self) -> Option<&'static str>
The first key this matcher names that can never claim a unit —
not because the wire withheld it, but because the key itself names
an empty set of values.
The crate-internal unmatchable_fields’s sibling, and the difference is
where each is answerable: an unmatchable field depends on the draft and
the unit, so it can only be reported during a run, while an inert key
is a property of the configuration alone and is therefore
ShapeProfile::try_new’s to reject
before a session ever starts. Rejecting is strictly better than
reporting: a class that can never fire is the configuration that looks
applied and does nothing that constructor exists to prevent, and here
it is knowable without a single byte of traffic.
Public because a caller that builds matchers from its own configuration
needs the same pre-flight refusal try_new gets: a matcher handed to a
ProxyHook rather than to a shaping class
reaches no constructor that could check it.
The three shapes, each of which try_new used to accept:
- a
RangeSetbuilt from an inverted range —RangeSet::newdropsstart > end, so the set is empty andcontainsis alwaysfalse; - an empty
Matcher::priorityrange (200..=100); Matcher::every_nthwithn == 0, whichSelf::matchesanswersfalsefor unconditionally.
Returns the key’s field name as it is spelled on this struct, so the error message names something the author can search their own configuration for.