//! Messages sent from the server to the client by the messenger. use std::collections::HashSet; use serde::{Deserialize, Serialize}; use thiserror::Error; /// Represents the type of message being sent between the client and the server #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub enum MessageType { /// Sent to the client to indicate an error made by the client Error(Error), /// Sent to a client on the initial join, indicating the online users OnlineUsers(HashSet), /// Sent when a user joins the chat. Contains their username UserJoined(String), /// Sent when a user disconnects from the chat. Contains their username UserLeft(String), /// Sent when a user sends a message in the chat. Contains their message UserMessage(UserMessage), } /// Errors the server may respond with when performing operations #[derive(Clone, Debug, Deserialize, Eq, Error, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub enum Error { /// Cannot process the sent message #[error("server cannot process the received message")] CannotProcess, /// Message sent was invalid #[error("server received invalid message")] InvalidMessage, /// Expected different message than received #[error("server received unexpected message (expected {expected:?}, received {received:?}")] UnexpectedMessage { /// Message the server expected to receive expected: crate::client::MessageType, /// Message the server received received: crate::client::MessageType, }, /// Username chosen is not available #[error("chosen username ({chosen_username}) has already been taken")] UsernameNotAvailable { /// Username that was chosen, but is not available chosen_username: String, }, } /// Represents a message sent through a websocket #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct UserMessage { /// Content of the message content: String, /// The name of the message sender sender: String, /// Timestamp indicating when this message was sent #[serde(with = "time::serde::iso8601")] timestamp: time::OffsetDateTime, } impl UserMessage { /// Constructs a new instance of the [`UserMessage`]. #[must_use] pub const fn new(content: String, sender: String, timestamp: time::OffsetDateTime) -> Self { Self { content, sender, timestamp, } } /// Retrieves a reference to the content of the [`UserMessage`]. #[must_use] pub const fn content(&self) -> &String { &self.content } /// Retrieves a reference to the sender of the [`UserMessage`]. #[must_use] pub const fn sender(&self) -> &String { &self.sender } /// Retrieves a timestamp to the content of the [`UserMessage`]. #[must_use] pub const fn timestamp(&self) -> &time::OffsetDateTime { &self.timestamp } } impl From for MessageType { fn from(val: UserMessage) -> Self { Self::UserMessage(val) } }