You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
3.4 KiB

use std::cell::RefCell;
use crate::config::Player;
// this global stuff is so that we can load up the config and check stuff without
// being part of the Game struct
thread_local! {
/// Minimum length for name
static NAME_MIN: RefCell<usize> = RefCell::new(0);
/// Maximum length for name
static NAME_MAX: RefCell<usize> = RefCell::new(0);
/// Characters allowed to be in name
static NAME_CHARS: RefCell<&'static str> = RefCell::new("");
/// Password minimum length
static PASS_MIN: RefCell<usize> = RefCell::new(0);
/// Password maximum length
static PASS_MAX: RefCell<usize> = RefCell::new(0);
/// Password allowed characters
static PASS_CHARS: RefCell<&'static str> = RefCell::new("");
}
/// Return value for check functions
#[derive(Debug)]
pub enum PlayerCheck {
/// The value checks out
Ok(String),
/// There is one or more issues
Err(Vec<String>),
}
/// Initialize the check module from the Player part of the Config.
///
/// # Arguments
///
/// * config: the Player struct of Config
///
/// # Example
/// ```
/// use rude::config::Config;
/// use rude::check;
///
/// let config = Config::load("config.toml").unwrap();
/// check::init(&config.player);
/// ```
pub fn init(config: &Player) {
NAME_MIN.with(|n| *n.borrow_mut() = config.name_min);
NAME_MAX.with(|n| *n.borrow_mut() = config.name_max);
NAME_CHARS.with(|n| *n.borrow_mut() = Box::leak(config.name_chars.clone().into_boxed_str()));
PASS_MIN.with(|p| *p.borrow_mut() = config.pass_min);
PASS_MAX.with(|p| *p.borrow_mut() = config.pass_max);
PASS_CHARS.with(|p| *p.borrow_mut() = Box::leak(config.pass_chars.clone().into_boxed_str()));
}
/// Check the player name to ensure it meets guidelines
pub fn player_name<S: Into<String>>(name: S) -> PlayerCheck {
let name = name.into();
let name = name.trim();
let mut err_vec = Vec::<String>::new();
if name.len() < NAME_MIN.with(|n| *n.borrow()) {
err_vec.push(
[
&NAME_MIN.with(|n| *n.borrow()).to_string(),
" character minimum",
]
.concat(),
);
} else if name.len() > NAME_MAX.with(|n| *n.borrow()) {
err_vec.push(
[
&NAME_MAX.with(|n| *n.borrow()).to_string(),
" character maximum"
]
.concat()
);
}
for c in name.chars() {
if !NAME_CHARS.with(|n| *n.borrow()).contains(&c.to_string()) {
err_vec.push(
[
"Allowed characters are: ",
&NAME_CHARS.with(|n| *n.borrow())
]
.concat()
);
break;
}
}
if err_vec.is_empty() {
PlayerCheck::Ok(name.into())
} else {
PlayerCheck::Err(err_vec)
}
}
/// Check the password to ensure it meets password requirements
pub fn player_password<S: Into<String>>(password: S) -> PlayerCheck {
let password = password.into();
let mut err_vec = Vec::<String>::new();
if password.len() < PASS_MIN.with(|p| *p.borrow()) {
err_vec.push(
[
&PASS_MIN.with(|p| *p.borrow()).to_string(),
" character minimum"
]
.concat()
);
} else if password.len() > PASS_MAX.with(|p| *p.borrow()) {
err_vec.push(
[
&PASS_MAX.with(|p| *p.borrow()).to_string(),
" character maximum"
]
.concat()
);
}
for c in password.chars() {
if !PASS_CHARS.with(|p| *p.borrow()).contains(&c.to_string()) {
err_vec.push(
[
"Allowed characters are: ",
&PASS_CHARS.with(|p| *p.borrow()).to_string()
]
.concat()
);
break;
}
}
if err_vec.is_empty() {
PlayerCheck::Ok(password.into())
} else {
PlayerCheck::Err(err_vec)
}
}