use super::Dictionary;
use crate::{GraphemeProps, GraphemeState};
pub(crate) fn next_word(
dictionary: &Dictionary,
chars: impl Iterator<Item = (usize, char)>,
props: impl Fn(char) -> GraphemeProps,
graphemes: GraphemeState,
) -> Option<usize> {
longest_word(dictionary, chars, props, graphemes).0
}
pub(crate) fn longest_word(
dictionary: &Dictionary,
chars: impl Iterator<Item = (usize, char)>,
props: impl Fn(char) -> GraphemeProps,
mut graphemes: GraphemeState,
) -> (Option<usize>, bool) {
let automaton = dictionary.automaton();
let mut state = 0;
let mut matching = true;
let mut word = false;
let mut longest = None;
let mut second_cluster = None;
let mut first = true;
for (offset, ch) in chars {
let starts_cluster = graphemes.advance(props(ch));
if !first && starts_cluster {
if word {
longest = Some(offset);
}
second_cluster.get_or_insert(offset);
}
first = false;
word = false;
if matching {
match dictionary
.symbol(ch)
.and_then(|symbol| automaton.step(state, symbol))
{
Some(next) => {
state = next;
word = automaton.is_terminal(next);
}
None => matching = false,
}
}
if !matching {
if longest.is_some() {
return (longest, true);
}
if second_cluster.is_some() {
return (second_cluster, false);
}
}
}
if matching && word {
return (None, true);
}
match longest {
Some(longest) => (Some(longest), true),
None => (second_cluster, false),
}
}