sudachi/dic/
dictionary_access.rs1use std::collections::HashMap;
18use std::ops::Deref;
19
20use crate::analysis::morpheme::SingleMorpheme;
21use crate::dic::description::Description;
22use crate::dic::grammar::Grammar;
23use crate::dic::lexicon_set::LexiconSet;
24use crate::dic::subset::InfoSubset;
25use crate::error::SudachiResult;
26use crate::input_text::InputBuffer;
27use crate::plugin::input_text::InputTextPlugin;
28use crate::plugin::oov::OovProviderPlugin;
29use crate::plugin::path_rewrite::PathRewritePlugin;
30
31pub trait LexiconAccess {
32 fn lexicon(&self) -> &LexiconSet<'_>;
33}
34
35impl<T> LexiconAccess for T
36where
37 T: Deref,
38 <T as Deref>::Target: LexiconAccess,
39{
40 fn lexicon(&self) -> &LexiconSet<'_> {
41 <T as Deref>::deref(self).lexicon()
42 }
43}
44
45pub trait DescriptionAccess {
46 fn description(&self) -> &Description;
47}
48
49impl<T> DescriptionAccess for T
50where
51 T: Deref,
52 <T as Deref>::Target: DescriptionAccess,
53{
54 fn description(&self) -> &Description {
55 <T as Deref>::deref(self).description()
56 }
57}
58
59pub trait ReferenceIdAccess {
61 fn reference_ids(&self) -> HashMap<u32, String>;
62}
63
64impl<T> ReferenceIdAccess for T
65where
66 T: Deref,
67 <T as Deref>::Target: ReferenceIdAccess,
68{
69 fn reference_ids(&self) -> HashMap<u32, String> {
70 <T as Deref>::deref(self).reference_ids()
71 }
72}
73
74pub trait DictionaryAccess: LexiconAccess {
76 fn grammar(&self) -> &Grammar<'_>;
77
78 fn input_text_plugins(&self) -> &[Box<dyn InputTextPlugin + Sync + Send>];
79 fn oov_provider_plugins(&self) -> &[Box<dyn OovProviderPlugin + Sync + Send>];
80 fn path_rewrite_plugins(&self) -> &[Box<dyn PathRewritePlugin + Sync + Send>];
81}
82
83impl<T> DictionaryAccess for T
84where
85 T: Deref,
86 <T as Deref>::Target: DictionaryAccess,
87{
88 fn grammar(&self) -> &Grammar<'_> {
89 <T as Deref>::deref(self).grammar()
90 }
91
92 fn input_text_plugins(&self) -> &[Box<dyn InputTextPlugin + Sync + Send>] {
93 <T as Deref>::deref(self).input_text_plugins()
94 }
95
96 fn oov_provider_plugins(&self) -> &[Box<dyn OovProviderPlugin + Sync + Send>] {
97 <T as Deref>::deref(self).oov_provider_plugins()
98 }
99
100 fn path_rewrite_plugins(&self) -> &[Box<dyn PathRewritePlugin + Sync + Send>] {
101 <T as Deref>::deref(self).path_rewrite_plugins()
102 }
103}
104
105pub(crate) fn normalize_input_text<D: DictionaryAccess + ?Sized>(
107 dict: &D,
108 text: &str,
109 buffer: &mut InputBuffer,
110) -> SudachiResult<()> {
111 buffer.reset().push_str(text);
112 buffer.start_build()?;
113 for plugin in dict.input_text_plugins() {
114 plugin.rewrite(buffer)?;
115 }
116 buffer.build(dict.grammar())
117}
118
119pub(crate) fn rewrite_input_text_for_comparison<D: DictionaryAccess + ?Sized>(
125 dict: &D,
126 text: &str,
127 buffer: &mut InputBuffer,
128) -> SudachiResult<()> {
129 buffer.reset().push_str(text);
130 buffer.start_build()?;
131 for plugin in dict.input_text_plugins() {
132 plugin.rewrite(buffer)?;
133 }
134 Ok(())
135}
136
137pub(crate) fn lookup_all_entries<D>(
139 dict: D,
140 surface: &str,
141 subset: InfoSubset,
142) -> SudachiResult<Vec<SingleMorpheme<D>>>
143where
144 D: DictionaryAccess + Clone,
145{
146 let mut query_buffer = InputBuffer::new();
147 rewrite_input_text_for_comparison(&dict, surface, &mut query_buffer)?;
148 let query = query_buffer.current().to_owned();
149 let mut entry_buffer = InputBuffer::new();
150 let mut result = Vec::new();
151
152 for word_id in dict.lexicon().word_ids() {
153 let word_id = word_id?;
154 let word_info = dict
155 .lexicon()
156 .get_word_info_subset(word_id, InfoSubset::HEADWORD)?;
157 rewrite_input_text_for_comparison(
158 &dict,
159 word_info.headword(dict.lexicon()),
160 &mut entry_buffer,
161 )?;
162 if entry_buffer.current() == query {
163 result.push(SingleMorpheme::from_word_id(dict.clone(), word_id, subset)?);
164 }
165 }
166
167 Ok(result)
168}