gukhanmun_opendict/lib.rs
1// Gukhanmun: Bundled Open Korean Dictionary data for Gukhanmun.
2// Copyright (C) 2026 Hong Minhee
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <https://www.gnu.org/licenses/>.
16
17//! Bundled Open Korean Dictionary (우리말샘) data for Gukhanmun.
18
19#![forbid(unsafe_code)]
20#![deny(missing_docs)]
21
22use std::sync::OnceLock;
23
24use gukhanmun_fst::FstDictionary;
25
26/// Extracts canonical TSV rows from Open Korean Dictionary dumps.
27pub mod extract;
28
29static GENERAL_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/general.gukfst"));
30static NORTH_KOREAN_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/north-korean.gukfst"));
31static DIALECT_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/dialect.gukfst"));
32static ARCHAIC_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/archaic.gukfst"));
33
34static GENERAL: OnceLock<FstDictionary> = OnceLock::new();
35static NORTH_KOREAN: OnceLock<FstDictionary> = OnceLock::new();
36static DIALECT: OnceLock<FstDictionary> = OnceLock::new();
37static ARCHAIC: OnceLock<FstDictionary> = OnceLock::new();
38
39/// Returns the bundled Open Korean Dictionary `일반어` dictionary.
40///
41/// The dictionary is embedded as FST bytes generated from the canonical TSV
42/// snapshot in this crate's `data` directory and is decoded lazily on first
43/// use. It is intentionally separate from [`north_korean`], [`dialect`], and
44/// [`archaic`] so callers can compose exactly the categories they want with
45/// `ChainDictionary`.
46pub fn general() -> &'static FstDictionary {
47 GENERAL.get_or_init(|| decode_static_dictionary(GENERAL_BYTES, "일반어"))
48}
49
50/// Returns the bundled Open Korean Dictionary `북한어` dictionary.
51///
52/// This category carries North Korean readings and orthography such as
53/// `歷史` → `력사`, `來日` → `래일`, and `勞動` → `로동`. It is kept as its own
54/// dictionary so presets can prioritize it above the South Korean standard
55/// dictionary without forcing callers to load the other Open Korean Dictionary
56/// categories.
57pub fn north_korean() -> &'static FstDictionary {
58 NORTH_KOREAN.get_or_init(|| decode_static_dictionary(NORTH_KOREAN_BYTES, "북한어"))
59}
60
61/// Returns the bundled Open Korean Dictionary `방언` dictionary.
62///
63/// The category is exposed independently because dialect entries are useful for
64/// custom pipelines but should not be enabled by the stock South or North
65/// Korean presets.
66pub fn dialect() -> &'static FstDictionary {
67 DIALECT.get_or_init(|| decode_static_dictionary(DIALECT_BYTES, "방언"))
68}
69
70/// Returns the bundled Open Korean Dictionary `옛말` dictionary.
71///
72/// The category is exposed independently because archaic entries are useful for
73/// custom pipelines but should not be enabled by the stock South or North
74/// Korean presets.
75pub fn archaic() -> &'static FstDictionary {
76 ARCHAIC.get_or_init(|| decode_static_dictionary(ARCHAIC_BYTES, "옛말"))
77}
78
79fn decode_static_dictionary(bytes: &'static [u8], category: &'static str) -> FstDictionary {
80 FstDictionary::from_static_bytes(bytes).unwrap_or_else(|error| {
81 panic!("embedded Open Korean Dictionary {category} FST is invalid: {error}")
82 })
83}