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