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 pub fn convert(&self, input: &str) -> String {
113 self.conversion_chain.convert(input)
114 }
115
116 /// 返回当前加载的配置名称
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 {BuiltinConfig} config - 要使用的内置配置枚举。
128 /// @returns {Promise<OpenCC>} - 一个 Promise,成功时解析为 OpenCC 实例。
129 /// @throws {JsValue} - 如果配置加载失败,则抛出一个错误对象。
130 ///
131 /// @example
132 /// ```javascript
133 /// import init, { OpenCC, BuiltinConfig } from './pkg/ferrous_opencc.js';
134 ///
135 /// async function main() {
136 /// await init();
137 /// try {
138 /// const converter = new OpenCC(BuiltinConfig.S2t);
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: BuiltinConfig) -> std::result::Result<OpenCC, JsValue> {
148 OpenCC::from_config(config).map_err(|e| JsValue::from_str(&e.to_string()))
149 }
150
151 /// 根据加载的配置转换字符串。
152 ///
153 /// @param {string} input - 需要转换的字符串。
154 /// @returns {string} - 转换后的字符串。
155 ///
156 /// @example
157 /// ```javascript
158 /// const traditionalText = converter.convert("开放中文转换");
159 /// console.log(traditionalText); // 预期: 開放中文轉換
160 /// ```
161 #[wasm_bindgen(js_name = convert)]
162 pub fn convert_wasm(&self, input: &str) -> String {
163 self.convert(input)
164 }
165
166 /// 获取当前加载的配置的名称。
167 ///
168 /// @returns {string} - 配置的名称。
169 ///
170 /// @example
171 /// ```javascript
172 /// const configName = converter.name;
173 /// console.log(configName);
174 /// ```
175 #[wasm_bindgen(getter, js_name = name)]
176 pub fn name_wasm(&self) -> String {
177 self.name.clone()
178 }
179}