use dashmap::DashMap; use dashmap::mapref::entry::Entry; use once_cell::sync::Lazy; use rand::prelude::{IndexedRandom, RngExt}; use std::sync::Arc; use crate::anonymous_clients::anonymous_client_connection::AnonymousClientConnection; static ANONYMOUS_USERS: Lazy>> = Lazy::new(|| DashMap::new()); static ANONYMOUS_USERNAMES: Lazy> = Lazy::new(|| DashMap::new()); pub fn add_anonymous_user(connection: Arc) { ANONYMOUS_USERS.insert(connection.get_user_id(), connection); } #[allow(dead_code)] pub async fn remove_anonymous_user(user_id: u64) { if let Some((_, connection)) = ANONYMOUS_USERS.remove(&user_id) { let username = connection.get_user_name().await; ANONYMOUS_USERNAMES.remove_if(&username, |_, reserved_user_id| { *reserved_user_id == user_id }); } } pub async fn get_anonymous_user(user_id: u64) -> Option> { ANONYMOUS_USERS.get(&user_id).map(|c| c.clone()) } pub async fn get_anonymous_user_by_name( username: String, ) -> Option> { let user_id = ANONYMOUS_USERNAMES .get(&username.to_lowercase())? .value() .to_owned(); get_anonymous_user(user_id).await } pub fn generate_username(user_id: u64) -> String { let adjectives = ["Swift", "Clever", "Brave", "Sneaky", "Fierce"]; let nouns = ["Tiger", "Eagle", "Shark", "Wolf", "Dragon"]; let mut rng = rand::rng(); loop { let Some(adj) = adjectives.choose(&mut rng) else { continue; }; let Some(noun) = nouns.choose(&mut rng) else { continue; }; let username = format!("{}{}{}", adj, noun, rng.random_range(0..10000)); let canonical_username = username.to_lowercase(); if reserve_username(canonical_username, user_id) { return username; } } } fn reserve_username(username: String, user_id: u64) -> bool { if let Entry::Vacant(entry) = ANONYMOUS_USERNAMES.entry(username) { entry.insert(user_id); true } else { false } } #[cfg(test)] mod tests { use super::*; #[test] fn username_reservation_is_unique() { let username = "anonymous-manager-reservation-test".to_string(); assert!(reserve_username(username.clone(), 1)); assert!(!reserve_username(username.clone(), 2)); ANONYMOUS_USERNAMES.remove(&username); } }