Skip to main content

msime_engine/
lib.rs

1// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2
3//! The input engine: composition state, input schemes, dictionary queries, ranking and learning.
4//!
5//! This crate replaces the C++ MSIME-Engine that used to be fetched from `engine-lock.json` and patched by overlay scripts. It owns the input algorithms; `msime-input-runtime` keeps orchestrating hosts and does not duplicate any of it.
6//!
7//! The documented API is the core layer at the crate root: `Session`, its options and snapshot, and the functions and types beside them (they mirror the C++ `metasequoia::` API the golden fixtures were recorded against), plus the public modules such as `assets`, `diagnostics`, `touch` and `multilingual`. `host`, `ordering`, `backend` and `web` are msime's own product glue (the session facade and settings-page helpers its hosts call, its candidate ordering, its msime-cloud protocol, its browser storage): they stay `pub` only so msime's crates in the same repository can reach them, are hidden from the documentation, are not part of the library API and change with msime's hosts; other programs should not use them. msime's product crates import everything the core layer takes or returns from the root, like a third party would; the boundary is described in `docs/ARCHITECTURE.md` and `.agents/notes/implemented/architecture/2026-10-29-engine-host-dogfood.md`. The crate's README says which dictionary files a session reads, what to set in a downstream workspace, and the licences of the data compiled in.
8//!
9//! 引擎在运行时读写的每个文件(词库、模型、学习日志、代次目录)的格式、版本检查、产出方与数据许可证见仓库里的 `docs/data-formats.md`;代码注释里的 `data-formats.md §N` 指它的章节。
10
11// 非测试代码的日志一律走 `logging::warn`,嵌入方才换得掉出口(`set_log_sink`);测试和基准测量照旧可以直接打印。
12#![cfg_attr(not(test), deny(clippy::print_stderr))]
13
14pub mod access;
15pub mod assets;
16#[doc(hidden)]
17pub mod backend;
18mod cache;
19pub mod cantonese;
20pub mod diagnostics;
21mod dictionary;
22mod error;
23pub mod format;
24mod handwriting;
25mod helpcode;
26#[doc(hidden)]
27pub mod host;
28mod ime;
29mod japanese;
30mod korean;
31pub use korean::KoreanLayout;
32pub mod language_dictionary;
33mod lattice;
34mod local;
35pub mod logging;
36pub mod multilingual;
37mod nine_key;
38mod nine_key_shuangpin;
39#[doc(hidden)]
40pub mod ordering;
41mod paths;
42mod pinyin;
43mod punctuation;
44mod quanpin;
45mod session;
46mod shared_string;
47mod shuangpin;
48pub mod stroke;
49mod text;
50mod tibetan;
51pub mod time;
52pub mod touch;
53mod types;
54mod user_dictionary;
55pub mod vietnamese;
56#[cfg(all(target_family = "wasm", target_os = "unknown"))]
57#[doc(hidden)]
58pub mod web;
59mod wubi;
60pub mod zhuyin;
61
62pub use access::DictionaryAccess;
63pub use error::{EngineError, ErrorCode, Result};
64#[cfg(not(target_os = "android"))]
65pub use handwriting::handwriting_recognize;
66pub use handwriting::order_handwriting_candidates;
67pub use logging::{set_log_sink, LogSink};
68// 按需下载的 `.gram` 语法模型由宿主侧资源包管理,删除包时需要释放
69// `GramDb::shared` 缓存的内存映射,经这个窄出口暴露给 host-api。
70pub use lattice::octagram;
71pub use nine_key::KeyGrid;
72pub use paths::RuntimePaths;
73pub use pinyin::glide::{GlideKeyboard, GlidePoint};
74pub use punctuation::{BracketMarks, PunctuationMarks, QuoteMarks};
75pub use session::{Clock, Session, SessionOptions, SessionSnapshot};
76pub use types::{
77    autocorrect_type, fuzzy_rule, request_autocorrect_mask, CandidateEdge, CandidateSource,
78    Command, CommandTableEntry, CommandTranslationQuery, EnglishInputOptions, FirstPageRows,
79    FrequencyAdjustmentMode, FrequencyAdjustmentOptions, FuzzyPinyinOptions, KeyResult,
80    LocalInputMode, LocalModeOptions, MentionEntry, MixedExpressiveOptions, NineKeyShuangpinKind,
81    NineKeyShuangpinTable, OnlineInputMode, OnlineQuery, PersonalDictionaryEntry,
82    PersonalDictionaryKind, PluginCommand, PluginCommandQuery, QuickPhraseEntry, SchemeSet,
83    SchemeType, SentenceAssociationOptions, ShuangpinCustomTable, ShuangpinHelpcodeModes,
84    ShuangpinProfileKind, SyllableHelpcode, WordItem, WubiInputOptions, WubiProfileKind,
85    DEFAULT_FIRST_PAGE_ROWS,
86};
87// 辅助码表:`SessionOptions::helpcode_table` 与 `Session::set_helpcode_table` 收的就是它,宿主自己读表(辅助码表插件、没有文件系统的网页)时用这几项。
88pub use helpcode::{load_helpcode_keymap, HelpcodeKeymap, SharedKeymap};
89// 用户自定义的 26 键双拼表(`SessionOptions::shuangpin_custom_profile`)的校验:宿主在把表交给会话之前先校验,不合法就不要传。设置页编辑表用的辅助函数(内置表作起点、不留存的校验)是产品胶水,在 `host` 里。
90pub use shuangpin::custom::{
91    validate_custom_profile as validate_shuangpin_custom_profile,
92    CustomProfileError as ShuangpinCustomProfileError, CustomTablePart as ShuangpinCustomTablePart,
93};
94// 九键、14 键、18 键双拼的表:用户表的校验、按方案取表。取到的 `NineKeyShuangpin` 经 `KeyGrid::NineKeyShuangpin` 交给会话,它的 `key_hints` 给出键面提示。设置页编辑表用的辅助函数同样在 `host` 里。
95pub use nine_key_shuangpin::{
96    nine_key_shuangpin as validate_nine_key_shuangpin_table, resolve as resolve_nine_key_shuangpin,
97    resolve_eighteen_key_shuangpin, resolve_fourteen_key_shuangpin, NineKeyShuangpin,
98    NineKeyShuangpinError, NineKeyShuangpinKeyHint,
99};
100pub use user_dictionary::bundled::{
101    dictionary_table_entries, edit_bundled_dictionary_entry, DictionaryTableEntry,
102    DictionaryTablePage,
103};
104pub use user_dictionary::generation::{prepare_runtime_paths, prepare_runtime_paths_for};
105pub use user_dictionary::journal::quarantine_corrupt_journal;
106pub use user_dictionary::personal::{
107    edit_personal_dictionary, personal_dictionary_entries, validate_personal_dictionary_entry,
108    PersonalDictionaryPage,
109};
110pub use user_dictionary::replay::{replay as replay_user_dictionary, ReplayResult};
111pub use user_dictionary::reset::{reset_learned_data, reset_learned_data_for};
112pub use user_dictionary::state::{
113    dictionary_state_revision, stage_dictionary_state, stream_dictionary_state,
114    DictionaryStateRecord, DEFAULT_MAXIMUM_RECORDS,
115};
116pub use wubi::code::phrase_code as wubi_phrase_code;
117
118pub use local::command::{valid_plugin_argument, EXTENDED_ARGUMENT_SYMBOLS};
119pub use local::date_time::LocalDateTime;
120pub use local::url;
121
122/// Create or migrate an `msime-english.db` to the schema the engine reads. Fixtures without one need it; `prepare_runtime_paths` copies both dictionaries.
123pub fn ensure_english_schema(path: &std::path::Path) -> Result<()> {
124    dictionary::english::ensure_english_schema(path)
125}
126
127/// Write every queued personal-context transition now. Those writes are otherwise delayed about 2 s; call this before reading the journal directly or re-preparing a generation.
128pub fn flush_personal_learning() {
129    user_dictionary::ngram_store::flush_all()
130}
131
132/// Write every queued personal-context transition and stop the background thread that writes them, waiting for it to end. Call before unloading the engine or exiting the process; sessions still work afterwards, and the next transition they record starts the thread again.
133pub fn shutdown() {
134    user_dictionary::ngram_store::shutdown()
135}
136
137/// Drop every cached journal, personal-context and local-mode connection, on every thread (a connection an operation is using closes when that operation ends). Call before deleting or replacing a data directory.
138pub fn close_cached_databases() {
139    user_dictionary::journal::close_cached_journals()
140}
141
142/// Hands the engine the bytes of `msime-japanese.dat` for `path`, the location a Japanese session reads its model from (`RuntimePaths::resource(assets::JAPANESE_MODEL)` or `SessionOptions::japanese_dictionary`), so a host without a file system (the browser) can type Japanese. False, with nothing changed, when the bytes are not a valid model; a later call for the same path replaces the earlier one.
143pub fn preload_japanese_dictionary(path: &std::path::Path, bytes: Box<[u8]>) -> bool {
144    japanese::decoder::JapaneseDictionary::preload(path, bytes)
145}
146
147/// Forgets the model [`preload_japanese_dictionary`] put at `path`; sessions already using it keep it until they end.
148pub fn unload_japanese_dictionary(path: &std::path::Path) {
149    japanese::decoder::JapaneseDictionary::unload(path);
150}
151
152/// Releases the process-level Japanese model cache while sessions that still use a model keep it
153/// alive. Mobile hosts call this from their memory-pressure callback when there is no session
154/// handle to pass to `Session::reset_cache`.
155pub fn release_japanese_dictionary_cache() {
156    japanese::decoder::JapaneseDictionary::release_shared();
157}
158
159/// 放掉进程里为下一个会话留着、没有会话在用的整句联想 n-gram store(连同它的模型和日志连接)。正在用的会话不受影响;之后第一个会话重新读日志。和 [`release_japanese_dictionary_cache`] 一样由宿主的清缓存、内存告警动作调用。
160pub fn release_idle_personal_models() {
161    user_dictionary::ngram_store::release_idle();
162}