#[non_exhaustive]pub enum ActionKind {
Show 14 variants
Pass,
Replace,
ReplacePayload,
Delay,
Hold,
DropElide,
Truncate,
ResetStream,
CloseSession,
Open,
Reject,
ReplaceObject,
OpenAfter,
SerializeAfter,
}Expand description
A capability, named independently of whether
Action can express it.
Every kind here names a capability some value can express. A kind that nothing could construct used to be published too, so the table could document the gap — but a variant that no value can carry is a unit that compiles and never runs, and a table row saying so is a row about this crate’s plans rather than about what it does. Two such kinds were removed; the capabilities they named are simply absent, and absence is what the table now says by not listing them.
Self::OpenAfter and Self::SerializeAfter were in that family
until 0.4.0, when that release shipped
StreamAction::OpenAfter and
StreamAction::SerializeAfter;
their rustdoc now carries ordinary doc-tests that construct them,
where it used to carry compile_fail blocks that could not.
Self::ReplaceObject is deliberately not in that family, and the
distinction is what keeps the table honest: a value that carries it to
Site::Object exists (Action::Replace(b)), so the engine really is
asked and really does refuse, with Refusal::WrongSite. The
deferred-capability id printed on the variant names the gap; it is
not the refusal a run emits. See the variant’s own rustdoc.
Attempt mapping — how tests/action_matrix.rs turns a (site, kind) pair into something to run. Every kind maps to exactly one
expression, and a kind whose mapping does not typecheck at a site is
precisely a NotAttemptable cell:
| Kind | The attempt |
|---|---|
Pass | Action::Pass |
Replace | Action::Replace(b) |
ReplacePayload | Action::ReplacePayload(b), b.len() == payload_len |
ReplaceObject | Action::Replace(b) at Site::Object only — the same expression as Replace, so those two cells must agree, and action_matrix.rs asserts that they do. At every other site there is no attempt: the same expression there is Replace’s attempt, and this kind names a unit those sites do not carry (NotAttemptable::KindNotDefinedAtThisSite) |
Delay | Action::Pass.delayed(d) |
Hold | Action::Pass.held(gate) |
DropElide | Action::Drop(DropMode::Elide) |
Truncate | Action::Truncate { bytes, code } |
ResetStream | Action::ResetStream { code } |
CloseSession | Action::CloseSession { code, reason } |
Open | StreamAction::Open |
Reject | StreamAction::Reject { code } |
OpenAfter | StreamAction::OpenAfter(d) |
SerializeAfter | StreamAction::SerializeAfter(key) |
Action::ReplacePayload with a mismatched length is constructible,
and it is refused with Refusal::LengthChanged — the ReplacePayload
cell’s Conditional failing. Re-framing an object around a new length
is a different capability, and it has no row here because it has no
value: there is nothing to attempt and therefore nothing to refuse.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Pass
Replace
ReplacePayload
Action::ReplacePayload at
the original length.
Delay
Hold
DropElide
Action::Drop with
DropMode::Elide.
Truncate
ResetStream
CloseSession
Open
Reject
ReplaceObject
Replacing a whole wire object. Attemptable and refused, not
unconstructible — Action::Replace(b) at Site::Object is
exactly this attempt, so the engine is really asked and answers
with Refusal::WrongSite. Whole-object replacement at the object
site is a real attempt that really is refused, which is why this
kind is published and why its refusal is one a run emits.
At every non-object site it is
NotAttemptable { why: KindNotDefinedAtThisSite, refusal: WrongSite { site, action: ReplaceObject } }: a control frame, a
datagram and a stream are not objects, so no value carries this
kind there and nothing is ever attempted.
OpenAfter
Opening the peer stream after a delay.
StreamAction::OpenAfter,
shipped in 0.4.0; this kind is no longer in the constructor-less
family.
open_after_and_serialize_after_are_constructible — the pair of
doc-tests that used to prove this capability’s absence now proves
its presence, and they remain the crate’s only compile-time proof
that the two variants exist with the shape they do. They are ordinary
doc-tests rather than inverted compile_fail blocks on purpose: a
compile_fail block that fails for the wrong reason reports ok
exactly as loudly as one that fails for the right one, which is how
the two blocks this replaces went on passing while asserting a
struct-variant syntax (OpenAfter { after: … }) that never
matched the tuple variants that actually exist. An ordinary
doc-test can only pass by compiling and running.
// open_after_and_serialize_after_are_constructible (1 of 2)
use std::time::Duration;
use moqtap_proxy::action::StreamAction;
let a = StreamAction::OpenAfter(Duration::from_millis(1));
assert!(matches!(a, StreamAction::OpenAfter(d) if d == Duration::from_millis(1)));// open_after_and_serialize_after_are_constructible (2 of 2)
use moqtap_proxy::action::StreamAction;
use moqtap_proxy::event::ProxySide;
use moqtap_proxy::shape::StreamKey;
// A session-local id plus the side it arrived on — never a
// transport stream id, which is the constant 0 on WebTransport.
let key = StreamKey { side: ProxySide::ClientToProxy, id: 7 };
let b = StreamAction::SerializeAfter(key);
assert!(matches!(b, StreamAction::SerializeAfter(k) if k == key));And the verdicts, which is the one place the two kinds disagree:
SerializeAfter takes exactly the verdict
Self::Open takes at every site, and OpenAfter takes the same
except at Site::StreamHeader, where the peer stream already
exists and there is nothing left to defer.
use moqtap_proxy::capability::{classify, ActionKind, CapCtx, Refusal, Site, Support};
for site in [Site::StreamOpen, Site::StreamHeader] {
assert_eq!(
classify(site, ActionKind::SerializeAfter, &CapCtx::default()),
classify(site, ActionKind::Open, &CapCtx::default()),
"SerializeAfter tracks Open at every site",
);
}
assert_eq!(
classify(Site::StreamOpen, ActionKind::OpenAfter, &CapCtx::default()),
Support::Yes,
);
assert_eq!(
classify(Site::StreamHeader, ActionKind::OpenAfter, &CapCtx::default()),
Support::No(Refusal::WrongSite {
site: Site::StreamHeader,
action: ActionKind::OpenAfter,
}),
);SerializeAfter
Head-of-line simulation.
StreamAction::SerializeAfter,
shipped in 0.4.0; this kind is no longer in the constructor-less
family either.
Its constructor proof hangs on Self::OpenAfter, with its pair,
as its compile_fail block used to.
Trait Implementations§
Source§impl Clone for ActionKind
impl Clone for ActionKind
Source§fn clone(&self) -> ActionKind
fn clone(&self) -> ActionKind
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more