pub trait Plugin: Send {
// Required methods
fn name(&self) -> &str;
fn on_bytes(&mut self, ctx: &mut Ctx<'_>, input: &[u8]) -> Result<()>;
// Provided methods
fn on_eof(&mut self, ctx: &mut Ctx<'_>) -> Result<()> { ... }
fn tick_interval(&self) -> Option<Duration> { ... }
fn on_tick(&mut self, ctx: &mut Ctx<'_>) -> Result<()> { ... }
fn datagram_safe(&self) -> bool { ... }
}Expand description
One stage of a pipeline. Instances are per-direction and per-connection.
Synchronous on purpose: it is the only shape that maps onto a WASM guest call, and it keeps the per-chunk cost at a function call rather than a future poll. Anything that must await belongs on the effect side, where the host performs it off the critical path.
Required Methods§
Sourcefn on_bytes(&mut self, ctx: &mut Ctx<'_>, input: &[u8]) -> Result<()>
fn on_bytes(&mut self, ctx: &mut Ctx<'_>, input: &[u8]) -> Result<()>
A chunk arrived from upstream. input is the same slice as
Ctx::input; it is passed separately because it is the hot argument.
One call is one unit. Where a stage above declared framing with
Ctx::boundary that is one call per unit rather than one per chunk,
so a stage never has to unpick two of them from a single slice.
Provided Methods§
Sourcefn on_eof(&mut self, ctx: &mut Ctx<'_>) -> Result<()>
fn on_eof(&mut self, ctx: &mut Ctx<'_>) -> Result<()>
Upstream reached EOF. Last chance to emit buffered bytes.
Sourcefn tick_interval(&self) -> Option<Duration>
fn tick_interval(&self) -> Option<Duration>
How often this stage wants on_tick called, or
None (the default) for never.
Read once, at the end of construction, so it must not depend on
anything that changes later. A stage whose interval is configurable
reads its config in PluginFactory::build and answers from that.
The host owns the clock. A guest cannot read one (a WASM module has no way to reach the host’s time) which is why this is a period the stage asks for rather than a timestamp it checks. The cost falls on the relay: one timer per direction per connection for any pipeline containing a ticking stage, so a stage asking for milliseconds is asking every forked connection to wake up that often.
Sourcefn on_tick(&mut self, ctx: &mut Ctx<'_>) -> Result<()>
fn on_tick(&mut self, ctx: &mut Ctx<'_>) -> Result<()>
The stage’s schedule came due.
Called from the same task, and under the same rules, as
on_bytes, it just arrives without any. This is
how a stage does anything that time rather than traffic should drive:
report a measurement, release bytes it has been holding back, emit a
keepalive. Without it a stalled stream and a finished one are
indistinguishable from inside a plugin.
Ctx::input is empty, so there is nothing to pass through; anything
emitted here is emitted with Ctx::forward and continues downstream
through the stages below this one, in the same way
on_eof cascades. Emitting nothing is the common
case and costs nothing.
A stage that emits from here is fabricating a message boundary on a
datagram path (the bytes belong to no datagram the peer sent) so it
should report datagram_safe as false. A
stage that only observes need not.
What is emitted here is one unit unless Ctx::boundary says
otherwise, exactly as in on_bytes.
Ticks run for the life of the pipeline and stop at end of stream, so they arrive whether or not anything is moving, which is the point, and is what a keepalive needs. A stage that has nothing to say until the first chunk has arrived is expected to keep that state itself.
Sourcefn datagram_safe(&self) -> bool
fn datagram_safe(&self) -> bool
Whether this stage may sit on a path carrying datagrams.
On a byte stream a chunk is an arbitrary slice: a stage may buffer,
split or coalesce freely, and the host is free to do the same. On a
datagram path the chunk is the message: one on_bytes call per
datagram, and whatever it emits is sent as exactly one datagram. A
stage that buffers across calls, or emits two messages’ worth from one,
silently corrupts the protocol.
Ctx::boundary makes the second of those sayable rather than silent:
a stage that emits several units emits several messages. That is still
a rewrite of the peer’s message stream rather than a preservation of
it, so a stage doing it should say false here and let the host decide
whether to warn.
Defaults to false because that is the safe answer for a stage that has
not thought about it, including any plugin loaded from outside this
binary. A pure observer that only calls pass_through can say true;
anything holding state across calls should not.
Trait Implementations§
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".