diff options
| author | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:13:20 +1200 |
|---|---|---|
| committer | Sophie Forrest <git@sophieforrest.com> | 2024-08-30 23:13:44 +1200 |
| commit | e3cb82a3b33bd2a2e49c58ce18d1258fb505869e (patch) | |
| tree | 2375279182fb4f90f5c28560a08cda90591f608b /crates/messenger_common/src | |
Diffstat (limited to '')
| -rw-r--r-- | crates/messenger_common/src/client.rs | 15 | ||||
| -rw-r--r-- | crates/messenger_common/src/lib.rs | 77 | ||||
| -rw-r--r-- | crates/messenger_common/src/server.rs | 107 |
3 files changed, 199 insertions, 0 deletions
diff --git a/crates/messenger_common/src/client.rs b/crates/messenger_common/src/client.rs new file mode 100644 index 0000000..69a7fd6 --- /dev/null +++ b/crates/messenger_common/src/client.rs @@ -0,0 +1,15 @@ +//! Messages sent from the client to the server by the messenger. + +use serde::{Deserialize, Serialize}; + +/// 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 when a user joins the chat. Contains the username they wish to pick + SetUsername(String), + + /// Sent when a user sends a message in the chat. Contains their message as + /// a string + UserMessage(String), +} diff --git a/crates/messenger_common/src/lib.rs b/crates/messenger_common/src/lib.rs new file mode 100644 index 0000000..c05e870 --- /dev/null +++ b/crates/messenger_common/src/lib.rs @@ -0,0 +1,77 @@ +#![feature(custom_inner_attributes)] +#![feature(lint_reasons)] +#![feature(never_type)] +#![feature(lazy_cell)] +#![clippy::msrv = "1.69.0"] +#![deny(clippy::nursery)] +#![deny(clippy::pedantic)] +#![deny(clippy::alloc_instead_of_core)] +#![deny(clippy::as_underscore)] +#![deny(clippy::clone_on_ref_ptr)] +#![deny(clippy::create_dir)] +#![warn(clippy::dbg_macro)] +#![deny(clippy::default_numeric_fallback)] +#![deny(clippy::default_union_representation)] +#![deny(clippy::deref_by_slicing)] +#![deny(clippy::else_if_without_else)] +#![deny(clippy::empty_structs_with_brackets)] +#![deny(clippy::exit)] +#![deny(clippy::filetype_is_file)] +#![deny(clippy::fn_to_numeric_cast)] +#![deny(clippy::format_push_string)] +#![deny(clippy::get_unwrap)] +#![deny(clippy::if_then_some_else_none)] +#![allow( + clippy::implicit_return, + reason = "returns should be done implicitly, not explicitly" +)] +#![deny(clippy::indexing_slicing)] +#![deny(clippy::large_include_file)] +#![deny(clippy::let_underscore_must_use)] +#![deny(clippy::lossy_float_literal)] +#![deny(clippy::map_err_ignore)] +#![deny(clippy::mem_forget)] +#![deny(clippy::missing_docs_in_private_items)] +#![deny(clippy::missing_trait_methods)] +#![deny(clippy::multiple_inherent_impl)] +#![deny(clippy::needless_return)] +#![deny(clippy::non_ascii_literal)] +#![deny(clippy::panic_in_result_fn)] +#![deny(clippy::pattern_type_mismatch)] +#![deny(clippy::rc_buffer)] +#![deny(clippy::rc_mutex)] +#![deny(clippy::rest_pat_in_fully_bound_structs)] +#![deny(clippy::same_name_method)] +#![deny(clippy::separated_literal_suffix)] +#![deny(clippy::str_to_string)] +#![deny(clippy::string_add)] +#![deny(clippy::string_slice)] +#![deny(clippy::string_to_string)] +#![allow( + clippy::tabs_in_doc_comments, + reason = "tabs are preferred for this project" +)] +#![deny(clippy::try_err)] +#![deny(clippy::undocumented_unsafe_blocks)] +#![deny(clippy::unnecessary_self_imports)] +#![deny(clippy::unneeded_field_pattern)] +#![deny(clippy::unwrap_in_result)] +#![deny(clippy::unwrap_used)] +#![warn(clippy::use_debug)] +#![deny(clippy::verbose_file_reads)] +#![deny(clippy::wildcard_dependencies)] +#![deny(clippy::wildcard_enum_match_arm)] +#![deny(clippy::missing_panics_doc)] +#![deny(missing_copy_implementations)] +#![deny(missing_debug_implementations)] +#![deny(missing_docs)] +#![deny(single_use_lifetimes)] +#![deny(unsafe_code)] +#![deny(unused)] + +//! # Messenger Common +//! +//! Exports common resources used by the messenger client and server. + +pub mod client; +pub mod server; diff --git a/crates/messenger_common/src/server.rs b/crates/messenger_common/src/server.rs new file mode 100644 index 0000000..678d812 --- /dev/null +++ b/crates/messenger_common/src/server.rs @@ -0,0 +1,107 @@ +//! 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<String>), + + /// 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<UserMessage> for MessageType { + fn from(val: UserMessage) -> Self { + Self::UserMessage(val) + } +} |