use crate::alias::{Alphabet, Cyrillic, Latin};
type Processor = fn(&Alphabet, Cyrillic, Option<Cyrillic>, Option<Cyrillic>) -> Latin;
enum Handler {
Basic,
Smart(Processor),
}
pub struct Engine {
alphabet: Alphabet,
handler: Handler,
}
impl Engine {
pub fn basic(alphabet: Alphabet) -> Self {
Self {
alphabet,
handler: Handler::Basic,
}
}
pub fn smart(alphabet: Alphabet, processor: Processor) -> Self {
Self {
alphabet,
handler: Handler::Smart(processor),
}
}
pub fn process(&self, source: &str) -> Latin {
match &self.handler {
Handler::Basic => self.transliterate(source),
Handler::Smart(processor) => self.latinize(source, *processor),
}
}
fn transliterate(&self, source: &str) -> Latin {
source
.chars()
.map(|c| {
self.alphabet
.get(&c)
.map(|s| s.to_string())
.unwrap_or_else(|| c.to_string())
})
.collect()
}
fn latinize(&self, source: &str, processor: Processor) -> Latin {
let chars: Vec<Cyrillic> = source.chars().collect();
let mut result = String::with_capacity(chars.len() * 2);
for (index, ¤t) in chars.iter().enumerate() {
let prev = if index > 0 { Some(chars[index - 1]) } else { None };
let next = chars.get(index + 1).copied();
let translated = processor(&self.alphabet, current, prev, next);
result.push_str(&translated);
}
result
}
}