use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf};
use json_comments::StripComments;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use tracing::error;
use anyhow::Result;
pub trait Parser {
type Item: DeserializeOwned + Clone;
fn set_name(&mut self, name: String);
fn set_hasmap(&mut self, hs: HashMap<String, Self::Item>);
}
pub fn parse<T>(lang_file_path: &PathBuf, name: String) -> Result<T>
where
T: Parser + DeserializeOwned + Serialize + Clone + Default,
{
let file = File::open(lang_file_path)?;
let reader = BufReader::new(file);
let json_data = StripComments::new(reader);
let hs = match serde_json::from_reader(json_data) {
Ok(s) => s,
Err(err) => {
error!("{name} Parse Fail: {err:?}");
return Err(err.into());
}
};
let mut p: T = Default::default();
p.set_name(name);
p.set_hasmap(hs);
Ok(p)
}
#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum StrOrSeq {
String(String),
Array(Vec<String>),
}
impl std::fmt::Display for StrOrSeq {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
StrOrSeq::String(s) => s.clone(),
StrOrSeq::Array(v) => v.join("\n"),
}
)
}
}
impl StrOrSeq {
pub fn first(&self) -> Option<String> {
match self {
StrOrSeq::String(s) => Some(s.clone()),
StrOrSeq::Array(v) => v.first().cloned(),
}
}
}