use std::fs;
use std::path::{Component, Path};
use rustc_hash::FxHashMap;
use crate::error::LangError;
use crate::intern::intern;
use crate::store::StoredValue;
fn validate_locale(locale: &str) -> Result<(), LangError> {
let mut components = Path::new(locale).components();
match (components.next(), components.next()) {
(Some(Component::Normal(_)), None) => Ok(()),
_ => Err(LangError::InvalidLocale {
locale: locale.to_string(),
}),
}
}
pub(crate) fn load_file(
path: &str,
locale: &str,
) -> Result<FxHashMap<&'static str, StoredValue>, LangError> {
validate_locale(locale)?;
let file_path = Path::new(path).join(format!("{locale}.toml"));
let raw = fs::read_to_string(&file_path).map_err(|e| LangError::Io {
locale: locale.to_string(),
cause: e.to_string(),
})?;
parse_toml(locale, &raw)
}
pub(crate) fn parse_toml(
locale: &str,
raw: &str,
) -> Result<FxHashMap<&'static str, StoredValue>, LangError> {
let table: toml::Table = raw.parse().map_err(|e: toml::de::Error| LangError::Parse {
locale: locale.to_string(),
cause: e.to_string(),
})?;
let mut map: FxHashMap<&'static str, StoredValue> =
FxHashMap::with_capacity_and_hasher(table.len(), rustc_hash::FxBuildHasher);
for (key, value) in table {
if let toml::Value::String(s) = value {
let _ = map.insert(intern(&key), value_from_string(s));
}
}
Ok(map)
}
#[cfg(not(feature = "hot-reload"))]
#[inline]
fn value_from_string(s: String) -> StoredValue {
intern(&s)
}
#[cfg(feature = "hot-reload")]
#[inline]
fn value_from_string(s: String) -> StoredValue {
std::sync::Arc::from(s)
}