use phf::phf_set;
pub static VALID_SYLLABLES: phf::Set<&'static str> = phf_set! {
"a", "ai", "an", "ang", "ao",
"e", "ei", "en", "eng", "er",
"o", "ou",
"yi", "ya", "ye", "yao", "you", "yan", "yin", "yang", "ying", "yong",
"yu", "yue", "yuan", "yun",
"wu", "wa", "wo", "wai", "wei", "wan", "wen", "wang", "weng",
"ba", "bo", "bai", "bei", "bao", "ban", "ben", "bang", "beng",
"bi", "bie", "biao", "bian", "bin", "bing",
"bu",
"pa", "po", "pai", "pei", "pao", "pou", "pan", "pen", "pang", "peng",
"pi", "pie", "piao", "pian", "pin", "ping",
"pu",
"ma", "mo", "me", "mai", "mei", "mao", "mou", "man", "men", "mang", "meng",
"mi", "mie", "miao", "miu", "mian", "min", "ming",
"mu",
"fa", "fo", "fei", "fou", "fan", "fen", "fang", "feng",
"fu",
"da", "de", "dai", "dei", "dao", "dou", "dan", "den", "dang", "deng", "dong",
"di", "die", "diao", "diu", "dian", "ding",
"du", "duo", "dui", "duan", "dun",
"ta", "te", "tai", "tao", "tou", "tan", "tang", "teng", "tong",
"ti", "tie", "tiao", "tian", "ting",
"tu", "tuo", "tui", "tuan", "tun",
"na", "ne", "nai", "nei", "nao", "nou", "nan", "nen", "nang", "neng", "nong",
"ni", "nie", "niao", "niu", "nian", "nin", "niang", "ning",
"nu", "nuo", "nuan",
"nv", "nve",
"la", "le", "lai", "lei", "lao", "lou", "lan", "lang", "leng", "long",
"li", "lia", "lie", "liao", "liu", "lian", "lin", "liang", "ling",
"lu", "luo", "luan", "lun",
"lv", "lve",
"ga", "ge", "gai", "gei", "gao", "gou", "gan", "gen", "gang", "geng", "gong",
"gu", "gua", "guo", "guai", "gui", "guan", "gun", "guang",
"ka", "ke", "kai", "kao", "kou", "kan", "ken", "kang", "keng", "kong",
"ku", "kua", "kuo", "kuai", "kui", "kuan", "kun", "kuang",
"ha", "he", "hai", "hei", "hao", "hou", "han", "hen", "hang", "heng", "hong",
"hu", "hua", "huo", "huai", "hui", "huan", "hun", "huang",
"ji", "jia", "jie", "jiao", "jiu", "jian", "jin", "jiang", "jing", "jiong",
"ju", "jue", "juan", "jun",
"qi", "qia", "qie", "qiao", "qiu", "qian", "qin", "qiang", "qing", "qiong",
"qu", "que", "quan", "qun",
"xi", "xia", "xie", "xiao", "xiu", "xian", "xin", "xiang", "xing", "xiong",
"xu", "xue", "xuan", "xun",
"zha", "zhe", "zhi", "zhai", "zhao", "zhou", "zhan", "zhen", "zhang", "zheng", "zhong",
"zhu", "zhua", "zhuo", "zhuai", "zhui", "zhuan", "zhun", "zhuang",
"cha", "che", "chi", "chai", "chao", "chou", "chan", "chen", "chang", "cheng", "chong",
"chu", "chuo", "chuai", "chui", "chuan", "chun", "chuang",
"sha", "she", "shi", "shai", "shei", "shao", "shou", "shan", "shen", "shang", "sheng",
"shu", "shua", "shuo", "shuai", "shui", "shuan", "shun", "shuang",
"re", "ri", "rao", "rou", "ran", "ren", "rang", "reng", "rong",
"ru", "ruo", "rui", "ruan", "run",
"za", "ze", "zi", "zai", "zei", "zao", "zou", "zan", "zen", "zang", "zeng", "zong",
"zu", "zuo", "zui", "zuan", "zun",
"ca", "ce", "ci", "cai", "cao", "cou", "can", "cen", "cang", "ceng", "cong",
"cu", "cuo", "cui", "cuan", "cun",
"sa", "se", "si", "sai", "sao", "sou", "san", "sen", "sang", "seng", "song",
"su", "suo", "sui", "suan", "sun",
};
pub fn is_valid(s: &str) -> bool {
if s.is_ascii() && s.bytes().all(|b| b.is_ascii_lowercase()) {
VALID_SYLLABLES.contains(s)
} else {
VALID_SYLLABLES.contains(s.to_ascii_lowercase().as_str())
}
}
pub fn count() -> usize {
VALID_SYLLABLES.len()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn count_is_403() {
assert_eq!(count(), 403, "expected 403 canonical Mandarin syllables");
}
#[test]
fn common_syllables_recognized() {
for s in [
"wo",
"ni",
"ta",
"shi",
"zhong",
"guo",
"zhongguo".strip_suffix("guo").unwrap(),
"hao",
"xie",
"jin",
"ming",
"tian",
] {
assert!(is_valid(s), "{s:?} should be valid");
}
}
#[test]
fn nonsense_rejected() {
for s in ["xx", "qz", "rqx", "hmm", "vroom"] {
assert!(!is_valid(s), "{s:?} should be rejected");
}
}
#[test]
fn case_insensitive() {
assert!(is_valid("WO"));
assert!(is_valid("Zhong"));
}
#[test]
fn v_form_for_nlu() {
assert!(is_valid("nv"));
assert!(is_valid("lv"));
assert!(is_valid("nve"));
assert!(is_valid("lve"));
}
#[test]
fn jqx_use_u_not_v() {
assert!(is_valid("ju"));
assert!(is_valid("qu"));
assert!(is_valid("xu"));
assert!(is_valid("yu"));
}
}