rustwave 0.1.0

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

use crate::error::Result;
use serde::Serialize;
use uuid::Uuid;

use crate::server::server_handler::ServerStates;

/// A builder for sending an event to multiple clients, with optional
/// room targeting and sender exclusion.
///
/// # 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())
///             .room("room-1")
///             .send()
///             .await;
///     });
///
///     server.run().await?;
///     Ok(())
/// }
/// ```
pub struct BroadcastBuilder<T: Serialize> {
    event: String,
    data: T,
    expect: Option<Uuid>,
    room: Option<String>,
    server: Arc<ServerStates>,
}

impl<T: Serialize> BroadcastBuilder<T> {
    pub(crate) fn new(event: String, data: T, server: Arc<ServerStates>) -> Self {
        Self {
            event,
            data,
            expect: None,
            room: None,
            server,
        }
    }

    /// Excludes the client matching `socket_id` from the 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 sender_id = ctx.get_socket_id();
    ///     let _ = ctx.broadcast("message", data.raw())
    ///         .expect(sender_id)
    ///         .send()
    ///         .await;
    /// });
    /// # Ok(())
    /// # }
    /// ```
    pub fn expect(mut self, socket_id: Uuid) -> Self {
        self.expect = Some(socket_id);
        self
    }

    /// Restricts the broadcast to clients that have joined `room`.
    ///
    /// If not called, the event is sent to every connected client instead.
    ///
    /// # 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 sender_id = ctx.get_socket_id();
    ///     let _ = ctx.broadcast("message", data.raw())
    ///         .room("room-1")
    ///         .send()
    ///         .await;
    /// });
    /// # Ok(())
    /// # }
    /// ```
    pub fn room(mut self, room: &str) -> Self {
        self.room = Some(room.to_string());
        self
    }

    /// Dispatches the broadcast, applying any `.room(...)` / `.expect(...)`
    /// configuration set beforehand.
    ///
    /// # 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 sender_id = ctx.get_socket_id();
    ///     let _ = ctx.broadcast("message", data.raw())
    ///         .room("room-1")
    ///         .expect(sender_id)
    ///         .send()
    ///         .await;
    /// });
    /// # Ok(())
    /// # }
    /// ```
    pub async fn send(&self) -> Result<()> {
        match &self.room {
            Some(v) => {
                if let Some(id) = self.expect {
                    self.server
                        .room_broadcast_except(v, &id, &self.event, &self.data)
                        .await?;
                    Ok(())
                } else {
                    self.server
                        .room_broadcast(v, &self.event, &self.data)
                        .await?;
                    Ok(())
                }
            }
            None => {
                self.server.broadcast(&self.event, &self.data).await?;
                Ok(())
            }
        }
    }
}