use regex::Regex;
use std::fmt;
const REGEXP: &str = "^[-.0-9@_a-z]{4,30}$";
const REGEXP_WITH_PREFIX: &str = "^alias:[A-Z]{1}:[-.0-9@_a-z]{4,30}$";
#[derive(Debug, PartialEq, Eq)]
pub enum AliasError {
InvalidAlias,
RegexError,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Alias(String);
impl Alias {
pub fn new(alias: &str) -> Result<Alias, AliasError> {
if Self::is_valid(REGEXP, alias)? {
Ok(Alias(format!("{}", alias)))
} else if Self::is_valid(REGEXP_WITH_PREFIX, alias)? {
let value = Self::replace_prefix(alias)?;
Ok(Alias(value))
} else {
Err(AliasError::InvalidAlias)
}
}
pub fn to_string_with_prefix(&self, chain_id: u8) -> String {
format!("alias:{}:{}", chain_id as char, self.0)
}
fn is_valid(regexp: &str, alias: &str) -> Result<bool, AliasError> {
match Regex::new(regexp) {
Ok(r) => Ok(r.is_match(alias)),
Err(_) => Err(AliasError::RegexError),
}
}
fn replace_prefix(alias: &str) -> Result<String, AliasError> {
match Regex::new("^alias:[A-Z]{1}:") {
Ok(r) => Ok(r.replace(alias, "").to_string()),
Err(_) => Err(AliasError::RegexError),
}
}
}
impl fmt::Display for Alias {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::account::TESTNET;
#[test]
fn test_alias() {
let result = Alias::new("test");
assert!(result.is_ok());
let alias = result.unwrap();
assert_eq!(alias.to_string(), "test");
assert_eq!(alias.to_string_with_prefix(TESTNET), "alias:T:test");
let result = Alias::new("a");
assert_eq!(result, Err(AliasError::InvalidAlias));
let result = Alias::new("3MzGEv9wnaqrYFYujAXSH5RQfHaVKNQvx3D");
assert_eq!(result, Err(AliasError::InvalidAlias));
}
#[test]
fn test_alias_with_prefix() {
let result = Alias::new("alias:T:test");
assert!(result.is_ok());
let alias = result.unwrap();
assert_eq!(alias.to_string(), "test");
assert_eq!(alias.to_string_with_prefix(TESTNET), "alias:T:test");
}
}