Browse Source

Move join() from RoomMap to RoomEntry.

main
Titouan Rigoudy 2 years ago
parent
commit
30044af1c6
4 changed files with 101 additions and 74 deletions
  1. +3
    -8
      client/src/client.rs
  2. +7
    -10
      client/src/handlers/room_join_response_handler.rs
  3. +84
    -55
      client/src/room/map.rs
  4. +7
    -1
      proto/src/core/user.rs

+ 3
- 8
client/src/client.rs View File

@ -547,14 +547,7 @@ impl Client {
mut response: server::RoomJoinResponse, mut response: server::RoomJoinResponse,
) { ) {
// Join the room and store the received information. // Join the room and store the received information.
let result = self.rooms.join(
&response.room_name,
response.owner,
response.operators,
&response.users,
);
let room = match result {
let room = match self.rooms.get_mut_strict(&response.room_name) {
Ok(room) => room, Ok(room) => room,
Err(err) => { Err(err) => {
error!("RoomJoinResponse: {}", err); error!("RoomJoinResponse: {}", err);
@ -562,6 +555,8 @@ impl Client {
} }
}; };
room.join(response.owner, response.operators, &response.users);
// Then update the user structs based on the info we just got. // Then update the user structs based on the info we just got.
for user in response.users.drain(..) { for user in response.users.drain(..) {
self.users.insert(user); self.users.insert(user);


+ 7
- 10
client/src/handlers/room_join_response_handler.rs View File

@ -17,16 +17,13 @@ impl MessageHandler for RoomJoinResponseHandler {
response: &RoomJoinResponse, response: &RoomJoinResponse,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
{ {
let room = context
.state
.rooms
.join(
&response.room_name,
response.owner.clone(),
response.operators.clone(),
&response.users,
)
.context("joining room")?;
let room = context.state.rooms.get_mut_strict(&response.room_name)?;
room.join(
response.owner.clone(),
response.operators.clone(),
&response.users,
);
// Send under lock to avoid out-of-order sends. // Send under lock to avoid out-of-order sends.
let control_response = let control_response =


+ 84
- 55
client/src/room/map.rs View File

@ -28,13 +28,14 @@ pub struct RoomNotFoundError(String);
/// An entry in the chat room map. /// An entry in the chat room map.
#[derive(Debug)] #[derive(Debug)]
pub struct RoomEntry { pub struct RoomEntry {
name: String,
state: RoomState, state: RoomState,
} }
impl RoomEntry { impl RoomEntry {
/// Creates a new entry with the given state. /// Creates a new entry with the given state.
pub fn new(state: RoomState) -> Self {
Self { state }
pub fn new(name: String, state: RoomState) -> Self {
Self { name, state }
} }
/// Returns a copy of the room state contained in this entry. /// Returns a copy of the room state contained in this entry.
@ -42,14 +43,17 @@ impl RoomEntry {
self.state.clone() self.state.clone()
} }
pub fn into_state(self) -> RoomState {
self.state
}
/// Inserts the given message in this chat room's history. /// Inserts the given message in this chat room's history.
pub fn insert_message(&mut self, message: RoomMessage) { pub fn insert_message(&mut self, message: RoomMessage) {
self.state.messages.insert(message) self.state.messages.insert(message)
} }
/// Records that we are now trying to join the given room.
/// If the room is not found, or if its membership is not `NonMember`,
/// returns an error.
/// Records that we are now trying to join this room.
/// Returns an error if its membership is not `NonMember`,
pub fn start_joining(&mut self) -> Result<(), RoomMembershipChangeError> { pub fn start_joining(&mut self) -> Result<(), RoomMembershipChangeError> {
match self.state.membership { match self.state.membership {
RoomMembership::NonMember => { RoomMembership::NonMember => {
@ -63,6 +67,31 @@ impl RoomEntry {
)), )),
} }
} }
/// Records that we are now a member of this room and updates its state.
pub fn join(
&mut self,
owner: Option<String>,
mut operators: Vec<String>,
members: &[User],
) {
// Log what's happening.
if let RoomMembership::Joining = self.state.membership {
info!("Joined room {:?}", self.name);
} else {
warn!(
"Joined room {:?} but membership was already {:?}",
self.name, self.state.membership
);
}
// Update the room state.
self.state.membership = RoomMembership::Member;
self.state.user_count = members.len();
self.state.owner = owner;
self.state.operators = operators.drain(..).collect();
self.state.members = members.iter().map(|user| user.name.clone()).collect();
}
} }
/// Contains the mapping from room names to room data and provides a clean /// Contains the mapping from room names to room data and provides a clean
@ -84,7 +113,7 @@ impl RoomMap {
pub fn insert(&mut self, name: String, room: RoomState) -> Option<RoomState> { pub fn insert(&mut self, name: String, room: RoomState) -> Option<RoomState> {
self self
.map .map
.insert(name, RoomEntry::new(room))
.insert(name.clone(), RoomEntry::new(name, room))
.map(|entry| entry.state) .map(|entry| entry.state)
} }
@ -123,10 +152,10 @@ impl RoomMap {
) { ) {
let room = match old_map.remove(&name) { let room = match old_map.remove(&name) {
None => RoomState::new(RoomVisibility::Public, user_count as usize), None => RoomState::new(RoomVisibility::Public, user_count as usize),
Some(RoomEntry { mut state }) => {
state.visibility = visibility;
state.user_count = user_count as usize;
state
Some(mut entry) => {
entry.state.visibility = visibility;
entry.state.user_count = user_count as usize;
entry.state
} }
}; };
if let Some(_) = self.insert(name, room) { if let Some(_) = self.insert(name, room) {
@ -183,46 +212,6 @@ impl RoomMap {
rooms rooms
} }
/// Records that we are now a member of the given room and updates the room
/// information.
pub fn join(
&mut self,
room_name: &str,
owner: Option<String>,
mut operators: Vec<String>,
members: &[User],
) -> Result<&RoomEntry, RoomError> {
// First look up the room struct.
let room = self.get_mut_strict(room_name)?;
// Log what's happening.
if let RoomMembership::Joining = room.state.membership {
info!("Joined room {:?}", room_name);
} else {
warn!(
"Joined room {:?} but membership was already {:?}",
room_name, room.state.membership
);
}
// Update the room state.
room.state.membership = RoomMembership::Member;
room.state.user_count = members.len();
room.state.owner = owner;
room.state.operators.clear();
for user_name in operators.drain(..) {
room.state.operators.insert(user_name);
}
room.state.members.clear();
for user in members {
room.state.members.insert(user.name.clone());
}
Ok(room)
}
#[allow(dead_code)] #[allow(dead_code)]
/// Records that we are now trying to leave the given room. /// Records that we are now trying to leave the given room.
/// If the room is not found, or if its membership status is not `Member`, /// If the room is not found, or if its membership status is not `Member`,
@ -300,6 +289,8 @@ impl RoomMap {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::collections::HashSet;
use solstice_proto::server::RoomListResponse; use solstice_proto::server::RoomListResponse;
use crate::room::{RoomMembership, RoomState, RoomVisibility}; use crate::room::{RoomMembership, RoomState, RoomVisibility};
@ -308,10 +299,13 @@ mod tests {
#[test] #[test]
fn entry_start_joining_error() { fn entry_start_joining_error() {
let mut room = RoomEntry::new(RoomState {
membership: RoomMembership::Member,
..RoomState::default()
});
let mut room = RoomEntry::new(
"bleep".to_string(),
RoomState {
membership: RoomMembership::Member,
..RoomState::default()
},
);
room.start_joining().unwrap_err(); room.start_joining().unwrap_err();
@ -320,13 +314,48 @@ mod tests {
#[test] #[test]
fn entry_start_joining_success() { fn entry_start_joining_success() {
let mut room = RoomEntry::new(RoomState::default());
let mut room = RoomEntry::new("bleep".to_string(), RoomState::default());
room.start_joining().unwrap(); room.start_joining().unwrap();
assert_eq!(room.clone_state().membership, RoomMembership::Joining); assert_eq!(room.clone_state().membership, RoomMembership::Joining);
} }
#[test]
fn entry_join() {
let mut room = RoomEntry::new("bleep".to_string(), RoomState::default());
let owner = Some("owner".to_string());
let mut operators = vec!["operator1".to_string(), "operator2".to_string()];
let users = [
User {
name: "shruti".to_string(),
..User::default()
},
User {
name: "kim".to_string(),
..User::default()
},
];
room.join(owner.clone(), operators.clone(), &users);
assert_eq!(
room.into_state(),
RoomState {
membership: RoomMembership::Member,
owner: owner,
operators: operators.drain(..).collect::<HashSet<String>>(),
user_count: 2,
members: users
.iter()
.map(|user| user.name.clone())
.collect::<HashSet<String>>(),
..RoomState::default()
}
);
}
#[test] #[test]
fn map_new_is_empty() { fn map_new_is_empty() {
assert_eq!(RoomMap::new().get_room_list(), vec![]); assert_eq!(RoomMap::new().get_room_list(), vec![]);


+ 7
- 1
proto/src/core/user.rs View File

@ -22,6 +22,12 @@ pub enum UserStatus {
Online, Online,
} }
impl Default for UserStatus {
fn default() -> Self {
Self::Offline
}
}
impl ValueEncode for UserStatus { impl ValueEncode for UserStatus {
fn encode_to( fn encode_to(
&self, &self,
@ -55,7 +61,7 @@ impl ValueDecode for UserStatus {
/// This structure contains the last known information about a fellow user. /// This structure contains the last known information about a fellow user.
#[derive( #[derive(
Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize,
Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize,
)] )]
pub struct User { pub struct User {
/// The name of the user. /// The name of the user.


Loading…
Cancel
Save