ferrous_opencc/dictionary/
mod.rs1mod dict_group;
4mod fst_dict;
5
6pub(super) mod embedded {
7 include!(concat!(env!("OUT_DIR"), "/embedded_map.rs"));
8}
9
10use crate::config::DictConfig;
11use crate::error::{OpenCCError, Result};
12use dict_group::DictGroup;
13pub use fst_dict::FstDict;
14use std::fmt::Debug;
15use std::path::{Path, PathBuf};
16use std::sync::Arc;
17
18pub(super) trait Dictionary: Send + Sync + Debug {
20 fn match_prefix<'a>(&self, word: &'a str) -> Option<(&'a str, Vec<String>)>;
26
27 fn max_key_length(&self) -> usize;
29}
30
31#[allow(dead_code)]
34pub(super) enum DictType {
35 Fst(FstDict),
36 Group(DictGroup),
37}
38
39impl DictType {
40 pub(super) fn from_config(
42 config: &DictConfig,
43 config_dir: &Path,
44 ) -> Result<Arc<dyn Dictionary>> {
45 match config.dict_type.as_str() {
46 "text" | "ocd2" => {
47 let file_name = config.file.as_ref().ok_or_else(|| {
48 OpenCCError::InvalidConfig("'file' not found for 'text' dict".to_string())
49 })?;
50 let dict_path = find_dict_path(file_name, config_dir)?;
51 let dict = FstDict::new(&dict_path)?;
52 Ok(Arc::new(dict))
53 }
54 "group" => {
55 let dict_configs = config.dicts.as_ref().ok_or_else(|| {
56 OpenCCError::InvalidConfig("'dicts' not found for 'group' dict".to_string())
57 })?;
58 let mut dicts = Vec::new();
59 for dict_config in dict_configs {
60 dicts.push(Self::from_config(dict_config, config_dir)?);
62 }
63 let dict_group = DictGroup::new(dicts);
64 Ok(Arc::new(dict_group))
65 }
66 _ => Err(OpenCCError::UnsupportedDictType(config.dict_type.clone())),
67 }
68 }
69
70 pub(super) fn from_config_embedded(config: &DictConfig) -> Result<Arc<dyn Dictionary>> {
72 match config.dict_type.as_str() {
73 "text" | "ocd2" => {
74 let file_name = config.file.as_ref().ok_or_else(|| {
75 OpenCCError::InvalidConfig("'file' not found for 'text' dict".to_string())
76 })?;
77
78 let dict_bytes = embedded::EMBEDDED_DICTS
80 .get(file_name.as_str())
81 .ok_or_else(|| OpenCCError::ConfigNotFound(file_name.clone()))?;
82
83 let dict = FstDict::from_ocb_bytes(dict_bytes)?;
84 Ok(Arc::new(dict))
85 }
86 "group" => {
87 let dict_configs = config.dicts.as_ref().ok_or_else(|| {
88 OpenCCError::InvalidConfig("'dicts' not found for 'group' dict".to_string())
89 })?;
90 let mut dicts = Vec::new();
91 for dict_config in dict_configs {
92 dicts.push(Self::from_config_embedded(dict_config)?);
94 }
95 let dict_group = DictGroup::new(dicts);
96 Ok(Arc::new(dict_group))
97 }
98 _ => Err(OpenCCError::UnsupportedDictType(config.dict_type.clone())),
99 }
100 }
101}
102
103fn find_dict_path(file_name: &str, config_dir: &Path) -> Result<PathBuf> {
105 let path = config_dir.join(file_name);
106 if path.exists() {
107 return Ok(path);
108 }
109
110 Err(OpenCCError::FileNotFound(path.display().to_string()))
111}