use crate::rules::context::EncoderState;
use crate::rules::korean::rule_29::{ENGLISH_CONTINUATION, ROMAN_INDICATOR};
fn debug_assert_consistent(state: &EncoderState) {
debug_assert!(
!(state.is_english && state.needs_english_continuation),
"구간이 열린 채로 연속표를 예약할 수 없다"
);
debug_assert!(
!(state.is_english && state.roman_number_chain),
"구간이 열린 채로 숫자 다리가 설 수 없다"
);
}
pub(crate) fn exit_english(state: &mut EncoderState, needs_continuation: bool) {
state.is_english = false;
state.needs_english_continuation = needs_continuation;
state.roman_number_chain = false;
if !needs_continuation {
state.roman_section_is_english_context = false;
}
debug_assert_consistent(state);
}
pub(crate) fn enter_english(state: &mut EncoderState, result: &mut Vec<u8>) {
if state.needs_english_continuation {
result.push(ENGLISH_CONTINUATION);
} else {
result.push(ROMAN_INDICATOR);
}
state.is_english = true;
state.needs_english_continuation = false;
state.roman_number_chain = false;
debug_assert_consistent(state);
}
pub(crate) fn exit_english_for_roman_number_chain(state: &mut EncoderState) {
state.is_english = false;
state.needs_english_continuation = false;
state.roman_number_chain = true;
debug_assert_consistent(state);
}
pub(crate) fn resume_english_from_roman_number_chain(state: &mut EncoderState) {
state.is_english = true;
state.needs_english_continuation = false;
state.roman_number_chain = false;
debug_assert_consistent(state);
}
pub(crate) fn mark_section_open(state: &mut EncoderState) {
state.is_english = true;
state.needs_english_continuation = false;
state.roman_number_chain = false;
debug_assert_consistent(state);
}
pub(crate) fn set_section_open_keeping_number_chain(state: &mut EncoderState, open: bool) {
state.is_english = open;
state.needs_english_continuation = false;
if open {
state.roman_number_chain = false;
}
debug_assert_consistent(state);
}
pub(crate) fn clear_pending_continuation(state: &mut EncoderState) {
state.needs_english_continuation = false;
debug_assert_consistent(state);
}
pub(crate) fn clear_number_chain(state: &mut EncoderState) {
state.roman_number_chain = false;
debug_assert_consistent(state);
}
pub(crate) fn close_section_keeping_number_chain(state: &mut EncoderState) {
state.is_english = false;
state.needs_english_continuation = false;
debug_assert_consistent(state);
}
pub(crate) fn resolve_section_after_unit(state: &mut EncoderState, continues: bool) {
state.is_english = continues;
state.needs_english_continuation = false;
if continues {
state.roman_number_chain = false;
}
debug_assert_consistent(state);
}
pub(crate) fn set_section_open(state: &mut EncoderState, open: bool) {
state.is_english = open;
state.needs_english_continuation = false;
state.roman_number_chain = false;
debug_assert_consistent(state);
}
pub(crate) fn enter_english_if_starting(
state: &mut EncoderState,
word_chars: &[char],
has_ascii_alphabetic: bool,
result: &mut Vec<u8>,
) {
let starts_english = state.english_indicator
&& !state.is_english
&& has_ascii_alphabetic
&& word_chars.first().is_some_and(|c| c.is_ascii_alphabetic());
if !starts_english {
return;
}
if state.roman_number_chain {
resume_english_from_roman_number_chain(state);
} else if state.english_dominant_no_indicator {
state.is_english = true;
state.needs_english_continuation = false;
state.roman_number_chain = false;
} else {
enter_english(state, result);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn enter_english_if_starting_emits_roman_indicator() {
let mut state = EncoderState::new(true);
let mut result = Vec::new();
enter_english_if_starting(&mut state, &['a'], true, &mut result);
assert_eq!(result, vec![ROMAN_INDICATOR]);
assert!(state.is_english);
assert!(!state.needs_english_continuation);
assert!(!state.roman_number_chain);
}
}