use serde::Deserialize;
use serde_json::{Map, Value};
use super::script::Script;
#[derive(Deserialize)]
struct RawHyphenMins {
left: i32,
right: i32,
}
fn default_syllable_mode() -> String {
"tex".to_string()
}
#[derive(Deserialize)]
struct RawLanguage {
code: String,
name: String,
#[serde(rename = "nativeName")]
native_name: String,
script: Script,
#[serde(rename = "hyphenMins")]
hyphen_mins: RawHyphenMins,
#[serde(rename = "letterPattern")]
letter_pattern: String,
#[serde(rename = "wordSplitPattern")]
word_split_pattern: String,
#[serde(rename = "sentenceBoundaryPattern")]
sentence_boundary_pattern: String,
#[serde(default)]
formulas: Map<String, Value>,
#[serde(rename = "syllableHeuristics", default)]
syllable_heuristics: Option<Value>,
#[serde(rename = "syllableMode", default = "default_syllable_mode")]
syllable_mode: String,
}
#[derive(Debug, Clone)]
pub struct Language {
pub code: String,
pub name: String,
pub native_name: String,
pub script: Script,
pub min_hyphen_left: i32,
pub min_hyphen_right: i32,
pub letter_pattern: String,
pub word_split_pattern: String,
pub sentence_boundary_pattern: String,
pub formula_configs: Map<String, Value>,
pub syllable_heuristics: Option<Value>,
pub syllable_mode: String,
}
impl Language {
pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
let raw: RawLanguage = serde_json::from_str(json)?;
Ok(Language {
code: raw.code,
name: raw.name,
native_name: raw.native_name,
script: raw.script,
min_hyphen_left: raw.hyphen_mins.left,
min_hyphen_right: raw.hyphen_mins.right,
letter_pattern: raw.letter_pattern,
word_split_pattern: raw.word_split_pattern,
sentence_boundary_pattern: raw.sentence_boundary_pattern,
formula_configs: raw.formulas,
syllable_heuristics: raw.syllable_heuristics,
syllable_mode: raw.syllable_mode,
})
}
pub fn supports_formula(&self, formula_name: &str) -> bool {
self.formula_configs.contains_key(formula_name)
}
pub fn get_formula_config(&self, formula_name: &str) -> Option<&Value> {
self.formula_configs.get(formula_name)
}
pub fn get_supported_formulas(&self) -> Vec<String> {
self.formula_configs.keys().cloned().collect()
}
pub fn formula_number(&self, formula_name: &str, key: &str) -> Option<f64> {
self.get_formula_config(formula_name)
.and_then(|cfg| cfg.get(key))
.and_then(value_as_f64)
}
}
pub(crate) fn value_as_f64(v: &Value) -> Option<f64> {
match v {
Value::Number(n) => n.as_f64(),
Value::String(s) => s.trim().parse::<f64>().ok(),
_ => None,
}
}