qrpc 0.1.0

qrpc is a small QUIC + mTLS messaging library
Documentation
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;

    // Optional:
    // instance.send_to("peer-id", &TextMessage("hello".to_string())).await?;
    // instance.broadcast(&TextMessage("hello all".to_string())).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