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 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 — so the family of constructor-less capabilities is simply absent from this enum, and absence is what the table says by not listing it.

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 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.

open_after_and_serialize_after_are_constructible — the pair of doc-tests below are 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, so a block asserting a struct-variant syntax (OpenAfter { after: … }) would go on passing against 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 and the side it arrived on.
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.

Its constructor proof hangs on Self::OpenAfter, with its pair.

Trait Implementations§

Source§

impl Clone for ActionKind

Source§

fn clone(&self) -> Self

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: &Self) -> 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.

§

impl<T> Instrument for T

§

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

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

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, !>

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

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