#![deny(dead_code)]
#![deny(missing_docs)]
#![deny(unreachable_patterns)]
#![deny(unused_extern_crates)]
#![deny(unused_imports)]
#![deny(unused_qualifications)]
#[cfg(test)] #[macro_use] extern crate expectest;
pub mod constants;
pub mod error;
pub mod extensions;
pub mod phoneme;
pub use constants::*;
pub use error::*;
pub use extensions::*;
pub use phoneme::*;
use std::collections::HashMap;
use std::collections::hash_map::Keys;
pub type Word = String;
pub type Polyphone = Vec<Phoneme>;
#[derive(Default, Clone)]
pub struct Arpabet {
dictionary: HashMap<Word, Polyphone>,
}
impl Arpabet {
pub fn new() -> Arpabet {
Self {
dictionary: HashMap::new(),
}
}
pub fn from_map(map: HashMap<Word, Polyphone>) -> Self {
Self {
dictionary: map
}
}
pub fn from_phf_map(map: &phf::Map<&str, &[Phoneme]>) -> Self {
let mut hashmap = HashMap::with_capacity(map.len());
for (k, v) in map.into_iter() {
hashmap.insert(k.to_string(), v.to_vec());
}
Self {
dictionary: hashmap,
}
}
pub fn get_polyphone(&self, word: &str) -> Option<Polyphone> {
self.dictionary.get(word).and_then(|p| {
Some(p.iter()
.map(|p| p.clone())
.collect::<Vec<Phoneme>>())
})
}
pub fn get_polyphone_ref(&self, word: &str) -> Option<&Polyphone> {
self.dictionary.get(word)
}
pub fn get_polyphone_str(&self, word: &str) -> Option<Vec<&'static str>> {
self.dictionary.get(word)
.map(|polyphone| {
polyphone.iter()
.map(|phoneme| phoneme.to_str())
.collect()
})
}
pub fn combine(&self, other: &Arpabet) -> Arpabet {
let mut merged = self.dictionary.clone();
for (k, v) in other.dictionary.iter() {
merged.insert(k.clone(), v.clone());
}
Arpabet { dictionary: merged }
}
pub fn merge_from(&mut self, other: &Arpabet) {
for (k, v) in other.dictionary.iter() {
self.dictionary.insert(k.clone(), v.clone());
}
}
pub fn insert(&mut self, key: Word, value: Vec<Phoneme>) -> Option<Vec<Phoneme>> {
self.dictionary.insert(key, value)
}
pub fn remove(&mut self, key: &str) -> Option<Vec<Phoneme>> {
self.dictionary.remove(key)
}
pub fn keys(&self) -> Keys<String, Vec<Phoneme>> {
self.dictionary.keys()
}
pub fn len(&self) -> usize {
self.dictionary.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
use phoneme::{
Consonant,
Vowel,
VowelStress,
};
#[test]
fn insert() {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(arpa.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(arpa.get_polyphone("bar"), None);
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(arpa.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
}
#[test]
fn remove() {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
arpa.insert("boo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(arpa.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(arpa.get_polyphone("boo"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(arpa.len(), 2);
arpa.remove("boo");
assert_eq!(arpa.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(arpa.get_polyphone("boo"), None);
assert_eq!(arpa.len(), 1);
arpa.remove("foo");
assert_eq!(arpa.get_polyphone("foo"), None);
assert_eq!(arpa.get_polyphone("boo"), None);
assert_eq!(arpa.len(), 0);
}
#[test]
fn size() {
let mut arpa = Arpabet::new();
assert_eq!(arpa.len(), 0);
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(arpa.len(), 1);
arpa.insert("boo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(arpa.len(), 2);
arpa.remove("boo");
assert_eq!(arpa.len(), 1);
arpa.remove("foo");
assert_eq!(arpa.len(), 0);
}
#[test]
fn keys() {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
arpa.insert("boo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
let keys: Vec<String> = arpa.keys().cloned().collect();
assert_eq!(keys.len(), 2);
assert!(keys.iter().any(|x| x == "foo"));
assert!(keys.iter().any(|x| x == "boo"));
}
#[test]
fn get_polyphone() {
let mut a = Arpabet::new();
a.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(a.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(a.get_polyphone("bar"), None);
}
#[test]
fn get_polyphone_str() {
let mut a = Arpabet::new();
a.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(a.get_polyphone_str("foo"), Some(vec!["F", "UW1"]));
assert_eq!(a.get_polyphone_str("bar"), None);
}
#[test]
fn get_polyphone_ref() {
let mut a = Arpabet::new();
a.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
assert_eq!(a.get_polyphone_ref("foo"), Some(&vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress))],
));
assert_eq!(a.get_polyphone_ref("bar"), None);
}
#[test]
fn combine() {
let a = {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
arpa.insert("bar".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AA(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::R),
]);
arpa
};
let b = {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
arpa.insert("baz".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AE(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::Z),
]);
arpa
};
let c = a.combine(&b);
assert_eq!(c.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]));
assert_eq!(c.get_polyphone("bar"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AA(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::R),
]));
assert_eq!(c.get_polyphone("baz"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AE(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::Z),
]));
assert_eq!(c.get_polyphone("bin"), None);
}
#[test]
fn merge_from() {
let mut a = Arpabet::new();
a.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::F),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
a.insert("bar".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AA(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::R),
]);
let b = {
let mut arpa = Arpabet::new();
arpa.insert("foo".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]);
arpa.insert("baz".to_string(), vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AE(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::Z),
]);
arpa
};
a.merge_from(&b);
assert_eq!(a.get_polyphone("foo"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::UW(VowelStress::PrimaryStress)),
]));
assert_eq!(a.get_polyphone("bar"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AA(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::R),
]));
assert_eq!(a.get_polyphone("baz"), Some(vec![
Phoneme::Consonant(Consonant::B),
Phoneme::Vowel(Vowel::AE(VowelStress::PrimaryStress)),
Phoneme::Consonant(Consonant::Z),
]));
assert_eq!(a.get_polyphone("bin"), None);
}
}