pub enum CodecRule {
Show 18 variants
TrackNameTooLong,
ReasonPhraseTooLong,
GoAwayUriTooLong,
KvpValueTooLong,
KeyValueFormatting,
UnknownMessageParameter,
ParameterOutOfScope,
ParameterLengthMismatch,
InvalidFilterType,
InvalidFetchType,
SubscriptionFilterMalformed,
FilterEndGroupOverflow,
ObjectIdOverflow,
InvalidStreamTypeValue,
InvalidDatagramTypeValue,
EndOfTrackObjectId,
ExtensionsOnNonExistentObject,
InvalidRequiredRequestIdDelta,
}Expand description
A rule a peer broke that the negotiated draft’s decoder did refuse, named once across the drafts that state it.
§Why this is a second enum and not more variants of the first
AboveCodecRule is defined by what it is not: a rule stated about a
frame that reads perfectly well, which no decoder could refuse and which the
endpoint has to catch by comparing decoded fields against state it has been
keeping. Every rule here is the opposite. The frame did not read — a length
past its maximum, a discriminator the draft does not assign, a delta that
carries a number past the end of the varint space — and CodecError is what
says so. Folding the two into one enum would put the decoder refused this
and the decoder could not have seen this under one name, which is the
distinction crate::dispatch::ErrorCause exists to keep.
§Why it lives in this file rather than beside CodecError
Because of what reads it. scripts/check-drafts.py rule 8 walks this
file and holds every RuleCitation in it against the fourteen rendered
drafts: that the sentence is in every draft of the run, that it sits in the
section the row names, and that the code name is one the sentence itself
uses. A citation the gate cannot see is not a checked citation, and the
standard for adding one is deliberately steep: a sentence held against the
draft that will be cited, on each draft in the range claimed rather than on
a sample of it.
moqtap-codec is the other candidate and is the wrong one twice over: it is
where the errors live rather than where the drafts’ answers to them do,
and nothing in just drafts reads a table there either.
§Where the quoted sentences are, and are not
In the constants below, one per wording, which is the only place the gate
looks. The variant docs here describe rather than quote, and use backticks
where they name a fragment of a draft’s text. That is a departure from
AboveCodecRule above, and the reason is this group’s ranges: nearly
every rule here says something different on the oldest drafts in its range
than on the newest, so a doc that quoted one wording beside a sentence
naming ten drafts would be claiming it for all ten. The checker has a rule
for exactly that and it would be right to fire.
§What is in this table
These are the rules a consumer’s catalogue names as a list and does not
carry itself: a rule_for matching CodecError exhaustively has no
wildcard arm to file them under. Every one of them is a relay breaking a
rule the negotiated draft answers with a session close, and without a
citation here there is nothing to publish it as.
§Why the two Type-value rules are two
CodecRule::InvalidStreamTypeValue and
CodecRule::InvalidDatagramTypeValue are one condition as a reader thinks
of it — a Type inside its form holding a combination the draft rules out —
and two rules here, because drafts 16 through 21 state them as two
sentences in two sections, one about a datagram’s Type and one about a
subgroup stream header’s.
A RuleCitation is one sentence per draft: Self::citation takes the
first run that covers a draft and
every_run_is_ordered_contiguous_and_in_range forbids two runs claiming
one. So a single rule spanning both sentences could publish only one of
them, and would be right on half the frames it published and wrong on the
other half with nothing in the row to say which.
Splitting the rule here is only half of it, and the half that does not work
alone: the decoder has to hand over a value that says which sentence was
broken. CodecError::InvalidStreamTypeValue and
CodecError::InvalidDatagramTypeValue are that value. Deriving the
namespace from the raw number instead would be this build’s reading rather
than the decoder’s, because the two Type spaces overlap — which is the
reasoning CodecError::InvalidField already gets, arrived at from a
different direction.
§Two drafts where a close exists and no citation does
This table is not the inverse of codec_session_error_code, and two rows
are where the two come apart. Draft-20 answers both
Self::InvalidFilterType and Self::InvalidFetchType with
PROTOCOL_VIOLATION, and draft-20 states neither rule: it replaced the
subscription filter with a LOCATION_FILTER parameter whose optional fields
are found by length and carry no type discriminator, and it deleted the
Fetch Type field, both variant structures and the registry together.
Neither arm is reachable there. moqtap-codec’s draft-20 message reader
raises neither error and has nothing to raise it from, so the two closes are
inert rather than wrong, and both are kept for the reason draft-20’s own
connection already gives: CodecError is shared across drafts and
is not #[non_exhaustive], so every variant has to be answered on every
draft.
What the missing citation buys is that the inertness stops being load-bearing. If a draft-20 decoder ever did raise one, a consumer would find no sentence to publish and would name nobody — which is the right answer for a rule draft-20 does not state, and it does not depend on an unreachable arm staying unreachable.
Deliberately not #[non_exhaustive], for the reason AboveCodecRule
is not: a consumer deciding what it will name a relay for should find out
about a new rule by failing to build.
Variants§
TrackNameTooLong
A Full Track Name longer than the drafts’ maximum.
Drafts 11 through 20, Section 2.4.1 throughout — the section never moves and the sentence changes three times, which is the opposite of the usual shape and why this rule has four runs where most have one wording per section.
The maximum and its consequence are quoted together because the
consequence alone is not evidence: through draft-15 it refers back to
exceeding this length, and the length is in the sentence before it.
One nuance the citation carries and this build’s error message does not.
On drafts 11 through 15 the sentence bounds the Full Track Name
alone; draft-16 widens it to a Track Namespace or a Full Track Name.
CodecError::TrackNameTooLong renders as track namespace or full track
name exceeds … on all ten, which is the drafts’ own scope only from 16
on. A namespace over the maximum beside a short name is covered by no
sentence on the older five, and their rows quote what those drafts do
say rather than what this build measures.
Drafts 07 through 10 state no maximum at all.
ReasonPhraseTooLong
A Reason Phrase longer than the drafts’ maximum.
Drafts 11 through 20. The sentence has no full stop in any of them:
it runs straight into the next definition item, so every quotation here
ends at the code name. Supplying the full stop a transcriber would want
is exactly the truncation check-drafts.py rule 7 exists to catch, and
it would file the row under a sentence no draft has.
Four runs. The section moves twice — draft-14 inserts Section 1.3 Stream
Management Terms and draft-17 inserts Section 1.4.1 Variable-Length
Integers, pushing this down each time — and the wording changes twice,
once for the code rename and once where the maximum stops being a
maximum length of 1024 bytes and becomes a maximum value of 1024 bytes.
GoAwayUriTooLong
A GOAWAY New Session URI longer than the drafts’ maximum.
Drafts 11 through 20, in the GOAWAY message’s own section, which moves three times across the range.
Drafts 11 through 16 spell it The maxmimum length of the New Session URI is 8,192 bytes. The typo is the drafts’ and is reproduced in the
constant, because the gate compares against the rendering: a sentence
tidied up is a sentence no draft has. Draft-17 fixes it, which is one of
the two wording breaks in this rule’s four runs.
KvpValueTooLong
A Key-Value-Pair whose value is longer than the drafts’ maximum.
Drafts 11 through 20, in the Key-Value-Pair structure’s own section — 1.3.2 through draft-13, 1.4.2 on 14 through 16, 1.4.3 from draft-17, which is the same pair of insertions that moves the Reason Phrase rule.
The sub-variant and not the arm. CodecError::Kvp also carries
MissingLength, UnexpectedEnd and VarInt, which report how the bytes
ran out rather than a rule an endpoint states, and all the drafts
answer all three with no close. Only ValueTooLong reaches this rule,
which is why the probe that consumes it matches the sub-variant.
KeyValueFormatting
A key-value pair whose value is not the serialization its own Type defines.
Drafts 11 through 20, and the one rule in this table whose code is KEY_VALUE_FORMATTING_ERROR on every draft that states it rather than PROTOCOL_VIOLATION.
Four runs for three reasons at once. Drafts 11 through 13 spell the code in prose inside quotation marks and drafts 14 and later in capitals; draft-16 changes the verb from terminate to close; and the section moves twice under both. Only the first of those three is visible in the code name a row publishes, which is the argument for publishing the sentence beside it.
UnknownMessageParameter
A control message carrying a Message Parameter whose type its draft does not define.
Drafts 16 through 20, and the rule whose answer reverses rather than
arrives. Drafts 07 through 10 say a receiver ignores an unrecognized
parameter, and drafts 11 through 15 add Receivers MUST allow duplicates of unknown parameters, which presumes unknown parameters arrive and are
carried. Raising this on any of those nine would close a session over an
extension those drafts leave room for, so the decoder does not, and the
run starts where the sentence does.
Draft-16 is a run of its own for one word: it has the parameter
negotiated via Setup Parameters where drafts 17 and later say Setup Options, which is the rename draft-17 made. Publishing the later
wording for draft-16 would be quoting a sentence draft-16 has not got —
the exact defect this table was built to remove, one draft wide.
One namespace only. Every draft in range says a receiver ignores an unrecognised Setup Option, so an unknown type in a SETUP is carried and this is never raised for one.
ParameterOutOfScope
A Message Parameter appearing in a message type its own definition does not name.
Drafts 17 through 20. The other reversal, and a wider one: drafts 07
through 16 end the same sentence it MUST be ignored.
The sentence says close the connection, not close the session, on all four drafts. Reproduced as it stands. The drafts use the two words interchangeably here, and correcting one to the other would be this file speaking inside a draft’s own quotation marks — which is a defect this table has already been found holding five times.
ParameterLengthMismatch
A parameter whose value is not the shape its own type implies.
Drafts 07 through 10 alone, which makes it the only rule in either
table that exists on the oldest four drafts and nowhere else. The
sentence goes with the Parameter framing it describes, and drafts 11 and
later replaced that framing with Key-Value-Pairs — where the
neighbouring rule is Self::KeyValueFormatting, under a different
code.
It is also the only rule here answered with neither PROTOCOL_VIOLATION nor KEY_VALUE_FORMATTING_ERROR: each of those four drafts assigns Parameter Length Mismatch a number of its own in the session termination registry, and the sentence names it.
InvalidFilterType
A subscription filter naming a Filter Type the draft does not assign.
Drafts 14 through 19, and two runs because draft-14’s sentence carries
the draft’s own missing word — it has an endpoint MUST be close the session. Reproduced rather than corrected, for the reason
RuleCitation::sentence gives.
Drafts 07 through 13 state the rule and no consequence: a filter type
other than the assigned ones MUST be treated as error, which names no
code and no close. So the same value in the same place is a refused
message on the first seven drafts and a dead session on the next six,
and only the per-draft close table can tell them apart.
Draft-20 states it nowhere. See this enum’s own doc for why a close remains in draft-20’s table and why the missing citation is what makes that safe.
InvalidFetchType
A FETCH naming a Fetch Type the draft does not assign.
The sentence next to the Filter Type one, moving the same way and
carrying the same draft-14 missing word. Drafts 14 through 19; drafts 08
through 13 say a Fetch Type outside the set MUST be treated as an error and state no consequence, and draft-07 has a FETCH with no Fetch
Type field in it.
Draft-20 deleted the field, both variant structures and the registry together, so it has nothing to state.
Four runs for two wordings: the section moves three times across the range while the sentence stands still after draft-14.
SubscriptionFilterMalformed
A subscription filter parameter whose value is not a filter.
Drafts 15 through 20, and the one rule here whose code changes within its own range rather than only being spelled differently. Drafts 15 and 16 state it of this parameter directly and answer PROTOCOL_VIOLATION; drafts 17 through 20 drop that sentence and leave the general key-value rule, which answers KEY_VALUE_FORMATTING_ERROR. A filter three bytes long inside a four-byte parameter ends a draft-16 session with one code and a draft-17 session with the other.
The later run cites the same sentence Self::KeyValueFormatting does,
which is what a shared constant is for. The reading that a malformed
filter is a Value that does not match the serialization its Type defines
is this build’s, and it is the same reading codec_session_error_code
already makes on those four drafts. Stated here rather than left to be
noticed: the sentence is the drafts’, and that this malformation is its
case is a reading of it.
A Filter Type outside the assigned set is not this rule. That is
Self::InvalidFilterType, whose own section names its own code.
FilterEndGroupOverflow
An AbsoluteRange filter whose End Group Delta carries the last Group ID past the end of the varint space.
Drafts 18 through 20. Draft-17 introduced the delta and states the arithmetic with no consequence for overflowing it — that draft contains exactly one mention of the bound in the whole document and it is the Delta Type rule, not this one — so there an overflowing filter is a decode failure and nothing more.
The draft-18 and draft-19 run keeps the clause before the consequence, because the resulting Group ID has no antecedent without it. The two are contiguous inside one paragraph, so it is a quotation and not a splice. Draft-20 rewrote the pair as one self-contained sentence naming its own operands, which is the second run.
ObjectIdOverflow
A delta-encoded Object ID that would exceed the varint space once the delta is added to the previous Object ID on the same stream.
Drafts 18 through 20 in Section 11.4.2 and draft-21 in Section 11.3.1, two runs: the wording does not change and the section number does.
Drafts 14 through 17 carry the identical arithmetic in Section 10.4.2 and state no consequence for overflowing it — all four of them, not draft-17 alone — and drafts 07 through 13 have no Object ID Delta to overflow.
The three sentences are quoted unbroken, and no ellipsis may stand between the first and the third: eliding there splices across the sentence about the first Object in the Subgroup stream and makes a sentence none of the three drafts has.
InvalidStreamTypeValue
A subgroup stream header’s Type holding a combination its draft names as invalid.
Drafts 16 through 21, four runs: the section moves twice and the wording changes once, and the two moves do not coincide. Sections 10.4.2 on drafts 16 and 17, 11.4.2 on 18, 19 and 20, and 11.3.1 on draft-21; drafts 16 through 19 enumerate the code points after the sentence and drafts 20 and 21 state the bit pattern alone.
The sentence is quoted as far as the colon it ends on, because what follows it is a bulleted list of values rather than more sentence. That is the whole quotation and not an elision, so no ellipsis stands in for the list.
Paired with CodecRule::InvalidDatagramTypeValue, which is the same
rule stated for the other Type space in a different section of the same
drafts. They are two rules here because they are two sentences there,
and because a consumer holding one refusal has to be able to publish the
sentence it actually broke.
InvalidDatagramTypeValue
A datagram’s Type holding a combination its draft names as invalid.
Drafts 16 through 21, four runs, cut where
CodecRule::InvalidStreamTypeValue’s are cut and at different
numbers: Sections 10.3.1 on drafts 16 and 17, 11.3.1 on 18, 19 and 20,
and 11.2.1 on draft-21.
Draft-21 is why the two rules cannot share a run. It splits the section that held both, so the datagram sentence lands at 11.2.1 and the stream sentence at 11.3.1 — the one number that had been the datagram’s on the three drafts before it.
EndOfTrackObjectId
An end-of-Track Object stating an Object ID other than zero.
Drafts 08 through 10 alone, and the one rule in this table whose
sentence names no code: it ends with the receiver having to terminate
the session and nothing more, so RuleCitation::code_name is None
and a row publishes the number without a name for it. The number comes
from codec_session_error_code, which answers PROTOCOL_VIOLATION — what
those drafts answer every rule they close over without naming a code.
The name is absent because the draft does not supply it, which is not
the same thing as the draft stating no consequence.
There is a look-alike sentence in the same subsection of the same three
drafts, about Object Status 0x4 rather than 0x5, and the two differ by
four words in two places: the neighbour has a Group ID less than any
other and an Object ID less than or equal to the largest in the group,
where this one has a Group ID less than or equal to any other and an
Object ID other than zero. The neighbour is
AboveCodecRule::EndOfTrackOutOfPlace’s sentence and is already cited
above; citing it here would have put two rules under one wording and
looked right.
Draft-07 assigns no 0x5. Drafts 11 and later merge end of Track into 0x4 and permit either shape, so there is no longer a rule to break.
ExtensionsOnNonExistentObject
An Object with Object Status ‘Object Does Not Exist’ carrying extension headers.
Drafts 11 through 14, three runs: the section moves twice and draft-14 respells the code. The rule names one status and no others, so extensions beside End of Group or End of Track are legal on those four drafts and are not this.
Drafts 15 and later replaced the narrow form with the general one —
extensions, later properties, permitted only beside Normal — which is a
different rule with a different subject and reaches a consumer as
AboveCodecRule::PropertiesOnNonNormalStatus. Drafts 07 through 10
state neither form.
InvalidRequiredRequestIdDelta
A request message’s Required Request ID Delta naming a dependency below zero.
Draft-17 alone. Draft-18 removed the field and mentions it only in its change log, so no other draft can state the rule.
The only rule in this table answered with INVALID_REQUIRED_REQUEST_ID, and the only sentence in it carrying a character outside ASCII: the draft writes the comparison with a multiplication sign, and the gate compares against the rendering rather than against what a transcriber would have typed.
Implementations§
Source§impl CodecRule
impl CodecRule
Sourcepub fn citations(self) -> &'static [RuleCitation]
pub fn citations(self) -> &'static [RuleCitation]
Every draft run this rule has a checked citation for, oldest first.
Exhaustive with no wildcard arm, for the reason the enum is not
#[non_exhaustive]: a rule added to this file arrives here as an
E0004 and a decision about which drafts state it.
No arm answers with an empty slice, which is the one structural
difference from AboveCodecRule::citations. There, nine rules do, and
eight of them are rules no draft answers with a close. Here a rule with
nothing to cite would have no reason to exist: the whole set is chosen
by reading the fourteen codec_session_error_code tables for variants
answered Some on at least one draft, and a rule stated in no draft is
left out rather than written down with an empty slice. One rule is left
out on other grounds entirely, and the enum’s doc names it and says
which.
The runs are not the drafts that answer with a close, and the enum’s
doc says which two rows differ and why. A draft with a close and no
citation publishes nothing, which is the safe direction; a draft with a
citation and no close is a row nothing can reach, and
a_cited_draft_is_a_draft_that_closes below asserts there are none.
Sourcepub fn citation(self, draft: u8) -> Option<&'static RuleCitation>
pub fn citation(self, draft: u8) -> Option<&'static RuleCitation>
This rule as draft states it, or None where that draft does not.
The same contract as AboveCodecRule::citation, including the part
that matters most: there is no fallback to a neighbouring draft’s
wording. None means there is no sentence to publish, so there is no
accusation to make.