Skip to main content

lindera_dictionary/
macros.rs

1//! Shared macros for the per-dictionary crates (`lindera-ipadic`,
2//! `lindera-ko-dic`, `lindera-unidic`, `lindera-cc-cedict`, `lindera-jieba`,
3//! `lindera-ipadic-neologd`).
4//!
5//! Each of those crates' `embedded` module used to contain ~90 lines of
6//! identical boilerplate that differed only in the dictionary subdirectory
7//! name and the loader struct name. [`embedded_dictionary!`] generates that
8//! boilerplate from those two inputs.
9
10/// Generates the embedded-dictionary loader for a dictionary crate.
11///
12/// The dictionary data is baked into the binary with `include_bytes!`,
13/// reading from the `LINDERA_WORKDIR` directory populated by the crate's
14/// build script.
15///
16/// * `$dir` — the dictionary subdirectory inside `LINDERA_WORKDIR`
17///   (e.g. `"/lindera-ipadic"`).
18/// * `$loader` — the public loader struct name (e.g. `EmbeddedIPADICLoader`).
19///
20/// # Example
21///
22/// ```ignore
23/// lindera_dictionary::embedded_dictionary!("/lindera-ipadic", EmbeddedIPADICLoader);
24/// ```
25#[macro_export]
26macro_rules! embedded_dictionary {
27    ($dir:literal, $loader:ident) => {
28        const CHAR_DEFINITION_DATA: &[u8] =
29            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/char_def.bin"));
30        const CONNECTION_DATA: &[u8] =
31            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/matrix.mtx"));
32        const DA_DATA: &[u8] = include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/dict.da"));
33        const VALS_DATA: &[u8] =
34            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/dict.vals"));
35        const UNKNOWN_DATA: &[u8] =
36            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/unk.bin"));
37        const WORDS_IDX_DATA: &[u8] =
38            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/dict.wordsidx"));
39        const WORDS_DATA: &[u8] =
40            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/dict.words"));
41        const METADATA_DATA: &[u8] =
42            include_bytes!(concat!(env!("LINDERA_WORKDIR"), $dir, "/metadata.json"));
43
44        /// Loads the embedded dictionary from data baked into the binary.
45        pub fn load() -> $crate::LinderaResult<$crate::dictionary::Dictionary> {
46            let metadata = $crate::dictionary::metadata::Metadata::load(METADATA_DATA)?;
47            let prefix_dictionary = $crate::dictionary::prefix_dictionary::PrefixDictionary::load(
48                DA_DATA,
49                VALS_DATA,
50                WORDS_IDX_DATA,
51                WORDS_DATA,
52                true,
53            )?;
54            let connection_cost_matrix =
55                $crate::dictionary::connection_cost_matrix::ConnectionCostMatrix::load(
56                    CONNECTION_DATA,
57                )?;
58            let character_definition =
59                $crate::dictionary::character_definition::CharacterDefinition::load(
60                    CHAR_DEFINITION_DATA,
61                )?;
62            let unknown_dictionary =
63                $crate::dictionary::unknown_dictionary::UnknownDictionary::load(UNKNOWN_DATA)?;
64
65            Ok($crate::dictionary::Dictionary {
66                prefix_dictionary,
67                connection_cost_matrix,
68                character_definition,
69                unknown_dictionary,
70                metadata,
71            })
72        }
73
74        /// Loader that returns the dictionary embedded in the binary.
75        pub struct $loader;
76
77        impl Default for $loader {
78            fn default() -> Self {
79                Self::new()
80            }
81        }
82
83        impl $loader {
84            pub fn new() -> Self {
85                Self
86            }
87        }
88
89        impl $crate::loader::DictionaryLoader for $loader {
90            fn load(&self) -> $crate::LinderaResult<$crate::dictionary::Dictionary> {
91                load()
92            }
93        }
94    };
95}