1use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf};
2
3use json_comments::StripComments;
4use serde::{Deserialize, Serialize, de::DeserializeOwned};
5use tracing::error;
6
7use anyhow::Result;
9
10pub trait Parser {
11 type Item: DeserializeOwned + Clone;
12 fn set_name(&mut self, name: String);
13 fn set_hasmap(&mut self, hs: HashMap<String, Self::Item>);
14}
15
16pub fn parse<T>(lang_file_path: &PathBuf, name: String) -> Result<T>
18where
19 T: Parser + DeserializeOwned + Serialize + Clone + Default,
20{
21 let file = File::open(lang_file_path)?;
22 let reader = BufReader::new(file);
23
24 let json_data = StripComments::new(reader);
26
27 let hs = match serde_json::from_reader(json_data) {
29 Ok(s) => s,
30 Err(err) => {
31 error!("{name} Parse Fail: {err:?}");
32 return Err(err.into());
33 }
34 };
35
36 let mut p: T = Default::default();
37 p.set_name(name);
38 p.set_hasmap(hs);
39
40 Ok(p)
41}
42
43#[derive(Deserialize, Serialize, Clone, Debug)]
45#[serde(untagged)]
46pub enum StrOrSeq {
47 String(String),
48 Array(Vec<String>),
49}
50
51impl std::fmt::Display for StrOrSeq {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 write!(
54 f,
55 "{}",
56 match self {
57 StrOrSeq::String(s) => s.clone(),
58 StrOrSeq::Array(v) => v.join("\n"),
59 }
60 )
61 }
62}
63
64impl StrOrSeq {
65 pub fn first(&self) -> Option<String> {
67 match self {
68 StrOrSeq::String(s) => Some(s.clone()),
69 StrOrSeq::Array(v) => v.first().cloned(),
70 }
71 }
72}