qrpc-0.1.0 has been yanked.
qrpc
qrpc is a small QUIC + mTLS messaging library where each QrpcInstance works as both server and client.
Features:
- bidirectional long-lived connections,
- peer registration by unique ID,
- direct send and broadcast,
- typestate builder (
WithoutState / WithState),
- user-defined message trait (
QrpcMessage) with no protobuf requirement.
Minimal Usage (Self-Contained, No Proto)
This is the smallest complete setup using:
- an empty
AppState struct,
- a custom text message type,
- a single
QrpcInstance.
use std::sync::Arc;
use qrpc::{QrpcInstance, QrpcMessage, QrpcResult};
#[derive(Default)]
struct AppState {}
struct TextMessage(String);
impl QrpcMessage for TextMessage {
fn cmd_id(&self) -> u32 { 1 }
fn encode_vec(&self) -> Vec<u8> {
self.0.as_bytes().to_vec()
}
fn decode_vec(cmd_id: u32, data: &[u8]) -> QrpcResult<Self> {
if cmd_id != 1 {
return Err(qrpc::QrpcError::MessageDecode("unexpected cmd_id".to_string()));
}
let s = String::from_utf8(data.to_vec())
.map_err(|e| qrpc::QrpcError::MessageDecode(format!("utf8 decode failed: {e}")))?;
Ok(Self(s))
}
}
#[tokio::main]
async fn main() -> QrpcResult<()> {
let instance = QrpcInstance::<AppState, TextMessage, _>::builder(
|_state: Arc<AppState>, peer_id: String, msg: TextMessage| async move {
println!("from={peer_id}, text={}", msg.0);
Ok(())
},
)
.with_state(Arc::new(AppState::default()))
.with_id("node-a")
.with_ca_cert("tests/certs/ca.crt")
.with_identity("tests/certs/server.crt", "tests/certs/server.key")
.with_port(20001)
.build()?;
instance.start().await;
Ok(())
}
State Rules
- Use
.with_state(Arc<S>) to build an instance with any custom state type S.
- If you do not call
with_state, build() is available only for S = () and the builder injects () automatically.
Running Built-in Examples
cargo run --example two_nodes_ping_pong
cargo run --example three_nodes_mesh_direct
cargo run --example three_nodes_broadcast
cargo run --example two_node_20001
cargo run --example two_node_20002
LICENSE
See LICENSE