use crate::char_struct::CharType;
use crate::jauem::choseong::encode_choseong;
use crate::jauem::jongseong::encode_jongseong;
use crate::moeum::jungsong::encode_jungsong;
use crate::rules::RuleMeta;
use crate::rules::context::RuleContext;
use crate::rules::traits::{BrailleRule, Phase, RuleResult};
use crate::split::split_korean_jauem;
pub static META: RuleMeta = RuleMeta {
section: "16",
subsection: None,
name: "korean_exception_decomposition",
standard_ref: "2024 Korean Braille Standard, Ch.2 Sec.6 Art.14[붙임]/16[붙임]/17",
description: "Exception syllables (팠,껐,셩,쎵,졍,쪙,쳥,겄) fully decomposed",
};
pub const EXCEPTION_CHARS: [char; 8] = ['팠', '껐', '셩', '쎵', '졍', '쪙', '쳥', '겄'];
pub fn is_exception(ch: char) -> bool {
EXCEPTION_CHARS.contains(&ch)
}
pub struct Rule16;
impl BrailleRule for Rule16 {
fn meta(&self) -> &'static RuleMeta {
&META
}
fn phase(&self) -> Phase {
Phase::CoreEncoding
}
fn priority(&self) -> u16 {
70 }
fn matches(&self, ctx: &RuleContext) -> bool {
matches!(ctx.char_type, CharType::Korean(_)) && is_exception(ctx.current_char())
}
fn apply(&self, ctx: &mut RuleContext) -> Result<RuleResult, String> {
let CharType::Korean(korean) = ctx.char_type else {
return Ok(RuleResult::Skip);
};
let (cho0, cho1) = split_korean_jauem(korean.cho)?;
if cho1.is_some() {
ctx.emit(32); }
ctx.emit(encode_choseong(cho0)?);
ctx.emit_slice(encode_jungsong(korean.jung)?);
if let Some(jong) = korean.jong {
ctx.emit_slice(encode_jongseong(jong)?);
}
Ok(RuleResult::Consumed)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn identifies_all_exception_chars() {
for &ch in &EXCEPTION_CHARS {
assert!(is_exception(ch), "Expected {} to be exception", ch);
}
}
#[test]
fn rejects_non_exception_chars() {
assert!(!is_exception('가'));
assert!(!is_exception('나'));
assert!(!is_exception('성')); assert!(!is_exception('정')); }
#[test]
fn golden_test_alignment() {
let cases = vec![
("껐", "⠠⠈⠎⠌"), ("겄", "⠈⠎⠌"), ("껐어요", "⠠⠈⠎⠌⠎⠬"), ];
for (input, expected) in cases {
let result = crate::encode_to_unicode(input).unwrap();
assert_eq!(
result, expected,
"Rule 16 golden test failed for: {}",
input
);
}
}
#[test]
fn meta_is_correct() {
assert_eq!(META.section, "16");
assert_eq!(META.name, "korean_exception_decomposition");
}
}