ferrous_opencc/
config.rs

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/// 顶层的 JSON 配置结构
9#[derive(Deserialize, Debug)]
10pub struct Config {
11    /// 转换配置的名称
12    pub name: String,
13    /// 分词相关的配置
14    pub segmentation: SegmentationConfig,
15    /// 转换步骤链
16    pub conversion_chain: Vec<ConversionNodeConfig>,
17
18    /// 配置文件所在的目录
19    #[serde(skip)]
20    config_directory: PathBuf,
21}
22
23/// 配置中的分词部分
24#[derive(Deserialize, Debug)]
25pub struct SegmentationConfig {
26    /// 使用的分词器类型,例如 "mm" (最大匹配)
27    #[serde(rename = "type")]
28    pub seg_type: String,
29    /// 分词所使用的词典
30    pub dict: DictConfig,
31}
32
33/// 转换链中的一个节点
34/// 每个节点对应一个基于词典的转换步骤
35#[derive(Deserialize, Debug)]
36pub struct ConversionNodeConfig {
37    /// 此转换步骤要使用的词典
38    pub dict: DictConfig,
39}
40
41/// 代表一个词典配置,可以是一个单独的词典文件,也可以是一组词典
42#[derive(Deserialize, Debug)]
43pub struct DictConfig {
44    /// 词典的类型,例如 "text" 或 "group"
45    #[serde(rename = "type")]
46    pub dict_type: String,
47    /// 词典文件名 (用于 `type: "text"`)
48    pub file: Option<String>,
49    /// 子词典列表 (用于 `type: "group"`)。
50    pub dicts: Option<Vec<DictConfig>>,
51}
52
53impl Config {
54    /// 从 JSON 文件加载并解析配置
55    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        // 保存配置文件的父目录
63        config.config_directory = path.parent().unwrap_or_else(|| Path::new("")).to_path_buf();
64
65        Ok(config)
66    }
67
68    /// 获取配置文件所在的目录
69    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}