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