sudachi/dic/word_info/
data.rs1use crate::dic::lexicon::strings::StringPointer;
18use crate::dic::strings_cache::StringsCache;
19use crate::dic::subset::InfoSubset;
20use crate::dic::word_id::{DictId, WordId, WordRef};
21use crate::dic::word_info::WordInfoRawData;
22use crate::dic::LexiconAccess;
23
24#[derive(Clone, Debug, Default)]
26#[repr(transparent)]
27pub struct WordInfoRefData {
28 raw: WordInfoRawData,
29}
30
31impl WordInfoRefData {
32 pub fn from_raw(raw: WordInfoRawData) -> Self {
33 WordInfoRefData { raw }
34 }
35
36 pub fn headword_strptr(&self) -> StringPointer {
37 self.raw.headword_strptr
38 }
39
40 pub fn resolve(
42 self,
43 dict_id: DictId,
44 num_system_pos: usize,
45 pos_offsets: &[usize],
46 subset: InfoSubset,
47 ) -> WordInfoData {
48 let mut raw = self.raw;
49
50 if subset.contains(InfoSubset::POS_ID) {
51 let pos_id = raw.pos_id as usize;
52 if dict_id.is_user() && pos_id >= num_system_pos {
53 let pos_id_diff = pos_id - num_system_pos;
55 let pos_offset = pos_offsets[dict_id.as_raw() as usize];
56
57 raw.pos_id = (pos_offset + pos_id_diff) as i16;
58 }
59 }
60
61 if subset.contains(InfoSubset::NORMALIZED_FORM) {
62 raw.normalized_form = WordRef::resolve_raw(raw.normalized_form, dict_id);
63 }
64 if subset.contains(InfoSubset::DICTIONARY_FORM) {
65 raw.dictionary_form = WordRef::resolve_raw(raw.dictionary_form, dict_id);
66 }
67
68 if subset.contains(InfoSubset::SPLIT_C) {
69 Self::resolve_ref_vec(&mut raw.c_unit_split, dict_id);
70 }
71 if subset.contains(InfoSubset::SPLIT_B) {
72 Self::resolve_ref_vec(&mut raw.b_unit_split, dict_id);
73 }
74 if subset.contains(InfoSubset::SPLIT_A) {
75 Self::resolve_ref_vec(&mut raw.a_unit_split, dict_id);
76 }
77 if subset.contains(InfoSubset::WORD_STRUCTURE) {
78 Self::resolve_ref_vec(&mut raw.word_structure, dict_id);
79 }
80
81 WordInfoData::from_resolved(raw)
82 }
83
84 fn resolve_ref_vec(refs: &mut [u32], dict_id: DictId) {
85 for raw in refs.iter_mut() {
86 *raw = WordRef::resolve_raw(*raw, dict_id);
87 }
88 }
89}
90
91#[derive(Clone, Debug, Default)]
93#[repr(transparent)]
94pub struct WordInfoData {
95 raw: WordInfoRawData,
96}
97
98impl WordInfoData {
99 pub fn from_resolved(raw: WordInfoRawData) -> Self {
101 WordInfoData { raw }
102 }
103
104 pub fn new_oov(pos_id: i16, index_form_length: i16) -> Self {
105 Self {
106 raw: WordInfoRawData {
107 pos_id,
108 index_form_length,
109 ..Default::default()
110 },
111 }
112 }
113
114 pub fn pos_id(&self) -> u16 {
115 self.raw.pos_id as u16
116 }
117
118 pub fn index_form_length(&self) -> usize {
119 self.raw.index_form_length as usize
120 }
121
122 pub fn headword_strptr(&self) -> StringPointer {
123 self.raw.headword_strptr
124 }
125
126 pub fn reading_form_strptr(&self) -> StringPointer {
127 self.raw.reading_form_strptr
128 }
129
130 pub fn normalized_form_word_id(&self) -> WordId {
131 WordId::from_raw(self.raw.normalized_form)
132 }
133
134 pub fn dictionary_form_word_id(&self) -> WordId {
135 WordId::from_raw(self.raw.dictionary_form)
136 }
137
138 pub fn c_unit_split(&self) -> &[WordId] {
139 Self::as_word_id_slice(&self.raw.c_unit_split)
140 }
141
142 pub fn b_unit_split(&self) -> &[WordId] {
143 Self::as_word_id_slice(&self.raw.b_unit_split)
144 }
145
146 pub fn a_unit_split(&self) -> &[WordId] {
147 Self::as_word_id_slice(&self.raw.a_unit_split)
148 }
149
150 pub fn word_structure(&self) -> &[WordId] {
151 Self::as_word_id_slice(&self.raw.word_structure)
152 }
153
154 fn as_word_id_slice(raw_slice: &[u32]) -> &[WordId] {
155 if raw_slice.is_empty() {
156 &[]
157 } else {
158 unsafe {
160 std::slice::from_raw_parts(raw_slice.as_ptr() as *const WordId, raw_slice.len())
161 }
162 }
163 }
164
165 pub fn synonym_group_ids(&self) -> &[i32] {
166 &self.raw.synonym_group_ids
167 }
168
169 pub fn user_data(&self) -> &str {
170 &self.raw.user_data
171 }
172}
173
174pub trait WordInfoResolver: LexiconAccess {}
177
178impl<T: LexiconAccess> WordInfoResolver for T {}
179
180#[derive(Clone)]
186pub struct WordInfo {
187 data: WordInfoData,
188
189 word_id: WordId,
191
192 strings: StringsCache,
195}
196
197impl WordInfo {
198 pub fn new(data: WordInfoData, word_id: WordId) -> Self {
199 WordInfo {
200 data,
201 word_id,
202 strings: StringsCache::new(),
203 }
204 }
205
206 pub fn new_oov(pos_id: u16, index_form_length: i16, word_id: WordId, headword: String) -> Self {
207 Self {
208 data: WordInfoData::new_oov(pos_id as i16, index_form_length),
209 word_id,
210 strings: StringsCache::new_with_single_string(headword),
211 }
212 }
213
214 pub fn new_with_strings(
215 pos_id: i16,
216 index_form_length: i16,
217 word_id: WordId,
218 headword: String,
219 reading: String,
220 normalized_form: String,
221 dictionary_form: String,
222 ) -> Self {
223 WordInfo {
224 data: WordInfoData::new_oov(pos_id, index_form_length),
225 word_id,
226 strings: StringsCache::new_with_strings(
227 headword,
228 reading,
229 normalized_form,
230 dictionary_form,
231 ),
232 }
233 }
234
235 pub fn headword_strptr(&self) -> StringPointer {
236 self.data.headword_strptr()
238 }
239
240 pub fn index_form_length(&self) -> usize {
241 self.data.index_form_length()
242 }
243
244 pub fn pos_id(&self) -> u16 {
245 self.data.pos_id()
246 }
247
248 pub fn headword<T: WordInfoResolver>(&self, resolver: T) -> &str {
249 self.strings.headword(&resolver, &self.data, self.word_id)
250 }
251
252 pub fn reading_form<T: WordInfoResolver>(&self, resolver: T) -> &str {
253 self.strings.reading(&resolver, &self.data, self.word_id)
254 }
255
256 pub fn normalized_form<T: WordInfoResolver>(&self, resolver: T) -> &str {
257 self.strings
258 .normalized_form(&resolver, &self.data, self.word_id)
259 }
260
261 pub fn dictionary_form<T: WordInfoResolver>(&self, resolver: T) -> &str {
262 self.strings
263 .dictionary_form(&resolver, &self.data, self.word_id)
264 }
265
266 pub fn a_unit_split(&self) -> &[WordId] {
267 self.data.a_unit_split()
268 }
269
270 pub fn b_unit_split(&self) -> &[WordId] {
271 self.data.b_unit_split()
272 }
273
274 pub fn c_unit_split(&self) -> &[WordId] {
275 self.data.c_unit_split()
276 }
277
278 pub fn word_structure(&self) -> &[WordId] {
279 self.data.word_structure()
280 }
281
282 pub fn synonym_group_ids(&self) -> &[i32] {
283 self.data.synonym_group_ids()
284 }
285
286 pub fn user_data(&self) -> &str {
287 self.data.user_data()
288 }
289
290 pub fn borrow_data(&self) -> &WordInfoData {
291 &self.data
292 }
293}
294
295impl From<WordInfo> for WordInfoData {
296 fn from(info: WordInfo) -> Self {
297 info.data
298 }
299}