#[cfg(test)]
mod tests;
mod error;
pub use error::AlphabetError;
const DEFAULT: &str = "0123456789abcdefghijklmnopqrstuvwxyz";
const UPPERCASE: &str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const DECIMAL: &str = "0123456789";
const LATIN: &str = "abcdefghijklmnopqrstuvwxyz";
const LATIN_UPPERCASE: &str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
#[derive(Debug, Clone, Default)]
#[non_exhaustive]
pub enum Alphabet {
#[default]
Default,
UpperCase,
Decimal,
Latin,
LatinUpperCase,
Custom(String),
}
impl Alphabet {
pub fn new<T: Into<Alphabet>>(abc: T) -> Self {
abc.into().check().unwrap()
}
pub fn new_unchecked<T: Into<Alphabet>>(abc: T) -> Self {
abc.into()
}
fn valid(&self) -> (bool, Vec<char>) {
let v1: Vec<char> = self.get().chars().collect();
let mut v2 = v1.clone();
v2.sort();
v2.dedup();
(v1.len() == v2.len(), v2)
}
pub fn is_valid(&self) -> bool {
self.valid().0
}
pub fn to_valid(self) -> Self {
let valid = &self.valid();
if !valid.0 { return Self::Custom(valid.1.iter().collect()) }
self
}
pub fn check(self) -> Result<Self, AlphabetError> {
if !self.valid().0 { return Err( AlphabetError::RepeatedCharacters ) }
Ok( self )
}
pub fn get(&self) -> String {
match self {
Self::Default => DEFAULT.into(),
Self::UpperCase => UPPERCASE.into(),
Self::Decimal => DECIMAL.into(),
Self::Latin => LATIN.into(),
Self::LatinUpperCase => LATIN_UPPERCASE.into(),
Self::Custom(abc) => abc.into(),
}
}
pub fn simplify(self) -> Self {
match self.get().as_str() {
DEFAULT => Self::Default,
UPPERCASE => Self::UpperCase,
DECIMAL => Self::Decimal,
LATIN => Self::Latin,
LATIN_UPPERCASE => Self::LatinUpperCase,
abc => Self::new_unchecked(abc),
}
}
#[doc(hidden)]
pub fn nth_char(&self, i: usize) -> Result<char, AlphabetError> {
self.get().chars()
.nth(i)
.ok_or(AlphabetError::TooSmallAlphabet(i))
}
#[doc(hidden)]
pub fn chars_index(&self, c: char) -> Result<usize, AlphabetError> {
self.get().chars()
.position(|ch| ch == c)
.ok_or(AlphabetError::CharacterNotIncluded(c))
}
}
impl PartialEq for Alphabet {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Default, Self::Default) => true,
(Self::UpperCase, Self::UpperCase) => true,
(Self::Decimal, Self::Decimal) => true,
(Self::Latin, Self::Latin) => true,
(Self::LatinUpperCase, Self::LatinUpperCase) => true,
(Self::Custom(abc1), Self::Custom(abc2)) => abc1 == abc2,
_ => false
}
}
}
use std::convert::From;
impl From<String> for Alphabet {
fn from(abc: String) -> Self {
Self::Custom(abc)
}
}
impl From<&str> for Alphabet {
fn from(abc: &str) -> Self {
Self::Custom(abc.to_owned())
}
}