1use crate::error::{OpenCCError, Result};
2use serde::{Deserialize, Serialize};
3use std::fs::File;
4use std::io::BufReader;
5use std::path::{Path, PathBuf};
6use std::str::FromStr;
7
8#[cfg(feature = "wasm")]
9use wasm_bindgen::prelude::*;
10
11#[derive(Serialize, Deserialize, Debug)]
13pub struct Config {
14 pub name: String,
16 pub conversion_chain: Vec<ConversionNodeConfig>,
18
19 #[serde(skip)]
21 config_directory: PathBuf,
22}
23
24#[repr(i32)]
26#[cfg_attr(feature = "wasm", wasm_bindgen)]
27#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)]
28pub enum BuiltinConfig {
29 S2t = 0,
31 T2s = 1,
33 S2tw = 2,
35 Tw2s = 3,
37 S2hk = 4,
39 Hk2s = 5,
41 S2twp = 6,
43 Tw2sp = 7,
45 T2tw = 8,
47 Tw2t = 9,
49 T2hk = 10,
51 Hk2t = 11,
53 Jp2t = 12,
55 T2jp = 13,
57}
58
59impl BuiltinConfig {
60 pub fn to_filename(&self) -> &'static str {
62 match self {
63 BuiltinConfig::S2t => "s2t.json",
64 BuiltinConfig::T2s => "t2s.json",
65 BuiltinConfig::S2tw => "s2tw.json",
66 BuiltinConfig::Tw2s => "tw2s.json",
67 BuiltinConfig::S2hk => "s2hk.json",
68 BuiltinConfig::Hk2s => "hk2s.json",
69 BuiltinConfig::S2twp => "s2twp.json",
70 BuiltinConfig::Tw2sp => "tw2sp.json",
71 BuiltinConfig::T2tw => "t2tw.json",
72 BuiltinConfig::Tw2t => "tw2t.json",
73 BuiltinConfig::T2hk => "t2hk.json",
74 BuiltinConfig::Hk2t => "hk2t.json",
75 BuiltinConfig::Jp2t => "jp2t.json",
76 BuiltinConfig::T2jp => "t2jp.json",
77 }
78 }
79
80 pub fn from_filename(filename: &str) -> Result<Self> {
82 match filename {
83 "s2t.json" => Ok(BuiltinConfig::S2t),
84 "t2s.json" => Ok(BuiltinConfig::T2s),
85 "s2tw.json" => Ok(BuiltinConfig::S2tw),
86 "tw2s.json" => Ok(BuiltinConfig::Tw2s),
87 "s2hk.json" => Ok(BuiltinConfig::S2hk),
88 "hk2s.json" => Ok(BuiltinConfig::Hk2s),
89 "s2twp.json" => Ok(BuiltinConfig::S2twp),
90 "tw2sp.json" => Ok(BuiltinConfig::Tw2sp),
91 "t2tw.json" => Ok(BuiltinConfig::T2tw),
92 "tw2t.json" => Ok(BuiltinConfig::Tw2t),
93 "t2hk.json" => Ok(BuiltinConfig::T2hk),
94 "hk2t.json" => Ok(BuiltinConfig::Hk2t),
95 "jp2t.json" => Ok(BuiltinConfig::Jp2t),
96 "t2jp.json" => Ok(BuiltinConfig::T2jp),
97 _ => Err(OpenCCError::ConfigNotFound(filename.to_string())),
98 }
99 }
100}
101
102#[derive(Serialize, Deserialize, Debug)]
105pub struct ConversionNodeConfig {
106 pub dict: DictConfig,
108}
109
110#[derive(Serialize, Deserialize, Debug)]
112pub struct DictConfig {
113 #[serde(rename = "type")]
115 pub dict_type: String,
116 pub file: Option<String>,
118 pub dicts: Option<Vec<DictConfig>>,
120}
121
122impl Config {
123 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
125 let path = path.as_ref();
126 let file = File::open(path)
127 .map_err(|e| OpenCCError::FileNotFound(format!("{}: {}", path.display(), e)))?;
128 let reader = BufReader::new(file);
129 let mut config: Config = serde_json::from_reader(reader)?;
130
131 config.config_directory = path.parent().unwrap_or_else(|| Path::new("")).to_path_buf();
133
134 Ok(config)
135 }
136
137 pub fn get_config_directory(&self) -> &Path {
139 &self.config_directory
140 }
141}
142
143impl FromStr for Config {
144 type Err = OpenCCError;
145
146 fn from_str(s: &str) -> Result<Self> {
147 let config: Config = serde_json::from_str(s)?;
148 Ok(config)
149 }
150}