Expand description
Trait-based plugin API, inspired by
Pingora’s ProxyHttp/CTX design:
implement Plugin on a struct and export it with export_plugin! —
no raw pointers, no unsafe handlers, panics contained at the ABI
boundary.
Two kinds of state, exactly like Pingora:
- Per-call state lives in
Plugin::Ctx, created fresh byPlugin::new_ctxfor every incoming call and dropped when the call ends. - Cross-call state lives on the plugin struct itself: one instance
serves every call concurrently, so plain fields with
Atomic*,Mutex, or anythingSyncwork like Pingora’s service struct.
use nylon_ring::{export_plugin, NrStatus, Plugin, Reply, Session};
use std::sync::atomic::{AtomicU64, Ordering};
struct Demo {
// cross-call state, shared by every call
calls: AtomicU64,
}
struct DemoCtx {
// per-call state (Pingora-style CTX)
uppercase: bool,
}
impl Plugin for Demo {
type Ctx = DemoCtx;
const ENTRIES: &'static [&'static str] = &["echo", "shout"];
fn new() -> Self {
Demo { calls: AtomicU64::new(0) }
}
fn new_ctx(&self) -> DemoCtx {
DemoCtx { uppercase: false }
}
fn on_call(&self, session: &mut Session<'_>, ctx: &mut DemoCtx) -> Reply {
self.calls.fetch_add(1, Ordering::Relaxed);
match session.entry() {
"echo" => Reply::Bytes(session.payload().to_vec()),
"shout" => {
ctx.uppercase = true;
let text = String::from_utf8_lossy(session.payload()).to_string();
Reply::Text(if ctx.uppercase { text.to_uppercase() } else { text })
}
_ => Reply::Fail(NrStatus::Invalid),
}
}
}
export_plugin!(Demo);Entries listed in Plugin::ASYNC_ENTRIES dispatch to
Plugin::on_async_call instead — a native async handler (no
async_trait crate needed). The ABI callback returns immediately and
the reply is delivered when the future completes, through the host’s
cross-thread async path. Futures run via Plugin::spawn_async:
dependency-free thread-per-call by default, or override it with
tokio::spawn (or any executor) for real workloads.
The raw define_plugin! macro remains available for handlers that need
full control over the ABI (owned responses, buffer leases); the safe
host-call helpers in this module (send_result, send_result_owned,
acquire_result_buffer, commit_result_buffer) can be mixed into
either style.
Structs§
- Async
Session - One incoming async call: like
Sessionbut self-contained — the payload is copied out of host memory so the future may outlive the ABI callback that created it. - Session
- One incoming call: the entry it targets, its payload, and the session id for manual (streaming) replies.
Enums§
- Reply
- What a
Plugin::on_callhandler answers with.
Traits§
- Plugin
- A nylon-ring plugin. Implement this and export it with
export_plugin!; see the module docs for the state model.
Functions§
- acquire_
result_ buffer - Leases a host-owned response buffer for
sid; checkNrBufferLease::is_failedbefore writing. - commit_
result_ buffer - Commits a leased buffer as the response for
sid. - send_
result - Sends a response or stream frame for
sidthrough the host’ssend_result. Borrowed payloads (owned = 0) are copied by the host before this returns. ReportsInvalidwhen the plugin has not been initialized. - send_
result_ owned - Sends a response the host consumes without copying; the host takes ownership and calls the payload’s release exactly once.
Type Aliases§
- Async
Task - A boxed future handed to
Plugin::spawn_async; drive it to completion to deliver the call’s reply.