const INITIAL: [char; 19] = [
'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ',
'ㅌ', 'ㅍ', 'ㅎ',
];
const MEDIAL: [char; 21] = [
'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ',
'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ',
];
const FINAL: [char; 28] = [
' ', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ',
'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ',
];
pub fn is_hangeul(word: char) -> bool {
('가'..='힣').contains(&word)
}
fn is_consonant(word: char) -> bool {
('ㄱ'..='ㅎ').contains(&word)
}
fn is_medial(word: char) -> bool {
('ㅏ'..='ㅣ').contains(&word)
}
fn is_hangul_syllable(word: [char; 3]) -> bool {
if is_consonant(word[0]) && is_medial(word[1]) {
let res = FINAL.iter().position(|&s| s == word[2]);
res.is_some()
} else {
false
}
}
pub fn join_phonemes(word: [char; 3]) -> char {
if !is_hangul_syllable(word) {
return word[0];
}
let idx_begin = INITIAL.iter().position(|&x| x == word[0]).unwrap();
let idx_middle = MEDIAL.iter().position(|&x| x == word[1]).unwrap();
let idx_end = FINAL.iter().position(|&x| x == word[2]).unwrap();
let initial = '가' as u32;
let offset = ((idx_begin * MEDIAL.len() + idx_middle) * FINAL.len() + idx_end) as u32;
char::from_u32(initial + offset).unwrap()
}
pub fn modify_finall_jamo(letter: char, jamo: char) -> char {
if !is_hangeul(letter) {
return letter;
}
if FINAL.contains(&jamo) {
let mut splited_letter = split_phonemes(letter);
splited_letter[2] = jamo;
join_phonemes(splited_letter)
} else {
letter
}
}
pub fn split_phonemes(word: char) -> [char; 3] {
let mut phonemes: [char; 3] = [' '; 3];
if !is_hangeul(word) {
phonemes[0] = word;
return phonemes;
}
let unicode = word as u32;
let initial = '가' as u32;
let offset = unicode - initial;
let idx_begin: usize = (offset / (21 * 28)) as usize;
phonemes[0] = INITIAL[idx_begin];
let idx_middle: usize = ((offset / 28) % 21) as usize;
phonemes[1] = MEDIAL[idx_middle];
if (((unicode - 0xAC00) % (21 * 28)) % 28) != 0 {
let idx_end: usize = (offset % 28) as usize;
phonemes[2] = FINAL[idx_end];
}
phonemes
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn _is_hangeul() {
let temp = '똠';
assert_eq!(true, is_hangeul(temp));
let temp = 'a';
assert_eq!(false, is_hangeul(temp));
let temp = '😀';
assert_eq!(false, is_hangeul(temp));
}
#[test]
fn _is_hangul_syllable() {
let temp = ['ㄱ', 'ㅏ', 'ㄴ'];
assert_eq!(true, is_hangul_syllable(temp));
let temp = ['ㄱ', 'ㄴ', 'ㄷ'];
assert_eq!(false, is_hangul_syllable(temp));
let temp = ['ㅊ', 'ㄴ', 'ㅓ'];
assert_eq!(false, is_hangul_syllable(temp));
let temp = ['😀', 'ㄴ', 'ㄷ'];
assert_eq!(false, is_hangul_syllable(temp));
}
}