diff --git a/client/src/control/response.rs b/client/src/control/response.rs index 0a8804e..c303d41 100644 --- a/client/src/control/response.rs +++ b/client/src/control/response.rs @@ -99,7 +99,7 @@ pub struct UserInfoResponse { /// This stuct contains the last known information about every user. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct UserListResponse { - pub user_list: Vec<(String, User)>, + pub users: Vec<(String, User)>, } #[cfg(test)] @@ -359,7 +359,7 @@ mod tests { assert_eq!( serde_json::from_str::( r#"{ - "user_list": [ + "users": [ ["karandeep", { "name": "karandeep", "status": "Online", @@ -376,7 +376,7 @@ mod tests { ) .unwrap(), UserListResponse { - user_list: vec![( + users: vec![( "karandeep".to_string(), User { name: "karandeep".to_string(), diff --git a/client/src/dispatcher.rs b/client/src/dispatcher.rs index b38a014..c804e42 100644 --- a/client/src/dispatcher.rs +++ b/client/src/dispatcher.rs @@ -11,7 +11,7 @@ use crate::handlers::{ LoginStatusRequestHandler, PrivilegedUsersResponseHandler, RoomJoinRequestHandler, RoomJoinResponseHandler, RoomListRequestHandler, RoomListResponseHandler, RoomMessageRequestHandler, - RoomMessageResponseHandler, + RoomMessageResponseHandler, UserListRequestHandler, }; use crate::message_handler::MessageHandler; @@ -128,6 +128,12 @@ impl Dispatcher { handler: RoomJoinRequestHandler::default(), })) } + Message::ControlRequest(ControlRequest::UserListRequest) => { + Some(Box::new(DispatchedMessage { + message: (), + handler: UserListRequestHandler::default(), + })) + } Message::ControlRequest(request) => { warn!("Unhandled control request: {:?}", request); None diff --git a/client/src/handlers/mod.rs b/client/src/handlers/mod.rs index 6d67f63..ccf2873 100644 --- a/client/src/handlers/mod.rs +++ b/client/src/handlers/mod.rs @@ -6,6 +6,7 @@ mod room_list_request_handler; mod room_list_response_handler; mod room_message_request_handler; mod room_message_response_handler; +mod user_list_request_handler; pub use login_status_request_handler::LoginStatusRequestHandler; pub use privileged_users_response_handler::PrivilegedUsersResponseHandler; @@ -15,3 +16,4 @@ pub use room_list_request_handler::RoomListRequestHandler; pub use room_list_response_handler::RoomListResponseHandler; pub use room_message_request_handler::RoomMessageRequestHandler; pub use room_message_response_handler::RoomMessageResponseHandler; +pub use user_list_request_handler::UserListRequestHandler; diff --git a/client/src/handlers/user_list_request_handler.rs b/client/src/handlers/user_list_request_handler.rs new file mode 100644 index 0000000..9795125 --- /dev/null +++ b/client/src/handlers/user_list_request_handler.rs @@ -0,0 +1,94 @@ +use anyhow::Context as AnyhowContext; + +use crate::context::Context; +use crate::control::{Response, UserListResponse}; +use crate::message_handler::MessageHandler; + +#[derive(Debug, Default)] +pub struct UserListRequestHandler; + +impl MessageHandler for UserListRequestHandler { + type Message = (); + + fn run(self, context: &mut Context, _message: &()) -> anyhow::Result<()> { + let users = context.state.users.get_list(); + let control_response = + Response::UserListResponse(UserListResponse { users }); + + context + .control_response_tx + .blocking_send(control_response) + .context("sending control response")?; + Ok(()) + } + + fn name() -> String { + "UserListRequestHandler".to_string() + } +} + +#[cfg(test)] +mod tests { + use solstice_proto::{User, UserStatus}; + + use crate::context::{ContextBundle, ContextOptions}; + use crate::control::{Response, UserListResponse}; + use crate::message_handler::MessageHandler; + + use super::UserListRequestHandler; + + // Cannot get the compiler to be satisfied when borrowing the name... + fn user_name(pair: &(String, User)) -> String { + pair.0.clone() + } + + #[test] + fn run_sends_response() { + let shruti = User { + name: "shruti".to_string(), + status: UserStatus::Online, + average_speed: 1, + num_downloads: 2, + unknown: 3, + num_files: 4, + num_folders: 5, + num_free_slots: 6, + country: "IN".to_string(), + }; + let yao = User { + name: "yao".to_string(), + status: UserStatus::Away, + average_speed: 11, + num_downloads: 12, + unknown: 13, + num_files: 14, + num_folders: 15, + num_free_slots: 16, + country: "CN".to_string(), + }; + + let mut options = ContextOptions::default(); + options.initial_state.users.insert(shruti.clone()); + options.initial_state.users.insert(yao.clone()); + + let mut bundle = ContextBundle::new(options); + + UserListRequestHandler::default() + .run(&mut bundle.context, &()) + .unwrap(); + + let response = bundle.control_response_rx.blocking_recv().unwrap(); + + let mut users = match response { + Response::UserListResponse(UserListResponse { users }) => users, + _ => panic!("Unexpected control response: {:?}", response), + }; + + users.sort_by_key(user_name); + + assert_eq!( + users, + vec![("shruti".to_string(), shruti), ("yao".to_string(), yao)] + ); + } +} diff --git a/client/src/user.rs b/client/src/user.rs index 28b81f4..cd999f1 100644 --- a/client/src/user.rs +++ b/client/src/user.rs @@ -77,7 +77,6 @@ impl UserMap { Ok(()) } - #[cfg(test)] /// Returns the list of (user name, user data) representing all known users. pub fn get_list(&self) -> Vec<(String, User)> { let mut users = Vec::new();