1use crate::error::{OpenCCError, Result};
2use serde::Deserialize;
3use std::fs::File;
4use std::io::BufReader;
5use std::path::{Path, PathBuf};
6use std::str::FromStr;
7
8#[derive(Deserialize, Debug)]
10pub struct Config {
11 pub name: String,
13 pub segmentation: SegmentationConfig,
15 pub conversion_chain: Vec<ConversionNodeConfig>,
17
18 #[serde(skip)]
20 config_directory: PathBuf,
21}
22
23#[derive(Deserialize, Debug)]
25pub struct SegmentationConfig {
26 #[serde(rename = "type")]
28 pub seg_type: String,
29 pub dict: DictConfig,
31}
32
33#[derive(Deserialize, Debug)]
36pub struct ConversionNodeConfig {
37 pub dict: DictConfig,
39}
40
41#[derive(Deserialize, Debug)]
43pub struct DictConfig {
44 #[serde(rename = "type")]
46 pub dict_type: String,
47 pub file: Option<String>,
49 pub dicts: Option<Vec<DictConfig>>,
51}
52
53impl Config {
54 pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
56 let path = path.as_ref();
57 let file = File::open(path)
58 .map_err(|e| OpenCCError::FileNotFound(format!("{}: {}", path.display(), e)))?;
59 let reader = BufReader::new(file);
60 let mut config: Config = serde_json::from_reader(reader)?;
61
62 config.config_directory = path.parent().unwrap_or_else(|| Path::new("")).to_path_buf();
64
65 Ok(config)
66 }
67
68 pub fn get_config_directory(&self) -> &Path {
70 &self.config_directory
71 }
72}
73
74impl FromStr for Config {
75 type Err = OpenCCError;
76
77 fn from_str(s: &str) -> Result<Self> {
78 let config: Config = serde_json::from_str(s)?;
79 Ok(config)
80 }
81}