use crate::generated::{
LEXICON, LEXICON_OFFSETS, LEXICON_ORDERED_LENGTHS, LEXICON_ORDERED_LENGTHS_LEN,
LEXICON_SHORT_LENGTHS, PHRASEBOOK, PHRASEBOOK_SHORT,
};
#[derive(Clone)]
struct PhrasebookIter {
index: u32,
}
impl PhrasebookIter {
fn empty() -> Self {
Self {
index: PHRASEBOOK.len() as u32,
}
}
}
impl Iterator for PhrasebookIter {
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
let b = *PHRASEBOOK.get(self.index as usize)?;
self.index += 1;
Some(b)
}
}
#[derive(Clone)]
pub struct IterStr {
phrasebook: PhrasebookIter,
last_was_word: bool,
}
impl IterStr {
pub fn new(start_index: u32) -> IterStr {
IterStr {
phrasebook: PhrasebookIter { index: start_index },
last_was_word: false,
}
}
}
const HYPHEN: u8 = 127;
static LEXICON_ORDERED_LENGTH_INDICES: [u16; LEXICON_ORDERED_LENGTHS_LEN] = {
let mut arr = [0u16; LEXICON_ORDERED_LENGTHS_LEN];
let mut prev_len = None;
let mut i = 0;
while i < LEXICON_ORDERED_LENGTHS.len() {
let (end_idx, length) = LEXICON_ORDERED_LENGTHS[i];
if let Some(prev_len) = prev_len {
assert!(length == prev_len + 1);
}
prev_len = Some(length);
assert!(end_idx <= u16::MAX as usize);
arr[i] = end_idx as u16 - 1;
i += 1;
}
arr
};
impl Iterator for IterStr {
type Item = &'static str;
fn next(&mut self) -> Option<&'static str> {
let mut tmp = self.phrasebook.clone();
let raw_b = tmp.next()?;
let (is_end, b) = (raw_b & 0b1000_0000 != 0, raw_b & 0b0111_1111);
let ret = if b == HYPHEN {
self.last_was_word = false;
"-"
} else if self.last_was_word {
self.last_was_word = false;
return Some(" ");
} else {
self.last_was_word = true;
let (length, idx) = if b < PHRASEBOOK_SHORT {
let idx = b as usize;
(LEXICON_SHORT_LENGTHS[idx] as usize, idx)
} else {
let idx = u16::from_be_bytes([b - PHRASEBOOK_SHORT, tmp.next().unwrap()]);
let length = match LEXICON_ORDERED_LENGTH_INDICES.binary_search(&idx) {
Ok(i) => i,
Err(i) => i,
};
(length, idx as usize)
};
let offset = LEXICON_OFFSETS[idx] as usize;
&LEXICON[offset..offset + length]
};
self.phrasebook = if is_end { PhrasebookIter::empty() } else { tmp };
Some(ret)
}
}