const CONSONANTS: [&str; 33] = [
"k", "kh", "g", "gh", "ṅ",
"c", "ch", "j", "jh", "ñ",
"ṭ", "ṭh", "ḍ", "ḍh", "ṇ",
"t", "th", "d", "dh", "n",
"p", "ph", "b", "bh", "m",
"y", "r", "l", "v",
"ś", "ṣ", "s", "h"
];
const MATRAS: [&str; 16] = [
"a", "ā", "i", "ī", "u", "ū", "ṛ", "ṝ",
"ḷ", "ḹ", "e", "ai", "o", "au", "aṃ", "aḥ"
];
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MatraWeight {
Laghu, Guru, }
#[derive(Debug, Clone, PartialEq)]
pub struct Syllable {
pub value: u16, }
impl Syllable {
pub fn new(val: u16) -> self::Syllable {
Syllable { value: val }
}
pub fn to_sanskrit(&self) -> String {
let v = self.value as usize;
let c_idx = v / 16;
let m_idx = v % 16;
let c = CONSONANTS[c_idx % 33];
let m_str = if m_idx < 8 {
let lags = [0, 2, 4, 6, 8];
MATRAS[lags[m_idx % 5]]
} else {
let gurs = [1, 3, 5, 7, 9, 10, 11, 12, 13, 14, 15];
MATRAS[gurs[(m_idx - 8) % 11]]
};
format!("{}{}", c, m_str)
}
}
pub fn get_matra_weight(idx: usize) -> MatraWeight {
if idx < 8 {
MatraWeight::Laghu
} else {
MatraWeight::Guru
}
}
pub fn encode_vector(vec: &[u16], use_meter: bool) -> String {
let mut result = Vec::new();
for (i, val) in vec.iter().enumerate() {
result.push(Syllable::new(*val).to_sanskrit());
if use_meter && (i + 1) % 8 == 0 {
result.push("।".to_string());
}
}
result.join(" ")
}
pub fn decode_verse(verse: &str) -> Vec<u16> {
verse.split_whitespace()
.map(|s| {
let mut val = 0;
for c in 0..33 {
for m_idx in 0..16 {
let candidate_val = (c * 16 + m_idx) as u16;
let built = Syllable::new(candidate_val).to_sanskrit();
if built == s {
return candidate_val;
}
}
}
0 })
.collect()
}