Skip to main content

mecab_ko_dict/
lib.rs

1//! # mecab-ko-dict
2//!
3//! 한국어 형태소 사전 관리 라이브러리
4//!
5//! ## 주요 기능
6//!
7//! - 바이너리 사전 포맷 (v3.0)
8//! - FST 기반 형태소 검색
9//! - 연접 비용 매트릭스
10//! - 사전 빌더/컴파일러
11//!
12//! ## 예제
13//!
14//! ```rust,ignore
15//! use mecab_ko_dict::dictionary::SystemDictionary;
16//!
17//! let dict = SystemDictionary::load("path/to/dict").unwrap();
18//! let entries = dict.lookup("안녕");
19//! ```
20
21#![warn(missing_docs)]
22#![deny(unsafe_code)]
23#![cfg_attr(feature = "simd", feature(portable_simd))]
24#![allow(
25    clippy::inline_always,
26    clippy::similar_names,
27    clippy::cast_precision_loss,
28    clippy::cast_possible_truncation,
29    clippy::option_if_let_else,
30    clippy::map_unwrap_or,
31    clippy::zero_sized_map_values,
32    clippy::missing_panics_doc,
33    clippy::unwrap_used
34)]
35
36pub mod dictionary;
37pub mod domain;
38pub mod entry_store;
39pub mod file_watcher;
40pub mod hot_reload;
41pub mod lazy_entries;
42pub mod lazy_entries_v3;
43pub mod loader;
44pub mod matrix;
45pub mod string_pool;
46pub mod trie;
47pub mod user_dict;
48
49#[cfg(feature = "hot-reload-v2")]
50pub mod hot_reload_v2;
51
52pub use dictionary::{DictEntry, DictionaryLoader, LoadOptions, SystemDictionary};
53pub use entry_store::{EagerStore, EntryStore, LazyStore};
54pub use error::{DictError, Result};
55pub use file_watcher::{FileEvent, FileWatcher, WatchConfig};
56pub use hot_reload::{
57    DeltaUpdate, DeltaUpdateBuilder, EntryChange, HotReloadDictionary, Version, VersionInfo,
58};
59pub use lazy_entries::LazyEntries;
60pub use loader::{LazyDictionary, LoaderConfig, MmapDictionary};
61pub use matrix::{ConnectionMatrix, DenseMatrix, Matrix, MatrixLoader, MmapMatrix, SparseMatrix};
62pub use string_pool::{ConcurrentStringPool, StringPool, StringPoolStats};
63pub use trie::{MmapTrie, PrefixSearchResult, Trie, TrieBackend, TrieBuilder};
64pub use user_dict::{UserDictionary, UserDictionaryBuilder, UserEntry};
65
66/// 사전 엔트리
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct Entry {
69    /// 표면형
70    pub surface: String,
71    /// 좌문맥 ID
72    pub left_id: u16,
73    /// 우문맥 ID
74    pub right_id: u16,
75    /// 비용
76    pub cost: i16,
77    /// 품사 정보
78    pub feature: String,
79}
80
81/// 사전 인터페이스
82pub trait Dictionary {
83    /// 형태소 검색
84    fn lookup(&self, surface: &str) -> Vec<Entry>;
85
86    /// 연접 비용 조회
87    fn get_connection_cost(&self, left_id: u16, right_id: u16) -> i16;
88}
89
90/// 에러 모듈
91pub mod error {
92    use thiserror::Error;
93
94    /// 사전 에러 타입
95    #[derive(Error, Debug)]
96    pub enum DictError {
97        /// IO 에러
98        #[error("IO error: {0}")]
99        Io(#[from] std::io::Error),
100
101        /// 포맷 에러
102        #[error("Invalid dictionary format: {0}")]
103        Format(String),
104
105        /// 버전 불일치
106        #[error("Version mismatch: expected {expected}, found {found}")]
107        Version {
108            /// 예상 버전
109            expected: u32,
110            /// 실제 버전
111            found: u32,
112        },
113    }
114
115    /// Result 타입 별칭
116    pub type Result<T> = std::result::Result<T, DictError>;
117}
118
119/// 사전 포맷 모듈 (스텁)
120///
121/// 바이너리 사전 포맷 정의
122pub mod format {
123
124    /// 사전 헤더
125    pub struct Header {
126        /// 매직 넘버
127        pub magic: [u8; 4],
128        /// 버전
129        pub version: u32,
130        /// 엔트리 수
131        pub entry_count: u32,
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use super::*;
138
139    #[test]
140    fn test_entry_creation() {
141        let entry = Entry {
142            surface: "안녕".to_string(),
143            left_id: 1,
144            right_id: 1,
145            cost: 100,
146            feature: "NNG,*,T,안녕,*,*,*,*".to_string(),
147        };
148
149        assert_eq!(entry.surface, "안녕");
150    }
151}