use std::iter::Peekable;
use crate::{
characters::*,
mode::Tokenizer,
policy::{Policy, Standard},
token::Token,
};
pub type Transcriber<M, P = Standard> = TokenIter<Tokenizer<M>, Standard, P>;
pub struct TokenIter<I: Iterator<Item=Token<P>>, P: Policy, Q: Policy = P> {
inner: Peekable<I>,
last: Option<Token<Q>>,
pub settings: TranscriberSettings,
}
impl<I: Iterator<Item=Token<P>>, P: Policy> TokenIter<I, P, P> {
pub fn new(iter: I) -> Self {
Self {
inner: iter.peekable(),
last: None,
settings: Default::default(),
}
}
}
impl<I: Iterator<Item=Token<P>>, P: Policy, Q: Policy> TokenIter<I, P, Q> {
pub fn into_string(self) -> String { self.collect() }
pub fn last(&self) -> Option<&Token<Q>> { self.last.as_ref() }
pub fn peek(&mut self) -> Option<&Token<P>> { self.inner.peek() }
pub fn set_policy<R: Policy>(self) -> TokenIter<I, P, R> {
TokenIter {
inner: self.inner,
last: self.last.map(Token::change_policy),
settings: self.settings,
}
}
pub const fn with_settings(mut self, new: TranscriberSettings) -> Self {
self.settings = new;
self
}
}
impl<I, P> From<I> for TokenIter<I::IntoIter, P, P> where
I: IntoIterator<Item=Token<P>>,
P: Policy,
{
fn from(iter: I) -> Self { Self::new(iter.into_iter()) }
}
impl<I, P, Q> Iterator for TokenIter<I, P, Q> where
I: Iterator<Item=Token<P>>,
P: Policy,
Q: Policy,
{
type Item = Token<Q>;
fn next(&mut self) -> Option<Self::Item> {
let mut token: Token<Q> = self.inner.next()?.change_policy::<Q>();
if let Token::Glyph(glyph) = &mut token {
glyph.ligate_zwj = self.settings.ligate_zwj;
glyph.nuquerna = self.settings.nuquerna;
glyph.vowels = self.settings.vowels;
if self.settings.dot_plain && !glyph.carries_tehta() {
glyph.dot_under = true;
}
if self.settings.elide_a && glyph.tehta_is_a() {
if self.settings.keep_a_long && glyph.tehta_alt {
glyph.tehta_alt = false;
} else if self.settings.keep_a_init {
if matches!(&self.last, Some(Token::Glyph(_))) {
glyph.tehta_hidden = true;
}
} else {
glyph.tehta_hidden = true;
}
}
if self.settings.alt_a {
glyph.set_alt_a();
}
match self.inner.peek() {
Some(Token::Glyph(next)) => {
glyph.rince_final = false;
glyph.ligate_short = self.settings.ligate_short
&& next.telco_ligates();
}
_ => {
glyph.rince_final = self.settings.alt_rince;
glyph.ligate_short = false;
}
}
}
self.last = Some(token);
self.last
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct TranscriberSettings {
pub alt_a: bool,
pub alt_rince: bool,
pub dot_plain: bool,
pub elide_a: bool,
pub keep_a_init: bool,
pub keep_a_long: bool,
pub ligate_short: bool,
pub ligate_zwj: u8,
pub nuquerna: bool,
pub vowels: VowelStyle,
}
impl TranscriberSettings {
pub const fn new() -> Self {
Self {
alt_a: false,
alt_rince: false,
dot_plain: false,
elide_a: false,
keep_a_init: false,
keep_a_long: false,
ligate_short: false,
ligate_zwj: 0,
nuquerna: false,
vowels: VowelStyle::DEFAULT,
}
}
}
impl Default for TranscriberSettings {
fn default() -> Self { Self::new() }
}