rustwave 0.1.0

A lightweight async event-driven WebSocket framework for Rust
Documentation
use std::sync::Arc;

use serde::Serialize;

use uuid::Uuid;

use crate::{
    error::Result, peer::peer_state::PeerState, utils::broadcast_builder::BroadcastBuilder,
};

/// A handle representing a single connected client (peer).
///
/// # Example
///
/// ```no_run
/// 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 Id: {}", ctx.get_socket_id());
///     });
///     Ok(())
/// }
/// ```
#[derive(Clone)]
pub struct PeerContext {
    inner: Arc<PeerState>,
}

impl PeerContext {
    pub(crate) fn new(inner: Arc<PeerState>) -> Self {
        Self { inner }
    }

    pub(crate) fn get_peer_state(&self) -> Arc<PeerState> {
        self.inner.clone()
    }

    /// Returns the unique socket id assigned to this client.
    ///
    /// # Example
    ///
    /// ```no_run
    /// 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 Id: {}", ctx.get_socket_id());
    ///     });
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn get_socket_id(&self) -> Uuid {
        self.inner.get_socket_id()
    }

    /// Sends an event directly to this client.
    ///
    /// # Arguments
    ///
    /// * `event` - The name of the event to emit.
    /// * `data` - The data to send with the event.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use rustwave::{Server, Result};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let server = Server::bind("127.0.0.1:8080");
    ///
    ///     server.on("connection", |_data, ctx| async move {
    ///         let _ = ctx.emit("message", "hello").await;
    ///     });
    ///
    ///     Ok(())
    /// }
    /// ```
    pub async fn emit<T: Serialize>(&self, event: &str, data: T) -> Result<()> {
        self.inner.emit(event, data).await
    }

    /// Adds this client to `room`.
    ///
    /// # Arguments
    ///
    /// * `room` - The room to join.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use rustwave::{Server, Result};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let server = Server::bind("127.0.0.1:8080");
    ///
    ///     server.on("connection", |_data, ctx| async move {
    ///         ctx.join_room("room-1");
    ///     });
    ///
    ///    Ok(())
    /// }
    /// ```
    pub fn join_room(&self, room: &str) {
        self.inner.join_room(room);
    }

    /// Removes this client to `room`.
    ///
    /// # Arguments
    ///
    /// * `room` - The room to leave.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use rustwave::{Server, Result};
    ///
    /// #[tokio::main]
    /// async fn main() -> Result<()> {
    ///     let server = Server::bind("127.0.0.1:8080");
    ///
    ///     server.on("connection", |_data, ctx| async move {
    ///         ctx.leave_room("room-1");
    ///     });
    ///
    ///     Ok(())
    /// }
    /// ```
    pub fn leave_room(&self, room: &str) {
        self.inner.leave_room(room);
    }

    /// Starts building a broadcast from this client, using [`BroadcastBuilder`].
    ///
    /// By default it targets all clients, but `.room(...)` and `.expect(...)`
    /// can be chained before calling `.send()`.
    ///
    /// # Arguments
    ///
    /// * `event` - The event to broadcast.
    /// * `data` - The data to broadcast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// 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 {
    ///         let _ = ctx.broadcast("message", data.raw()).send().await;
    ///     });
    ///     Ok(())
    /// }
    /// ```
    pub fn broadcast<T: Serialize>(&self, event: &str, data: T) -> BroadcastBuilder<T> {
        self.inner.broadcast(event, data)
    }

    /// Broadcasts an event to every client in `room`.
    ///
    /// # Arguments
    ///
    /// * `room` - The room to broadcast to.
    /// * `event` - The event to broadcast.
    /// * `data` - The data to broadcast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// 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 {
    ///         let _ = ctx.broadcast_to_room("room-1", "message", data.raw()).await;
    ///     });
    ///
    ///
    ///     Ok(())
    /// }
    /// ```
    pub async fn broadcast_to_room<T: Serialize>(
        &self,
        room: &str,
        event: &str,
        data: T,
    ) -> Result<()> {
        self.inner.broadcast_to_room(room, event, data).await?;
        Ok(())
    }

    /// Broadcasts an event to every client in `room`, except the one
    /// matching `socket_id`.
    ///
    /// Commonly used to notify everyone else in a room while excluding the
    /// sender itself.
    ///
    /// # Arguments
    ///
    /// * `room` - The room to broadcast to.
    /// * `socket_id` - The id of the client to exclude.
    /// * `event` - The event to broadcast.
    /// * `data` - The data to broadcast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// 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 {
    ///         let _ = ctx.broadcast_to_expect("room-1", ctx.get_socket_id(), "message", data.raw()).await;
    ///     });
    ///
    ///     Ok(())
    /// }
    /// ```
    pub async fn broadcast_to_expect<T: Serialize>(
        &self,
        room: &str,
        socket_id: Uuid,
        event: &str,
        data: T,
    ) -> Result<()> {
        self.inner
            .broadcast_to_expect(room, socket_id, event, data)
            .await?;
        Ok(())
    }
}