use crate::uax29::{Action, state_enum, word::properties::WordBreakProperty};
state_enum! {
StartOfText, Any, CR, ALetter, Numeric, HLetter, Katakana,
ExtendNumLet, WSegSpace, AHLetterMid, Newline, RIOdd, NumericMid, HLetterDQ,
}
impl State {
pub const fn is_deferred(self) -> bool {
match self {
State::AHLetterMid | State::NumericMid | State::HLetterDQ => true,
State::StartOfText
| State::Any
| State::CR
| State::ALetter
| State::Numeric
| State::HLetter
| State::Katakana
| State::ExtendNumLet
| State::WSegSpace
| State::RIOdd
| State::Newline => false,
}
}
}
#[derive(Clone, Copy)]
pub(crate) struct Transition(pub(crate) State, pub(crate) Action);
type Row = [Transition; WordBreakProperty::NUM_VARIANTS];
pub(crate) const TABLE: [Row; State::NUM_VARIANTS] = [
start_of_text_transitions(),
any_transitions(),
cr_transitions(),
aletter_transitions(),
numeric_transitions(),
hletter_transitions(),
katakana_transitions(),
extendnumlet_transitions(),
wsegspace_transitions(),
ahletter_mid_transitions(),
newline_transitions(),
ri_odd_transitions(),
numeric_mid_transitions(),
hletter_dq_transitions(),
];
const fn default_all_break() -> Row {
let mut row = [brk(State::Any); WordBreakProperty::NUM_VARIANTS];
row[WordBreakProperty::ALetter as usize] = brk(State::ALetter);
row[WordBreakProperty::Numeric as usize] = brk(State::Numeric);
row[WordBreakProperty::CR as usize] = brk(State::CR);
row[WordBreakProperty::HebrewLetter as usize] = brk(State::HLetter);
row[WordBreakProperty::WSegSpace as usize] = brk(State::WSegSpace);
row[WordBreakProperty::Katakana as usize] = brk(State::Katakana);
row[WordBreakProperty::ExtendNumLet as usize] = brk(State::ExtendNumLet);
row[WordBreakProperty::Format as usize] = transparent();
row[WordBreakProperty::Extend as usize] = transparent();
row[WordBreakProperty::ZWJ as usize] = transparent();
row[WordBreakProperty::LF as usize] = brk(State::Newline);
row[WordBreakProperty::Newline as usize] = brk(State::Newline);
row[WordBreakProperty::RegionalIndicator as usize] = brk(State::RIOdd);
row
}
const fn default_all_deferred() -> Row {
let mut row = [deferred(State::Any); WordBreakProperty::NUM_VARIANTS];
row[WordBreakProperty::Format as usize] = transparent();
row[WordBreakProperty::Extend as usize] = transparent();
row[WordBreakProperty::ZWJ as usize] = transparent();
row
}
const fn without_wb4(row: &mut Row) {
row[WordBreakProperty::Extend as usize] = brk(State::Any);
row[WordBreakProperty::Format as usize] = brk(State::Any);
row[WordBreakProperty::ZWJ as usize] = brk(State::Any);
}
const fn start_of_text_transitions() -> Row {
let mut row = default_all_break();
without_wb4(&mut row);
row
}
const fn any_transitions() -> Row {
default_all_break()
}
const fn cr_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::LF as usize] = nb(State::Newline); without_wb4(&mut row);
row
}
const fn aletter_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::ALetter as usize] = nb(State::ALetter);
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row[WordBreakProperty::Numeric as usize] = nb(State::Numeric);
row[WordBreakProperty::MidLetter as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::MidNumLet as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::SingleQuote as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::ExtendNumLet as usize] = nb(State::ExtendNumLet);
row
}
const fn numeric_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::Numeric as usize] = nb(State::Numeric);
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row[WordBreakProperty::ALetter as usize] = nb(State::ALetter);
row[WordBreakProperty::MidNum as usize] = nb(State::NumericMid);
row[WordBreakProperty::MidNumLet as usize] = nb(State::NumericMid);
row[WordBreakProperty::SingleQuote as usize] = nb(State::NumericMid);
row[WordBreakProperty::ExtendNumLet as usize] = nb(State::ExtendNumLet);
row
}
const fn hletter_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row[WordBreakProperty::ALetter as usize] = nb(State::ALetter);
row[WordBreakProperty::Numeric as usize] = nb(State::Numeric);
row[WordBreakProperty::MidLetter as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::MidNumLet as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::SingleQuote as usize] = nb(State::AHLetterMid);
row[WordBreakProperty::SingleQuote as usize] = nb(State::Any);
row[WordBreakProperty::DoubleQuote as usize] = nb(State::HLetterDQ);
row[WordBreakProperty::ExtendNumLet as usize] = nb(State::ExtendNumLet);
row
}
const fn katakana_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::Katakana as usize] = nb(State::Katakana);
row[WordBreakProperty::ExtendNumLet as usize] = nb(State::ExtendNumLet);
row
}
const fn extendnumlet_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::ALetter as usize] = nb(State::ALetter);
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row[WordBreakProperty::Numeric as usize] = nb(State::Numeric);
row[WordBreakProperty::Katakana as usize] = nb(State::Katakana);
row[WordBreakProperty::ExtendNumLet as usize] = nb(State::ExtendNumLet);
row
}
const fn wsegspace_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::WSegSpace as usize] = nb(State::WSegSpace);
row[WordBreakProperty::Extend as usize] = nb(State::Any);
row[WordBreakProperty::Format as usize] = nb(State::Any);
row[WordBreakProperty::ZWJ as usize] = nb(State::Any);
row
}
const fn ahletter_mid_transitions() -> Row {
let mut row = default_all_deferred();
row[WordBreakProperty::ALetter as usize] = nb(State::ALetter);
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row
}
const fn newline_transitions() -> Row {
let mut row = default_all_break();
without_wb4(&mut row);
row
}
const fn numeric_mid_transitions() -> Row {
let mut row = default_all_deferred();
row[WordBreakProperty::Numeric as usize] = nb(State::Numeric);
row
}
const fn hletter_dq_transitions() -> Row {
let mut row = default_all_deferred();
row[WordBreakProperty::HebrewLetter as usize] = nb(State::HLetter);
row
}
const fn ri_odd_transitions() -> Row {
let mut row = default_all_break();
row[WordBreakProperty::RegionalIndicator as usize] = nb(State::Any);
row
}
const fn nb(s: State) -> Transition {
Transition(s, Action::NoBreak)
}
const fn brk(s: State) -> Transition {
Transition(s, Action::Break)
}
const fn deferred(s: State) -> Transition {
Transition(s, Action::DeferredBreak)
}
const fn transparent() -> Transition {
Transition(State::Any, Action::Transparent)
}