use derive_builder::Builder;
use std::fmt;
pub type CharsMapping = Vec<(&'static str, &'static str)>;
pub trait ToLatin {
fn translit(&self, input: &str) -> String;
}
pub trait FromLatin {
fn translit_reverse(&self, input: &str) -> String;
}
#[derive(Debug, Builder, Clone)]
pub struct Transliterator {
#[builder(setter(into))]
pub language: String,
#[builder(setter(into))]
pub code: String,
mapping: CharsMapping,
pre_processor_mapping: Option<CharsMapping>,
reverse_specific_mapping: Option<CharsMapping>,
reverse_specific_pre_processor_mapping: Option<CharsMapping>,
}
impl Transliterator {
fn transliterate(&self, input: &str, reverse: bool) -> String {
let mut input = input.to_owned();
if reverse {
if let Some(mapping) = &self.reverse_specific_mapping {
for elem in mapping.iter() {
let (source_char, translit_char) = (elem.0, elem.1);
input = input.replace(source_char, translit_char);
}
}
if let Some(mapping) = &self.reverse_specific_pre_processor_mapping {
for elem in mapping.iter() {
let (source_char, translit_char) = (elem.0, elem.1);
input = input.replace(source_char, translit_char);
}
}
}
if let Some(mapping) = &self.pre_processor_mapping {
for elem in mapping.iter() {
let (source_char, translit_char) = if reverse {
(elem.1, elem.0)
} else {
(elem.0, elem.1)
};
input = input.replace(source_char, translit_char);
}
}
for elem in self.mapping.iter() {
let (source_char, translit_char) = if reverse {
(elem.1, elem.0)
} else {
(elem.0, elem.1)
};
input = input.replace(source_char, translit_char);
}
input
}
}
impl ToLatin for Transliterator {
fn translit(&self, input: &str) -> String {
self.transliterate(input, false)
}
}
impl FromLatin for Transliterator {
fn translit_reverse(&self, input: &str) -> String {
self.transliterate(input, true)
}
}
impl fmt::Display for Transliterator {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.language)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::languages::Bulgarian;
const BULGARIAN: &str = "Лорем ипсум долор сит амет";
const LATIN: &str = "Lorem ipsum dolor sit amet";
#[test]
fn test_translit() {
let t = Transliterator::from(Bulgarian::new());
let result = t.translit(BULGARIAN);
assert_eq!(result, LATIN);
}
#[test]
fn test_translit_reverse() {
let t = Transliterator::from(Bulgarian::new());
let result = t.translit_reverse(LATIN);
assert_eq!(result, BULGARIAN);
}
}