3 Commits

6 changed files with 161 additions and 150 deletions
Unified View
  1. +2
    -2
      client/src/dispatcher.rs
  2. +0
    -1
      client/src/main.rs
  3. +0
    -0
      client/src/room/event.rs
  4. +6
    -147
      client/src/room/map.rs
  5. +7
    -0
      client/src/room/mod.rs
  6. +146
    -0
      client/src/room/state.rs

+ 2
- 2
client/src/dispatcher.rs View File

@ -9,7 +9,7 @@ use crate::context::Context;
use crate::control::Request as ControlRequest; use crate::control::Request as ControlRequest;
use crate::handlers::*; use crate::handlers::*;
use crate::message_handler::MessageHandler; use crate::message_handler::MessageHandler;
use crate::room_event::{HandleRoomEvent, RoomEvent, RoomEventHandler};
use crate::room::{HandleRoomEvent, RoomEvent, RoomEventHandler};
/// The type of messages dispatched by a dispatcher. /// The type of messages dispatched by a dispatcher.
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
@ -167,7 +167,7 @@ mod tests {
use crate::context::ContextBundle; use crate::context::ContextBundle;
use crate::control; use crate::control;
use crate::dispatcher::Message; use crate::dispatcher::Message;
use crate::room_event::testing::FakeRoomEventHandler;
use crate::room::testing::FakeRoomEventHandler;
use super::*; use super::*;


+ 0
- 1
client/src/main.rs View File

@ -18,7 +18,6 @@ mod login;
mod message_handler; mod message_handler;
mod peer; mod peer;
mod room; mod room;
mod room_event;
#[cfg(test)] #[cfg(test)]
mod testing; mod testing;
mod user; mod user;


client/src/room_event.rs → client/src/room/event.rs View File


client/src/room.rs → client/src/room/map.rs View File

@ -1,153 +1,11 @@
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::mem; use std::mem;
use std::time::SystemTime;
use log::{error, info, warn}; use log::{error, info, warn};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use solstice_proto::{server, User}; use solstice_proto::{server, User};
use thiserror::Error; use thiserror::Error;
/// This enumeration is the list of possible membership states for a chat room.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Membership {
/// The user is not a member of this room.
NonMember,
/// The user has requested to join the room, but hasn't heard back from the
/// server yet.
Joining,
/// The user is a member of the room.
Member,
/// The user has request to leave the room, but hasn't heard back from the
/// server yet.
Leaving,
}
/// This enumeration is the list of visibility types for rooms that the user is
/// a member of.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Visibility {
/// This room is visible to any user.
Public,
/// This room is visible only to members, and the user owns it.
PrivateOwned,
/// This room is visible only to members, and someone else owns it.
PrivateOther,
}
/// A message sent to a chat room.
#[derive(
Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize,
)]
pub struct Message {
/// Time at which the message was received by this client.
///
/// We use `SystemTime` instead of `Instant` because this is serialized and
/// sent to API clients.
///
/// Defined first in order for the `Ord` and `PartialOrd` derived traits to
/// sort by this key first.
pub received_at: SystemTime,
/// The user name of the message sender.
pub user_name: String,
/// The contents of the message.
pub message: String,
}
/// The history of messages sent for a single chat room.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MessageHistory {
/// Messages, sorted in increasing order.
messages: Vec<Message>,
}
// MessageHistory should be transparent for serialization purposes.
impl<'de> Deserialize<'de> for MessageHistory {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let messages = Vec::<Message>::deserialize(deserializer)?;
Ok(Self::new(messages))
}
}
// MessageHistory should be transparent for serialization purposes.
impl Serialize for MessageHistory {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.messages.serialize(serializer)
}
}
impl MessageHistory {
pub fn new(mut messages: Vec<Message>) -> Self {
messages.sort();
Self { messages }
}
/// Inserts a `message` into this history.
pub fn insert(&mut self, message: Message) {
self.messages.push(message);
// This could be terrible for performance in the general case, but we know
// that messages should be coming in almost-always sorted since
// `received_at` is usually set to `now()`.
self.messages.sort();
}
#[cfg(test)]
/// Returns the list of messages sorted in increasing chronological order.
pub fn to_vec(&self) -> Vec<Message> {
return self.messages.clone();
}
}
/// This structure contains the last known information about a chat room.
/// It does not store the name, as that is stored implicitly as the key in the
/// room hash table.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Room {
/// The membership state of the user for the room.
pub membership: Membership,
/// The visibility of the room.
pub visibility: Visibility,
/// True if the user is one of the room's operators, False if the user is a
/// regular member.
pub operated: bool,
/// The number of users that are members of the room.
pub user_count: usize,
/// The name of the room's owner, if any.
pub owner: Option<String>,
/// The names of the room's operators.
pub operators: HashSet<String>,
/// The names of the room's members.
pub members: HashSet<String>,
/// The messages sent to this chat room.
pub messages: MessageHistory,
/// The tickers displayed in this room.
pub tickers: Vec<(String, String)>,
}
impl Room {
/// Creates a new room with the given visibility and user count.
pub fn new(visibility: Visibility, user_count: usize) -> Self {
Room {
membership: Membership::NonMember,
visibility: visibility,
operated: false,
user_count: user_count,
owner: None,
operators: HashSet::new(),
members: HashSet::new(),
messages: MessageHistory::default(),
tickers: Vec::new(),
}
}
}
use crate::room::{Membership, Room, Visibility};
/// The error returned by RoomMap functions. /// The error returned by RoomMap functions.
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -175,7 +33,6 @@ impl RoomMap {
/// Inserts the given room in the map under the given name. /// Inserts the given room in the map under the given name.
/// Same semantics as `std::collections::HashMap::insert()`. /// Same semantics as `std::collections::HashMap::insert()`.
#[cfg(test)]
pub fn insert(&mut self, name: String, room: Room) -> Option<Room> { pub fn insert(&mut self, name: String, room: Room) -> Option<Room> {
self.map.insert(name, room) self.map.insert(name, room)
} }
@ -218,7 +75,7 @@ impl RoomMap {
room room
} }
}; };
if let Some(_) = self.map.insert(name, room) {
if let Some(_) = self.insert(name, room) {
error!("Room present twice in room list response"); error!("Room present twice in room list response");
} }
} }
@ -403,7 +260,9 @@ mod tests {
use solstice_proto::server::RoomListResponse; use solstice_proto::server::RoomListResponse;
use super::{Membership, Message, MessageHistory, Room, RoomMap, Visibility};
use crate::room::{Membership, Message, MessageHistory, Room, Visibility};
use super::RoomMap;
#[test] #[test]
fn deserialize_membership() { fn deserialize_membership() {

+ 7
- 0
client/src/room/mod.rs View File

@ -0,0 +1,7 @@
mod event;
mod map;
mod state;
pub use event::*;
pub use map::*;
pub use state::*;

+ 146
- 0
client/src/room/state.rs View File

@ -0,0 +1,146 @@
use std::collections::HashSet;
use std::time::SystemTime;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// This enumeration is the list of possible membership states for a chat room.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Membership {
/// The user is not a member of this room.
NonMember,
/// The user has requested to join the room, but hasn't heard back from the
/// server yet.
Joining,
/// The user is a member of the room.
Member,
/// The user has request to leave the room, but hasn't heard back from the
/// server yet.
Leaving,
}
/// This enumeration is the list of visibility types for rooms that the user is
/// a member of.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub enum Visibility {
/// This room is visible to any user.
Public,
/// This room is visible only to members, and the user owns it.
PrivateOwned,
/// This room is visible only to members, and someone else owns it.
PrivateOther,
}
/// A message sent to a chat room.
#[derive(
Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize,
)]
pub struct Message {
/// Time at which the message was received by this client.
///
/// We use `SystemTime` instead of `Instant` because this is serialized and
/// sent to API clients.
///
/// Defined first in order for the `Ord` and `PartialOrd` derived traits to
/// sort by this key first.
pub received_at: SystemTime,
/// The user name of the message sender.
pub user_name: String,
/// The contents of the message.
pub message: String,
}
/// The history of messages sent for a single chat room.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MessageHistory {
/// Messages, sorted in increasing order.
messages: Vec<Message>,
}
// MessageHistory should be transparent for serialization purposes.
impl<'de> Deserialize<'de> for MessageHistory {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let messages = Vec::<Message>::deserialize(deserializer)?;
Ok(Self::new(messages))
}
}
// MessageHistory should be transparent for serialization purposes.
impl Serialize for MessageHistory {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.messages.serialize(serializer)
}
}
impl MessageHistory {
pub fn new(mut messages: Vec<Message>) -> Self {
messages.sort();
Self { messages }
}
/// Inserts a `message` into this history.
pub fn insert(&mut self, message: Message) {
self.messages.push(message);
// This could be terrible for performance in the general case, but we know
// that messages should be coming in almost-always sorted since
// `received_at` is usually set to `now()`.
self.messages.sort();
}
#[cfg(test)]
/// Returns the list of messages sorted in increasing chronological order.
pub fn to_vec(&self) -> Vec<Message> {
return self.messages.clone();
}
}
/// This structure contains the last known information about a chat room.
/// It does not store the name, as that is stored implicitly as the key in the
/// room hash table.
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Room {
/// The membership state of the user for the room.
pub membership: Membership,
/// The visibility of the room.
pub visibility: Visibility,
/// True if the user is one of the room's operators, False if the user is a
/// regular member.
pub operated: bool,
/// The number of users that are members of the room.
pub user_count: usize,
/// The name of the room's owner, if any.
pub owner: Option<String>,
/// The names of the room's operators.
pub operators: HashSet<String>,
/// The names of the room's members.
pub members: HashSet<String>,
/// The messages sent to this chat room.
pub messages: MessageHistory,
/// The tickers displayed in this room.
pub tickers: Vec<(String, String)>,
}
impl Room {
/// Creates a new room with the given visibility and user count.
pub fn new(visibility: Visibility, user_count: usize) -> Self {
Room {
membership: Membership::NonMember,
visibility: visibility,
operated: false,
user_count: user_count,
owner: None,
operators: HashSet::new(),
members: HashSet::new(),
messages: MessageHistory::default(),
tickers: Vec::new(),
}
}
}

Loading…
Cancel
Save