use crate::char_shortcut;
use crate::char_struct::CharType;
use crate::rules::RuleMeta;
use crate::rules::context::RuleContext;
use crate::rules::traits::{BrailleRule, Phase, RuleResult};
pub static META_13: RuleMeta = RuleMeta {
section: "13",
subsection: None,
name: "syllable_abbreviation",
standard_ref: "2024 Korean Braille Standard, Ch.2 Sec.6 Art.13",
description: "Common syllable abbreviations (가,나,다,...,하)",
};
#[cfg(test)]
fn apply(ch: char) -> Result<&'static [u8], String> {
char_shortcut::encode_char_shortcut(ch)
}
pub fn has_abbreviation(ch: char) -> bool {
char_shortcut::SHORTCUT_MAP.contains_key(&ch)
}
pub struct Rule13;
impl BrailleRule for Rule13 {
fn meta(&self) -> &'static RuleMeta {
&META_13
}
fn phase(&self) -> Phase {
Phase::CoreEncoding
}
fn priority(&self) -> u16 {
90 }
fn matches(&self, ctx: &RuleContext) -> bool {
if let CharType::Korean(_) = ctx.char_type {
has_abbreviation(ctx.current_char())
} else {
false
}
}
fn apply(&self, ctx: &mut RuleContext) -> Result<RuleResult, String> {
let encoded = char_shortcut::encode_char_shortcut(ctx.current_char())?;
ctx.emit_slice(encoded);
Ok(RuleResult::Consumed)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::unicode::decode_unicode;
#[test]
fn encodes_basic_syllable_abbreviations() {
assert_eq!(apply('가').unwrap(), &[decode_unicode('⠫')]);
assert_eq!(apply('나').unwrap(), &[decode_unicode('⠉')]);
assert_eq!(apply('다').unwrap(), &[decode_unicode('⠊')]);
assert_eq!(apply('사').unwrap(), &[decode_unicode('⠇')]);
assert_eq!(apply('하').unwrap(), &[decode_unicode('⠚')]);
}
#[test]
fn encodes_extended_abbreviations() {
assert_eq!(
apply('것').unwrap(),
&[decode_unicode('⠸'), decode_unicode('⠎')]
);
assert_eq!(apply('영').unwrap(), &[decode_unicode('⠻')]);
assert_eq!(apply('은').unwrap(), &[decode_unicode('⠵')]);
assert_eq!(apply('인').unwrap(), &[decode_unicode('⠟')]);
}
#[test]
fn has_abbreviation_returns_true_for_known() {
assert!(has_abbreviation('가'));
assert!(has_abbreviation('것'));
assert!(has_abbreviation('영'));
}
#[test]
fn has_abbreviation_returns_false_for_unknown() {
assert!(!has_abbreviation('곤'));
assert!(!has_abbreviation('A'));
assert!(!has_abbreviation('1'));
}
#[test]
fn non_abbreviated_char_returns_error() {
assert!(apply('곤').is_err());
}
#[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 13 golden test failed for: {}",
input
);
}
}
}