Skip to main content

ActionKind

Enum ActionKind 

Source
#[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:

KindThe attempt
PassAction::Pass
ReplaceAction::Replace(b)
ReplacePayloadAction::ReplacePayload(b), b.len() == payload_len
ReplaceObjectAction::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)
DelayAction::Pass.delayed(d)
HoldAction::Pass.held(gate)
DropElideAction::Drop(DropMode::Elide)
TruncateAction::Truncate { bytes, code }
ResetStreamAction::ResetStream { code }
CloseSessionAction::CloseSession { code, reason }
OpenStreamAction::Open
RejectStreamAction::Reject { code }
OpenAfterStreamAction::OpenAfter(d)
SerializeAfterStreamAction::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
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Pass

§

Replace

§

ReplacePayload

Action::ReplacePayload at the original length.

§

Delay

§

Hold

§

DropElide

§

Truncate

§

ResetStream

§

CloseSession

§

Open

§

Reject

§

ReplaceObject

Replacing a whole wire object. Attemptable and refused, not unconstructibleAction::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

Source§

fn clone(&self) -> ActionKind

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for ActionKind

Source§

impl Debug for ActionKind

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for ActionKind

Source§

impl PartialEq for ActionKind

Source§

fn eq(&self, other: &ActionKind) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for ActionKind

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more