igo/dictionary/
unknown.rs

1use std::io::{self};
2use std::cmp::min;
3use crate::dictionary::{self, CharCategory, WordDic, SPACE_CHAR};
4use crate::Utf16Str;
5use crate::util::DirLike;
6
7
8/// 未知語の検索を行う
9pub struct Unknown {
10    /// 文字カテゴリ管理クラス
11    pub category: CharCategory,
12    /// 文字カテゴリがSPACEの文字のID
13    pub space_id: i32
14}
15
16impl Unknown {
17    pub fn new(dir: &mut dyn DirLike) -> io::Result<Unknown> {
18        let category = CharCategory::new(dir)?;
19        Ok(Unknown {
20            space_id: category.category(SPACE_CHAR).id, // NOTE: ' 'の文字カテゴリはSPACEに予約されている
21            category
22        })
23    }
24
25    pub fn search(&self, text: &Utf16Str, start: usize, wdic: &WordDic,
26                  callback: &mut dyn dictionary::Callback) {
27        let ch = text[start];
28        let ct = self.category.category(ch);
29
30        if !callback.is_empty() && !ct.invoke {
31            return;
32        }
33
34        let is_space = ct.id == self.space_id;
35        let limit = min(text.len(), (ct.length as usize) + start);
36        for i in start..limit {
37            wdic.search_from_trie_id(ct.id, start, (i - start) + 1, is_space, callback);
38            if (i + 1) != limit && !self.category.is_compatible(ch, text[i + 1]) {
39                return;
40            }
41        }
42
43        if ct.group && limit < text.len() {
44            for i in limit..text.len() {
45                if !self.category.is_compatible(ch, text[i]) {
46                    wdic.search_from_trie_id(ct.id, start, i - start, is_space, callback);
47                    return;
48                }
49            }
50            wdic.search_from_trie_id(ct.id, start, text.len() - start, is_space, callback);
51        }
52    }
53}