# RustWave
A lightweight async event-driven WebSocket framework for Rust.
## Installation
```toml
[dependencies]
rustwave = "0.1"
tokio = { version = "1", features = ["full"] }
```
## Table of Contents
- [Basic Server](#basic-server)
- [Basic Client](#basic-client)
- [Namespaces](#namespaces)
- [Rooms](#rooms)
- [Broadcasting](#broadcasting)
- [Emit to a Specific Client](#emit-to-a-specific-client)
- [Connection / Disconnection Events](#connection--disconnection-events)
- [Typed Payloads](#typed-payloads)
- [Checking Client Status](#checking-client-status)
- [Force Disconnect](#force-disconnect)
---
## Basic Server
```rust
use rustwave::{Server, Result};
#[tokio::main]
async fn main() -> Result<()> {
let server = Server::bind("127.0.0.1:8080");
server.on("message", |data, ctx| async move {
println!("Client {} say: {}", ctx.get_socket_id(), data);
let _ = ctx.emit("message", "got it!").await;
});
server.run().await?;
Ok(())
}
```
## Basic Client
```rust
use rustwave::{Client, Result};
#[tokio::main]
async fn main() -> Result<()> {
let client = Client::connect("ws://127.0.0.1:8080").await?;
client.on("message", |data| async move {
println!("Server say: {}", data);
});
client.emit("message", "hello").await?;
client.wait().await;
Ok(())
}
```
## Namespaces
```rust
use rustwave::{Server, Result};
#[tokio::main]
async fn main() -> Result<()> {
let server = Server::bind("127.0.0.1:8080");
// events on the root namespace ("/")
server.on("message", |data, ctx| async move {
println!("[root] {}: {}", ctx.get_socket_id(), data);
});
// custom namespace
let chat = server.namespace("/chat");
chat.on("message", |data, ctx| async move {
println!("[chat] {}: {}", ctx.get_socket_id(), data);
});
server.run().await?;
Ok(())
}
```
Connect a client to a specific namespace by including it in the URL:
```rust
let root_client = Client::connect("ws://127.0.0.1:8080/").await?;
let chat_client = Client::connect("ws://127.0.0.1:8080/chat").await?;
```
## Rooms
```rust
ctx.leave_room("room-1");
});
let _ = ctx.broadcast_to_room("room-1", "room-message", text).await;
});
```
## Broadcasting
```rust
// send to everyone in the namespace
});
// send to everyone in a room
.room("room-1")
.send()
.await;
});
// send to everyone in a room, except the sender
let _ = ctx.broadcast("message", data.raw())
.room("room-1")
.expect(sender_id)
.send()
.await;
});
// shorthand: broadcast to room, excluding sender
let _ = ctx.broadcast_to_expect("room-1", sender_id, "message", data.raw()).await;
});
// broadcast from a Namespace handle directly (e.g. outside a handler)
let chat = server.namespace("/chat");
chat.emit("announcement", "server restarting soon").await?;
chat.emit_to_room("room-1", "message", "hello room!").await?;
```
## Emit to a Specific Client
```rust
use uuid::Uuid;
let chat = server.namespace("/chat");
let socket_id: Uuid = /* ... */;
chat.emit_to(&socket_id, "private-message", "Hello there").await?;
```
## Connection / Disconnection Events
```rust
println!("client disconnected: {}", ctx.get_socket_id());
});
```
Client-side disconnect handling:
```rust
```
## Typed Payloads
```rust
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
struct Message {
text: String,
room: String,
}
println!("Client {} say: {} in {}", ctx.get_socket_id(), msg.text, msg.room);
}
});
// sending a typed struct works too
client.emit("message", Message {
text: "hey!".to_string(),
room: "general".to_string(),
}).await?;
```
## Checking Client Status
```rust
let chat = server.namespace("/chat");
println!("connected clients: {}", chat.get_client_count());
if chat.is_connected(&some_socket_id) {
println!("still online");
}
```
## Force Disconnect
```rust
let chat = server.namespace("/chat");
// disconnect a single client
chat.disconnect(&some_socket_id).await?;
// disconnect everyone in the namespace
chat.disconnect_all().await?;
```
---
## Example Chat Application
A complete chat application demonstrating:
- Client & Server
- Rooms
- Broadcasting
- Typed payloads
- Join room events
| Server | [`examples/terminal_server.rs`](examples/chat_server.rs) |
| Client | [`examples/terminal_client.rs`](examples/chat_client.rs) |
Run the server:
```bash
cargo run --example terminal_server
```
Run one or more clients:
```bash
cargo run --example terminal_client
```