2023-02-15 21:16:43 -05:00
|
|
|
use std::fmt::Display;
|
|
|
|
|
2023-02-11 17:04:16 -05:00
|
|
|
include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
|
|
|
|
|
2023-02-15 21:16:43 -05:00
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
2023-02-11 17:04:16 -05:00
|
|
|
/// A word struct
|
|
|
|
pub struct Word<'a> {
|
|
|
|
/// The word itself
|
|
|
|
pub word: &'a str,
|
|
|
|
|
|
|
|
/// The binary representation of this number
|
|
|
|
///
|
|
|
|
/// The words are responsible for 13 bits of data, so this is fine to fit in a u16
|
|
|
|
pub number: u16,
|
|
|
|
}
|
|
|
|
|
2023-02-15 21:16:43 -05:00
|
|
|
impl Display for Word<'_> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2023-02-17 01:01:45 +00:00
|
|
|
write!(f, "{}", self.word)
|
2023-02-15 21:16:43 -05:00
|
|
|
}
|
2023-02-11 17:04:16 -05:00
|
|
|
}
|
|
|
|
|
2023-02-15 19:16:57 -05:00
|
|
|
/// Helper function that gets the mapped number from a word
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-02-15 19:36:06 -05:00
|
|
|
/// use words::get_number;
|
2023-02-15 19:16:57 -05:00
|
|
|
///
|
2023-02-15 21:16:43 -05:00
|
|
|
/// assert!(get_number("ThE").is_some());
|
|
|
|
/// assert!(get_number("AsDf").is_none());
|
2023-02-15 19:16:57 -05:00
|
|
|
/// ```
|
2023-02-15 21:16:43 -05:00
|
|
|
pub fn get_number<S>(maybe_word: S) -> Option<u16>
|
2023-02-15 19:16:57 -05:00
|
|
|
where
|
|
|
|
S: AsRef<str>,
|
|
|
|
{
|
|
|
|
get_word(maybe_word).map(|w| w.number)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets a word from the word map
|
|
|
|
///
|
|
|
|
/// ```rust
|
2023-02-15 19:36:06 -05:00
|
|
|
/// use words::get_word;
|
2023-02-15 19:16:57 -05:00
|
|
|
///
|
2023-02-15 21:16:43 -05:00
|
|
|
/// assert!(get_word("THE").is_some());
|
|
|
|
/// assert!(get_word("the").is_some());
|
|
|
|
/// assert!(get_word("tHe").is_some());
|
|
|
|
/// assert!(get_word("ASDFASDF").is_none());
|
2023-02-15 19:16:57 -05:00
|
|
|
/// ```
|
2023-02-15 21:16:43 -05:00
|
|
|
pub fn get_word<S>(maybe_word: S) -> Option<&'static Word<'static>>
|
2023-02-15 19:16:57 -05:00
|
|
|
where
|
|
|
|
S: AsRef<str>,
|
|
|
|
{
|
|
|
|
WORD_MAP
|
|
|
|
.get(&maybe_word.as_ref().trim().to_ascii_uppercase())
|
|
|
|
.copied()
|
|
|
|
}
|
2023-02-15 22:57:30 -05:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2023-02-17 01:06:19 +00:00
|
|
|
#[test]
|
|
|
|
fn test_length() {
|
2023-03-11 14:57:00 -05:00
|
|
|
assert!(WORDS.len() >= 4096 + 2);
|
|
|
|
assert!(NUMBER_TO_WORDS.len() >= 4096 + 2);
|
2023-02-17 01:06:19 +00:00
|
|
|
|
2023-03-11 14:57:00 -05:00
|
|
|
for i in 0..4096 + 2_u16 {
|
2023-02-17 01:06:19 +00:00
|
|
|
assert_eq!(NUMBER_TO_WORDS[i as usize][0].number, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-15 22:57:30 -05:00
|
|
|
#[test]
|
|
|
|
fn test_equivalence() {
|
|
|
|
// Test equivalence
|
|
|
|
macro_rules! te {
|
|
|
|
($word1:ident, $word2: ident) => {
|
|
|
|
eprintln!("Checking if {:?} is a word", stringify!($word1));
|
|
|
|
assert!(get_word(stringify!($word1)).is_some());
|
|
|
|
eprintln!("Checking if {:?} is a word", stringify!($word2));
|
|
|
|
assert!(get_word(stringify!($word2)).is_some());
|
|
|
|
eprintln!("Checking equivalence");
|
|
|
|
assert_eq!(
|
|
|
|
get_word(stringify!($word1)).unwrap().number,
|
|
|
|
get_word(stringify!($word1)).unwrap().number
|
|
|
|
);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Homonyms
|
2023-03-11 14:57:00 -05:00
|
|
|
// te!(blue, blew);
|
2023-02-15 22:57:30 -05:00
|
|
|
te!(yellow, hello);
|
2023-03-11 14:57:00 -05:00
|
|
|
// te!(days, daze);
|
|
|
|
// te!(day, days);
|
2023-02-15 22:57:30 -05:00
|
|
|
|
|
|
|
// Plurals
|
2023-03-11 14:57:00 -05:00
|
|
|
// te!(sent, sense);
|
|
|
|
// te!(sent, scents);
|
|
|
|
// te!(sent, cents);
|
2023-02-15 22:57:30 -05:00
|
|
|
}
|
|
|
|
}
|