ferrous_opencc/lib.rs
1//! # 纯 Rust 实现的 `OpenCC`
2//!
3//! 为繁体中文和简体中文之间提供高性能的转换。
4//!
5//! ## 示例
6//!
7//! ```
8//! use ferrous_opencc::OpenCC;
9//!
10//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
11//! // 创建 OpenCC 实例
12//! let opencc = OpenCC::from_config(ferrous_opencc::config::BuiltinConfig::S2t)?;
13//!
14//! // 转换文本
15//! let text = "开放中文转换是完全由 Rust 实现的。";
16//! let converted = opencc.convert(text);
17//!
18//! assert_eq!(converted, "開放中文轉換是完全由 Rust 實現的。");
19//! # Ok(())
20//! # }
21//! ```
22
23pub mod config;
24pub mod conversion;
25pub mod dictionary;
26pub mod error;
27#[cfg(not(target_arch = "wasm32"))]
28pub mod ffi;
29
30#[cfg(feature = "wasm")]
31use wasm_bindgen::prelude::*;
32
33use config::Config;
34use conversion::ConversionChain;
35use error::Result;
36use std::path::Path;
37
38use crate::{config::BuiltinConfig, dictionary::embedded};
39
40include!(concat!(env!("OUT_DIR"), "/embedded_map.rs"));
41
42/// 核心的 `OpenCC` 转换器
43#[cfg_attr(feature = "wasm", wasm_bindgen)]
44pub struct OpenCC {
45 /// 配置名称
46 name: String,
47 /// 用于执行转换的词典链
48 conversion_chain: ConversionChain,
49}
50
51impl OpenCC {
52 /// 从配置文件创建一个新的 `OpenCC` 实例。
53 /// 解析 JSON 配置文件,加载所有必需的词典,并构建转换流程。
54 ///
55 /// # 参数
56 ///
57 /// * `config_path`: 指向主 JSON 配置文件(例如 `s2t.json`)的路径
58 ///
59 /// # 返回
60 ///
61 /// 一个 `Result`,其中包含新的 `OpenCC` 实例,或者在加载失败时返回错误
62 pub fn new<P: AsRef<Path>>(config_path: P) -> Result<Self> {
63 // 1. 解析配置文件
64 let config = Config::from_file(config_path)?;
65 let config_dir = config.get_config_directory();
66
67 // 2. 初始化转换链
68 let conversion_chain = ConversionChain::from_config(&config.conversion_chain, config_dir)?;
69
70 Ok(Self {
71 name: config.name,
72 conversion_chain,
73 })
74 }
75
76 /// 从内置的配置创建 `OpenCC` 实例。
77 ///
78 /// # 示例
79 /// ```
80 /// use ferrous_opencc::{OpenCC, config::BuiltinConfig, error::Result};
81 ///
82 /// fn main() -> Result<()> {
83 /// let opencc = OpenCC::from_config(BuiltinConfig::S2t)?;
84 /// Ok(())
85 /// }
86 /// ```
87 pub fn from_config(config_enum: BuiltinConfig) -> Result<Self> {
88 let name = config_enum.to_filename();
89 let config_str = embedded::EMBEDDED_CONFIGS
90 .get(name)
91 .ok_or_else(|| error::OpenCCError::ConfigNotFound(name.to_string()))?;
92
93 let config: Config = config_str.parse()?;
94
95 let conversion_chain = ConversionChain::from_config_embedded(&config.conversion_chain)?;
96
97 Ok(Self {
98 name: config.name,
99 conversion_chain,
100 })
101 }
102
103 /// 根据加载的配置转换字符串
104 ///
105 /// # 参数
106 ///
107 /// * `input`: 需要转换的字符串
108 ///
109 /// # 返回
110 ///
111 /// 转换后的字符串
112 #[must_use]
113 pub fn convert(&self, input: &str) -> String {
114 self.conversion_chain.convert(input)
115 }
116
117 /// 返回当前加载的配置名称
118 #[must_use]
119 pub fn name(&self) -> &str {
120 &self.name
121 }
122}
123
124#[cfg(feature = "wasm")]
125#[wasm_bindgen]
126impl OpenCC {
127 /// 创建一个新的 `OpenCC` 实例。
128 ///
129 /// @param {`string`} `config_name` - 要使用的内置配置名称, 例如 "s2t.json"。
130 /// @returns {`OpenCC`} - 一个 `OpenCC` 实例。
131 /// @throws {`JsValue`} - 如果配置加载失败,则抛出一个错误对象。
132 ///
133 /// @example
134 /// ```javascript
135 /// import init, { OpenCC } from './pkg/ferrous_opencc.js';
136 ///
137 /// async function main() {
138 /// await init();
139 /// try {
140 /// const converter = new OpenCC("s2t.json");
141 /// console.log('加载成功:', converter.name);
142 /// } catch (err) {
143 /// console.error('加载失败:', err);
144 /// }
145 /// }
146 /// main();
147 /// ```
148 #[wasm_bindgen(constructor)]
149 pub fn new_wasm(config_name: &str) -> std::result::Result<Self, JsValue> {
150 let config_enum = BuiltinConfig::from_filename(config_name)
151 .map_err(|e| JsValue::from_str(&e.to_string()))?;
152 Self::from_config(config_enum).map_err(|e| JsValue::from_str(&e.to_string()))
153 }
154
155 /// 根据加载的配置转换字符串。
156 ///
157 /// @param {string} input - 需要转换的字符串。
158 /// @returns {string} - 转换后的字符串。
159 ///
160 /// @example
161 /// ```javascript
162 /// const traditionalText = converter.convert("开放中文转换");
163 /// console.log(traditionalText); // 预期: 開放中文轉換
164 /// ```
165 #[wasm_bindgen(js_name = convert)]
166 #[must_use]
167 pub fn convert_wasm(&self, input: &str) -> String {
168 self.convert(input)
169 }
170
171 /// 获取当前加载的配置的名称。
172 ///
173 /// @returns {string} - 配置的名称。
174 ///
175 /// @example
176 /// ```javascript
177 /// const configName = converter.name;
178 /// console.log(configName);
179 /// ```
180 #[wasm_bindgen(getter, js_name = name)]
181 #[must_use]
182 pub fn name_wasm(&self) -> String {
183 self.name.clone()
184 }
185}