use std::collections::HashMap;
use saphyr::{LoadableYamlNode, Yaml, Yaml::Mapping};
use aok::Result;
#[derive(PartialEq, Default)]
pub struct Term {
pub global: Option<crate::Term>,
pub lang: HashMap<u32, crate::Term>,
}
impl Term {
pub fn restore(&mut self, lang: u32, txt: impl Into<String>) -> String {
let mut txt = txt.into();
if let Some(ref mut map) = self.lang.get_mut(&lang) {
txt = map.restore(&txt);
} else if let Some(ref mut global) = self.global {
txt = global.restore(&txt);
}
txt
}
pub fn replace(&mut self, lang: u32, txt: impl Into<String>) -> String {
let mut txt = txt.into();
if let Some(ref mut map) = self.lang.get_mut(&lang) {
if let Some(t) = map.replace(&txt) {
txt = t;
}
} else if let Some(ref mut global) = self.global
&& let Some(t) = global.replace(&txt)
{
txt = t;
}
txt
}
}
fn map_li(map: &Yaml) -> Vec<(String, String)> {
if let Mapping(map) = map {
let mut li = Vec::with_capacity(map.len());
for (k, v) in map {
if let Some(k) = k.as_str() {
li.push((k.to_owned(), v.as_str().unwrap_or_default().to_owned()))
}
}
li
} else {
vec![]
}
}
pub fn load(yml: impl AsRef<str>) -> Result<Term> {
let mut term = Term::default();
let mut lang_li = Vec::new();
for i in Yaml::load_from_str(yml.as_ref())? {
if let Mapping(ref m) = i {
for (lang, term_yml) in m {
let term_li = map_li(term_yml);
if !term_li.is_empty() {
if lang.is_null() {
term.global = Some(crate::Term::load(term_li)?);
} else if let Some(lang) = lang.as_str()
&& let Some(lang) = lang::by_str(lang)
{
lang_li.push((lang as u32, term_li));
}
}
}
}
}
for (lang, term_li) in lang_li {
term.lang.insert(
lang,
if let Some(ref global) = term.global {
crate::Term::load(
term_li
.into_iter()
.chain(global.map.iter().map(|(k, v)| (k.clone(), v.clone()))),
)
} else {
crate::Term::load(term_li)
}?,
);
}
Ok(term)
}