pub mod english;
pub use self::english::*;
use once_cell::unsync::Lazy;
use std::collections::HashMap;
use thiserror::Error;
#[derive(Debug, Error, PartialEq)]
pub enum WordlistError {
#[error("the index `{0}` is invalid")]
InvalidIndex(usize),
#[error("the word `{0}` is invalid")]
InvalidWord(String),
}
#[derive(Debug)]
pub struct WordlistData {
words: HashMap<usize, &'static str>,
indexes: HashMap<&'static str, usize>,
}
pub trait Wordlist {
fn wordlist() -> Lazy<WordlistData>;
fn get_word(index: usize) -> Result<&'static str, WordlistError> {
Self::wordlist()
.words
.get(&index)
.ok_or(WordlistError::InvalidIndex(index))
.map(|word| *word)
}
fn get_index(word: &str) -> Result<usize, WordlistError> {
Self::wordlist()
.indexes
.get(word)
.ok_or_else(|| WordlistError::InvalidWord(word.into()))
.map(|usize| *usize)
}
fn contains_word(word: &str) -> bool {
Self::get_index(word).is_ok()
}
fn get_all() -> Vec<&'static str> {
let mut words: Vec<&'static str> = Self::wordlist().words.values().cloned().collect();
words.sort_unstable();
words
}
fn starting_with(start: &str) -> Vec<&'static str> {
let mut words = Self::wordlist()
.words
.values()
.into_iter()
.filter(|word| word.starts_with(start))
.cloned()
.collect::<Vec<&'static str>>();
words.sort_unstable();
words
}
fn next_starting_with(start: &str, current_word: &str) -> Option<&'static str> {
let words = Self::starting_with(start);
let position = words.iter().position(|word| word == ¤t_word)?;
let position = if position == (words.len() - 1) {
0
} else {
position
};
Some(*words.get(position + 1)?)
}
}