use std::collections::HashMap;
use std::sync::Arc;
use parking_lot::Mutex;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum GatewayError {
#[error("客户端未找到: {0}")]
ClientNotFound(String),
#[error("群组未找到: {0}")]
GroupNotFound(String),
#[error("发送失败: {0}")]
SendFailed(String),
#[error("无效的 client_id: {0}")]
InvalidClientId(String),
#[error("传输错误: {0}")]
Transport(String),
#[error("序列化失败: {0}")]
Serialize(String),
}
pub type ClientId = String;
#[derive(Debug, Clone)]
pub struct GatewayConfig {
pub register_address: String,
pub heartbeat_interval: u64,
pub default_group: Option<String>,
}
impl Default for GatewayConfig {
fn default() -> Self {
Self {
register_address: "127.0.0.1:1238".to_string(),
heartbeat_interval: 55,
default_group: None,
}
}
}
impl GatewayConfig {
pub fn new(register_address: impl Into<String>) -> Self {
Self {
register_address: register_address.into(),
heartbeat_interval: 55,
default_group: None,
}
}
pub fn with_heartbeat_interval(mut self, interval: u64) -> Self {
self.heartbeat_interval = interval;
self
}
pub fn with_default_group(mut self, group: impl Into<String>) -> Self {
self.default_group = Some(group.into());
self
}
}
pub trait GatewayTransport: Send + Sync {
fn send_to_client(&self, client_id: &str, message: &str) -> Result<(), GatewayError>;
fn send_to_clients(&self, client_ids: &[String], message: &str) -> Result<(), GatewayError>;
fn send_to_all(&self, message: &str) -> Result<(), GatewayError>;
fn send_to_group(&self, group: &str, message: &str) -> Result<(), GatewayError>;
fn get_all_client_ids(&self) -> Result<Vec<String>, GatewayError>;
fn get_client_id_list_by_group(&self, group: &str) -> Result<Vec<String>, GatewayError>;
fn get_groups_by_client_id(&self, client_id: &str) -> Result<Vec<String>, GatewayError>;
fn join_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError>;
fn leave_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError>;
fn ungroup(&self, group: &str) -> Result<(), GatewayError>;
fn is_online(&self, client_id: &str) -> Result<bool, GatewayError>;
fn get_client_count(&self) -> Result<usize, GatewayError>;
fn get_client_count_by_group(&self, group: &str) -> Result<usize, GatewayError>;
fn close_client(&self, client_id: &str) -> Result<(), GatewayError>;
}
#[derive(Debug, Default)]
pub struct MemoryGatewayTransport {
state: Mutex<GatewayState>,
}
#[derive(Debug, Default)]
struct GatewayState {
client_messages: HashMap<ClientId, Vec<String>>,
client_groups: HashMap<ClientId, Vec<String>>,
group_clients: HashMap<String, Vec<ClientId>>,
}
impl MemoryGatewayTransport {
pub fn new() -> Self {
Self::default()
}
pub fn register_client(&self, client_id: &str) {
self.state
.lock()
.client_messages
.entry(client_id.to_string())
.or_default();
}
pub fn client_messages(&self, client_id: &str) -> Vec<String> {
self.state
.lock()
.client_messages
.get(client_id)
.cloned()
.unwrap_or_default()
}
}
impl GatewayTransport for MemoryGatewayTransport {
fn send_to_client(&self, client_id: &str, message: &str) -> Result<(), GatewayError> {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
let mut state = self.state.lock();
match state.client_messages.get_mut(client_id) {
Some(messages) => {
messages.push(message.to_string());
Ok(())
}
None => Err(GatewayError::ClientNotFound(client_id.to_string())),
}
}
fn send_to_clients(&self, client_ids: &[String], message: &str) -> Result<(), GatewayError> {
let mut state = self.state.lock();
for client_id in client_ids {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
if !state.client_messages.contains_key(client_id) {
return Err(GatewayError::ClientNotFound(client_id.to_string()));
}
}
for client_id in client_ids {
if let Some(messages) = state.client_messages.get_mut(client_id) {
messages.push(message.to_string());
}
}
Ok(())
}
fn send_to_all(&self, message: &str) -> Result<(), GatewayError> {
let mut state = self.state.lock();
for messages in state.client_messages.values_mut() {
messages.push(message.to_string());
}
Ok(())
}
fn send_to_group(&self, group: &str, message: &str) -> Result<(), GatewayError> {
let mut state = self.state.lock();
if let Some(client_ids) = state.group_clients.get(group) {
let client_ids = client_ids.clone();
for client_id in client_ids {
if let Some(messages) = state.client_messages.get_mut(&client_id) {
messages.push(message.to_string());
}
}
}
Ok(())
}
fn get_all_client_ids(&self) -> Result<Vec<String>, GatewayError> {
let state = self.state.lock();
Ok(state.client_messages.keys().cloned().collect())
}
fn get_client_id_list_by_group(&self, group: &str) -> Result<Vec<String>, GatewayError> {
let state = self.state.lock();
Ok(state.group_clients.get(group).cloned().unwrap_or_default())
}
fn get_groups_by_client_id(&self, client_id: &str) -> Result<Vec<String>, GatewayError> {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
let state = self.state.lock();
if !state.client_messages.contains_key(client_id) {
return Err(GatewayError::ClientNotFound(client_id.to_string()));
}
Ok(state
.client_groups
.get(client_id)
.cloned()
.unwrap_or_default())
}
fn join_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError> {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
let mut state = self.state.lock();
if !state.client_messages.contains_key(client_id) {
return Err(GatewayError::ClientNotFound(client_id.to_string()));
}
let client_groups = state
.client_groups
.entry(client_id.to_string())
.or_default();
if !client_groups.iter().any(|g| g == group) {
client_groups.push(group.to_string());
}
let group_clients = state.group_clients.entry(group.to_string()).or_default();
if !group_clients.iter().any(|c| c == client_id) {
group_clients.push(client_id.to_string());
}
Ok(())
}
fn leave_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError> {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
let mut state = self.state.lock();
if !state.client_messages.contains_key(client_id) {
return Err(GatewayError::ClientNotFound(client_id.to_string()));
}
let group_exists = state.group_clients.contains_key(group);
if !group_exists {
return Err(GatewayError::GroupNotFound(group.to_string()));
}
if let Some(groups) = state.client_groups.get_mut(client_id) {
groups.retain(|g| g != group);
}
if let Some(client_ids) = state.group_clients.get_mut(group) {
client_ids.retain(|c| c != client_id);
}
Ok(())
}
fn ungroup(&self, group: &str) -> Result<(), GatewayError> {
let mut state = self.state.lock();
if !state.group_clients.contains_key(group) {
return Err(GatewayError::GroupNotFound(group.to_string()));
}
state.group_clients.remove(group);
for groups in state.client_groups.values_mut() {
groups.retain(|g| g != group);
}
Ok(())
}
fn is_online(&self, client_id: &str) -> Result<bool, GatewayError> {
let state = self.state.lock();
Ok(state.client_messages.contains_key(client_id))
}
fn get_client_count(&self) -> Result<usize, GatewayError> {
let state = self.state.lock();
Ok(state.client_messages.len())
}
fn get_client_count_by_group(&self, group: &str) -> Result<usize, GatewayError> {
let state = self.state.lock();
Ok(state.group_clients.get(group).map(|v| v.len()).unwrap_or(0))
}
fn close_client(&self, client_id: &str) -> Result<(), GatewayError> {
if client_id.is_empty() {
return Err(GatewayError::InvalidClientId(client_id.to_string()));
}
let mut state = self.state.lock();
if state.client_messages.remove(client_id).is_none() {
return Err(GatewayError::ClientNotFound(client_id.to_string()));
}
state.client_groups.remove(client_id);
for client_ids in state.group_clients.values_mut() {
client_ids.retain(|c| c != client_id);
}
Ok(())
}
}
pub struct Gateway {
config: GatewayConfig,
transport: Arc<dyn GatewayTransport>,
}
impl Gateway {
pub fn new(config: GatewayConfig, transport: Arc<dyn GatewayTransport>) -> Self {
Self { config, transport }
}
pub fn send_to_client(&self, client_id: &str, message: &str) -> Result<(), GatewayError> {
self.transport.send_to_client(client_id, message)
}
pub fn send_to_all(&self, message: &str) -> Result<(), GatewayError> {
self.transport.send_to_all(message)
}
pub fn send_to_group(&self, group: &str, message: &str) -> Result<(), GatewayError> {
self.transport.send_to_group(group, message)
}
pub fn join_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError> {
self.transport.join_group(client_id, group)
}
pub fn leave_group(&self, client_id: &str, group: &str) -> Result<(), GatewayError> {
self.transport.leave_group(client_id, group)
}
pub fn ungroup(&self, group: &str) -> Result<(), GatewayError> {
self.transport.ungroup(group)
}
pub fn is_online(&self, client_id: &str) -> Result<bool, GatewayError> {
self.transport.is_online(client_id)
}
pub fn get_client_count(&self) -> Result<usize, GatewayError> {
self.transport.get_client_count()
}
pub fn get_client_count_by_group(&self, group: &str) -> Result<usize, GatewayError> {
self.transport.get_client_count_by_group(group)
}
pub fn get_all_client_ids(&self) -> Result<Vec<String>, GatewayError> {
self.transport.get_all_client_ids()
}
pub fn get_client_id_list_by_group(&self, group: &str) -> Result<Vec<String>, GatewayError> {
self.transport.get_client_id_list_by_group(group)
}
pub fn close_client(&self, client_id: &str) -> Result<(), GatewayError> {
self.transport.close_client(client_id)
}
pub fn config(&self) -> &GatewayConfig {
&self.config
}
}
#[cfg(test)]
mod tests {
use super::*;
const CLIENT_A: &str = "7f00000108fc00000001";
const CLIENT_B: &str = "7f00000108fc00000002";
const CLIENT_C: &str = "7f00000108fc00000003";
#[test]
fn test_gateway_config_builder() {
let config = GatewayConfig::new("127.0.0.1:1238")
.with_heartbeat_interval(30)
.with_default_group("default");
assert_eq!(config.register_address, "127.0.0.1:1238");
assert_eq!(config.heartbeat_interval, 30);
assert_eq!(config.default_group.as_deref(), Some("default"));
}
#[test]
fn test_memory_gateway_transport_send_to_client() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.send_to_client(CLIENT_A, "hello").unwrap();
transport.send_to_client(CLIENT_A, "world").unwrap();
let messages = transport.client_messages(CLIENT_A);
assert_eq!(messages, vec!["hello".to_string(), "world".to_string()]);
}
#[test]
fn test_memory_gateway_transport_send_to_clients() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport
.send_to_clients(&[CLIENT_A.to_string(), CLIENT_B.to_string()], "broadcast")
.unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["broadcast".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_B),
vec!["broadcast".to_string()]
);
}
#[test]
fn test_memory_gateway_transport_send_to_all() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.register_client(CLIENT_C);
transport.send_to_all("announcement").unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["announcement".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_B),
vec!["announcement".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_C),
vec!["announcement".to_string()]
);
}
#[test]
fn test_memory_gateway_transport_send_to_group() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.register_client(CLIENT_C);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
transport.send_to_group("room1", "group-msg").unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["group-msg".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_B),
vec!["group-msg".to_string()]
);
assert!(transport.client_messages(CLIENT_C).is_empty());
transport.send_to_group("nonexistent", "msg").unwrap();
}
#[test]
fn test_memory_gateway_transport_join_leave_group() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_A, "room2").unwrap();
let groups = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert_eq!(groups, vec!["room1".to_string(), "room2".to_string()]);
let clients = transport.get_client_id_list_by_group("room1").unwrap();
assert_eq!(clients, vec![CLIENT_A.to_string()]);
transport.join_group(CLIENT_A, "room1").unwrap();
let groups = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert_eq!(groups.len(), 2);
transport.leave_group(CLIENT_A, "room1").unwrap();
let groups = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert_eq!(groups, vec!["room2".to_string()]);
let clients = transport.get_client_id_list_by_group("room1").unwrap();
assert!(clients.is_empty());
let err = transport.leave_group(CLIENT_A, "nonexistent").unwrap_err();
match err {
GatewayError::GroupNotFound(group) => assert_eq!(group, "nonexistent"),
other => panic!("期望 GroupNotFound, 实际 {other:?}"),
}
}
#[test]
fn test_memory_gateway_transport_ungroup() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
transport.ungroup("room1").unwrap();
let clients = transport.get_client_id_list_by_group("room1").unwrap();
assert!(clients.is_empty());
let groups_a = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert!(!groups_a.iter().any(|g| g == "room1"));
let groups_b = transport.get_groups_by_client_id(CLIENT_B).unwrap();
assert!(!groups_b.iter().any(|g| g == "room1"));
let err = transport.ungroup("nonexistent").unwrap_err();
match err {
GatewayError::GroupNotFound(group) => assert_eq!(group, "nonexistent"),
other => panic!("期望 GroupNotFound, 实际 {other:?}"),
}
}
#[test]
fn test_memory_gateway_transport_is_online() {
let transport = MemoryGatewayTransport::new();
assert!(!transport.is_online(CLIENT_A).unwrap());
transport.register_client(CLIENT_A);
assert!(transport.is_online(CLIENT_A).unwrap());
transport.close_client(CLIENT_A).unwrap();
assert!(!transport.is_online(CLIENT_A).unwrap());
}
#[test]
fn test_memory_gateway_transport_get_client_count() {
let transport = MemoryGatewayTransport::new();
assert_eq!(transport.get_client_count().unwrap(), 0);
transport.register_client(CLIENT_A);
assert_eq!(transport.get_client_count().unwrap(), 1);
transport.register_client(CLIENT_B);
transport.register_client(CLIENT_C);
assert_eq!(transport.get_client_count().unwrap(), 3);
transport.register_client(CLIENT_A);
assert_eq!(transport.get_client_count().unwrap(), 3);
transport.close_client(CLIENT_B).unwrap();
assert_eq!(transport.get_client_count().unwrap(), 2);
}
#[test]
fn test_memory_gateway_transport_get_client_count_by_group() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.register_client(CLIENT_C);
assert_eq!(transport.get_client_count_by_group("room1").unwrap(), 0);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
transport.join_group(CLIENT_C, "room2").unwrap();
assert_eq!(transport.get_client_count_by_group("room1").unwrap(), 2);
assert_eq!(transport.get_client_count_by_group("room2").unwrap(), 1);
transport.leave_group(CLIENT_A, "room1").unwrap();
assert_eq!(transport.get_client_count_by_group("room1").unwrap(), 1);
}
#[test]
fn test_memory_gateway_transport_get_all_client_ids() {
let transport = MemoryGatewayTransport::new();
assert!(transport.get_all_client_ids().unwrap().is_empty());
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
let mut ids = transport.get_all_client_ids().unwrap();
ids.sort();
assert_eq!(ids, vec![CLIENT_A.to_string(), CLIENT_B.to_string()]);
}
#[test]
fn test_memory_gateway_transport_get_client_id_list_by_group() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
assert!(transport
.get_client_id_list_by_group("room1")
.unwrap()
.is_empty());
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
let mut clients = transport.get_client_id_list_by_group("room1").unwrap();
clients.sort();
assert_eq!(clients, vec![CLIENT_A.to_string(), CLIENT_B.to_string()]);
}
#[test]
fn test_memory_gateway_transport_get_groups_by_client_id() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
assert!(transport
.get_groups_by_client_id(CLIENT_A)
.unwrap()
.is_empty());
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_A, "room2").unwrap();
let groups = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert_eq!(groups, vec!["room1".to_string(), "room2".to_string()]);
let err = transport.get_groups_by_client_id(CLIENT_B).unwrap_err();
match err {
GatewayError::ClientNotFound(client_id) => assert_eq!(client_id, CLIENT_B),
other => panic!("期望 ClientNotFound, 实际 {other:?}"),
}
}
#[test]
fn test_memory_gateway_transport_close_client() {
let transport = MemoryGatewayTransport::new();
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
transport.close_client(CLIENT_A).unwrap();
assert!(!transport.is_online(CLIENT_A).unwrap());
assert_eq!(transport.get_client_count().unwrap(), 1);
let clients = transport.get_client_id_list_by_group("room1").unwrap();
assert_eq!(clients, vec![CLIENT_B.to_string()]);
let err = transport.close_client(CLIENT_A).unwrap_err();
match err {
GatewayError::ClientNotFound(client_id) => assert_eq!(client_id, CLIENT_A),
other => panic!("期望 ClientNotFound, 实际 {other:?}"),
}
}
#[test]
fn test_memory_gateway_transport_client_not_found() {
let transport = MemoryGatewayTransport::new();
let err = transport.send_to_client(CLIENT_A, "msg").unwrap_err();
match err {
GatewayError::ClientNotFound(client_id) => assert_eq!(client_id, CLIENT_A),
other => panic!("期望 ClientNotFound, 实际 {other:?}"),
}
let err = transport.join_group(CLIENT_A, "room1").unwrap_err();
match err {
GatewayError::ClientNotFound(client_id) => assert_eq!(client_id, CLIENT_A),
other => panic!("期望 ClientNotFound, 实际 {other:?}"),
}
transport.register_client(CLIENT_A);
let err = transport
.send_to_clients(&[CLIENT_A.to_string(), CLIENT_B.to_string()], "msg")
.unwrap_err();
match err {
GatewayError::ClientNotFound(client_id) => assert_eq!(client_id, CLIENT_B),
other => panic!("期望 ClientNotFound, 实际 {other:?}"),
}
assert!(transport.client_messages(CLIENT_A).is_empty());
}
#[test]
fn test_gateway_send_to_client() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
transport.register_client(CLIENT_A);
gateway.send_to_client(CLIENT_A, "hello").unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["hello".to_string()]
);
}
#[test]
fn test_gateway_send_to_all() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
gateway.send_to_all("broadcast").unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["broadcast".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_B),
vec!["broadcast".to_string()]
);
}
#[test]
fn test_gateway_send_to_group() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
transport.join_group(CLIENT_A, "room1").unwrap();
transport.join_group(CLIENT_B, "room1").unwrap();
gateway.send_to_group("room1", "group-msg").unwrap();
assert_eq!(
transport.client_messages(CLIENT_A),
vec!["group-msg".to_string()]
);
assert_eq!(
transport.client_messages(CLIENT_B),
vec!["group-msg".to_string()]
);
}
#[test]
fn test_gateway_join_group() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
transport.register_client(CLIENT_A);
gateway.join_group(CLIENT_A, "room1").unwrap();
let groups = transport.get_groups_by_client_id(CLIENT_A).unwrap();
assert_eq!(groups, vec!["room1".to_string()]);
let clients = gateway.get_client_id_list_by_group("room1").unwrap();
assert_eq!(clients, vec![CLIENT_A.to_string()]);
}
#[test]
fn test_gateway_is_online() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
assert!(!gateway.is_online(CLIENT_A).unwrap());
transport.register_client(CLIENT_A);
assert!(gateway.is_online(CLIENT_A).unwrap());
}
#[test]
fn test_gateway_get_client_count() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
assert_eq!(gateway.get_client_count().unwrap(), 0);
transport.register_client(CLIENT_A);
transport.register_client(CLIENT_B);
assert_eq!(gateway.get_client_count().unwrap(), 2);
assert_eq!(gateway.config().register_address, "127.0.0.1:1238");
assert_eq!(gateway.config().heartbeat_interval, 55);
}
#[test]
fn test_gateway_close_client() {
let transport = Arc::new(MemoryGatewayTransport::new());
let gateway = Gateway::new(GatewayConfig::new("127.0.0.1:1238"), transport.clone());
transport.register_client(CLIENT_A);
transport.join_group(CLIENT_A, "room1").unwrap();
gateway.close_client(CLIENT_A).unwrap();
assert!(!gateway.is_online(CLIENT_A).unwrap());
assert_eq!(gateway.get_client_count().unwrap(), 0);
assert!(gateway
.get_client_id_list_by_group("room1")
.unwrap()
.is_empty());
}
}