Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kanru committed Jan 3, 2024
1 parent 8020dae commit a42617e
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 97 deletions.
15 changes: 11 additions & 4 deletions src/capi/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{
cmp::min,
collections::BTreeMap,
ffi::{c_char, c_int, c_uint, c_ushort, c_void, CStr, CString},
mem,
iter, mem,
ptr::{null, null_mut},
slice, str,
sync::OnceLock,
Expand Down Expand Up @@ -736,7 +736,13 @@ pub extern "C" fn chewing_userphrase_enumerate(ctx: *mut ChewingContext) -> c_in
None => return -1,
};

ctx.userphrase_iter = Some(ctx.editor.user_dict().entries().peekable());
ctx.userphrase_iter = Some(
ctx.editor
.user_dict()
.entries()
.unwrap_or(Box::new(iter::empty()))
.peekable(),
);
0
}

Expand Down Expand Up @@ -923,9 +929,10 @@ pub extern "C" fn chewing_userphrase_lookup(
Some(phrase) => ctx
.editor
.user_dict()
.lookup_phrase(&syllables)
.lookup_all_phrases(&syllables)
.iter()
.any(|ph| ph.as_str() == phrase) as c_int,
None => (ctx.editor.user_dict().lookup_phrase(&syllables).count() > 0) as c_int,
None => ctx.editor.user_dict().lookup_phrase(&syllables).is_some() as c_int,
}
}

Expand Down
16 changes: 8 additions & 8 deletions src/dictionary/cdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::{
fmt::Debug,
fs::File,
io::{self, Write},
iter, mem,
mem,
path::{Path, PathBuf},
};

Expand All @@ -15,7 +15,7 @@ use crate::zhuyin::{Syllable, SyllableSlice};

use super::{
BuildDictionaryError, DictEntries, Dictionary, DictionaryBuilder, DictionaryInfo,
DictionaryUpdateError, Phrase, Phrases,
DictionaryUpdateError, Phrase,
};

mod serde {
Expand Down Expand Up @@ -151,7 +151,7 @@ impl CdbDictionary {
}

impl Dictionary for CdbDictionary {
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Phrases<'_> {
fn lookup_first_n_phrases(&self, syllables: &dyn SyllableSlice, first: usize) -> Vec<Phrase> {
let syllable_bytes = syllables.get_bytes();
let base_bytes = self.base.get(&syllable_bytes);
let base_phrases = match &base_bytes {
Expand All @@ -162,7 +162,7 @@ impl Dictionary for CdbDictionary {
Some(phrases) => phrases.clone().into_iter(),
None => vec![].into_iter(),
};
let phrases = base_phrases
base_phrases
.chain(added_phrases)
.filter(|it| {
let phrase_key = (syllable_bytes.as_slice().into(), it.as_str().into());
Expand All @@ -175,12 +175,12 @@ impl Dictionary for CdbDictionary {
None => it,
}
})
.collect::<Vec<_>>();
Box::new(phrases.into_iter())
.take(first)
.collect()
}

fn entries(&self) -> DictEntries {
Box::new(iter::empty())
fn entries(&self) -> Option<DictEntries> {
None
}

fn about(&self) -> DictionaryInfo {
Expand Down
25 changes: 11 additions & 14 deletions src/dictionary/layered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ use indexmap::IndexSet;

use crate::zhuyin::SyllableSlice;

use super::{
BlockList, DictEntries, Dictionary, DictionaryInfo, DictionaryUpdateError, Phrase, Phrases,
};
use super::{BlockList, DictEntries, Dictionary, DictionaryInfo, DictionaryUpdateError, Phrase};

/// A collection of dictionaries that returns the union of the lookup results.
/// # Examples
Expand Down Expand Up @@ -92,10 +90,10 @@ impl Dictionary for LayeredDictionary {
/// Else
/// Add phrases <- (phrase, freq)
/// ```
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Phrases<'_> {
fn lookup_first_n_phrases(&self, syllables: &dyn SyllableSlice, first: usize) -> Vec<Phrase> {
let (base, layers) = match self.inner.split_first() {
Some(d) => d,
None => return Box::new(std::iter::empty()),
None => return vec![],
};
let mut phrases = IndexSet::with_capacity(128);
phrases.extend(base.lookup_phrase(syllables).map(LookupPhrase));
Expand All @@ -104,17 +102,16 @@ impl Dictionary for LayeredDictionary {
phrases.replace(LookupPhrase(phrase));
}
}
Box::new(
phrases
.into_iter()
.map(|p| p.0)
.filter(|phrase| !self.is_blocked(&phrase.phrase)),
)
phrases
.into_iter()
.map(|p| p.0)
.filter(|phrase| !self.is_blocked(&phrase.phrase))
.take(first)
.collect()
}

fn entries(&self) -> DictEntries {
todo!("entries from all layers")
// Box::new(std::iter::empty())
fn entries(&self) -> Option<DictEntries> {
None
}

fn about(&self) -> DictionaryInfo {
Expand Down
52 changes: 32 additions & 20 deletions src/dictionary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,32 @@ pub type DictEntries = Box<dyn Iterator<Item = (Vec<Syllable>, Phrase)>>;
/// # }
/// ```
pub trait Dictionary: Any + Debug {
/// Returns an iterator to all single syllable words matched by the
/// syllable, if any. The result should use a stable order each time for the
/// same input.
fn lookup_word(&self, syllable: Syllable) -> Phrases<'_> {
self.lookup_phrase(&[syllable])
/// Returns first N phrases matched by the syllables.
///
/// The result should use a stable order each time for the same input.
fn lookup_first_n_phrases(&self, syllables: &dyn SyllableSlice, first: usize) -> Vec<Phrase>;
/// Returns all single syllable words matched by the syllable.
///
/// The result should use a stable order each time for the same input.
fn lookup_word(&self, syllable: Syllable) -> Vec<Phrase> {
self.lookup_all_phrases(&[syllable])
}
/// Returns the first phrase matched by the syllables.
///
/// The result should use a stable order each time for the same input.
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Option<Phrase> {
self.lookup_first_n_phrases(syllables, 1).into_iter().next()
}
/// Returns all phrases matched by the syllables.
///
/// The result should use a stable order each time for the same input.
fn lookup_all_phrases(&self, syllables: &dyn SyllableSlice) -> Vec<Phrase> {
self.lookup_first_n_phrases(syllables, usize::MAX)
}
/// Returns an iterator to all phrases matched by the syllables, if any. The
/// result should use a stable order each time for the same input.
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Phrases<'_>;
/// Returns an iterator to all phrases in the dictionary.
fn entries(&self) -> DictEntries;
///
/// Some dictionary backend does not support this operation.
fn entries(&self) -> Option<DictEntries>;
/// Returns information about the dictionary instance.
fn about(&self) -> DictionaryInfo;
/// Reopens the dictionary if it was changed by a different process
Expand Down Expand Up @@ -386,20 +401,17 @@ pub trait DictionaryBuilder {
}

impl Dictionary for HashMap<Vec<Syllable>, Vec<Phrase>> {
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Phrases<'_> {
fn lookup_first_n_phrases(&self, syllables: &dyn SyllableSlice, first: usize) -> Vec<Phrase> {
let syllables = syllables.as_slice().into_owned();
self.get(&syllables)
.cloned()
.map(|v| Box::new(v.into_iter()) as Phrases<'_>)
.unwrap_or_else(|| Box::new(std::iter::empty()))
let mut phrases = self.get(&syllables).cloned().unwrap_or_default();
phrases.truncate(first);
phrases
}

fn entries(&self) -> DictEntries {
Box::new(
self.clone()
.into_iter()
.flat_map(|(k, v)| v.into_iter().map(move |phrase| (k.clone(), phrase.clone()))),
)
fn entries(&self) -> Option<DictEntries> {
Some(Box::new(self.clone().into_iter().flat_map(|(k, v)| {
v.into_iter().map(move |phrase| (k.clone(), phrase.clone()))
})))
}

fn about(&self) -> DictionaryInfo {
Expand Down
45 changes: 20 additions & 25 deletions src/dictionary/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::zhuyin::{Syllable, SyllableSlice};

use super::{
BuildDictionaryError, DictEntries, Dictionary, DictionaryBuilder, DictionaryInfo,
DictionaryUpdateError, Phrase, Phrases,
DictionaryUpdateError, Phrase,
};

/// TODO: doc
Expand Down Expand Up @@ -269,7 +269,7 @@ impl From<RusqliteError> for DictionaryUpdateError {
}

impl Dictionary for SqliteDictionary {
fn lookup_phrase(&self, syllables: &dyn SyllableSlice) -> Phrases<'static> {
fn lookup_first_n_phrases(&self, syllables: &dyn SyllableSlice, first: usize) -> Vec<Phrase> {
let syllables_bytes = syllables.get_bytes();
let mut stmt = self
.conn
Expand All @@ -283,32 +283,30 @@ impl Dictionary for SqliteDictionary {
ORDER BY sort_id ASC, max(freq, coalesce(user_freq, 0)) DESC, phrase DESC",
)
.expect("SQL error");
Box::new(
stmt.query_map([syllables_bytes], |row| {
let (phrase, freq, time): (String, _, _) = row.try_into()?;
let mut phrase = Phrase::new(phrase, freq);
if let Some(last_used) = time {
phrase = phrase.with_time(last_used);
}
Ok(phrase)
})
.unwrap()
.map(|r| r.unwrap())
.collect::<Vec<_>>()
.into_iter(),
)
stmt.query_map([syllables_bytes], |row| {
let (phrase, freq, time): (String, _, _) = row.try_into()?;
let mut phrase = Phrase::new(phrase, freq);
if let Some(last_used) = time {
phrase = phrase.with_time(last_used);
}
Ok(phrase)
})
.unwrap()
.map(|r| r.unwrap())
.take(first)
.collect()
}

// FIXME too many clone
fn entries(&self) -> DictEntries {
fn entries(&self) -> Option<DictEntries> {
let mut stmt = self
.conn
.prepare_cached(
"SELECT syllables, phrase, max(freq, coalesce(user_freq, 0)), time
FROM dictionary_v1 LEFT JOIN userphrase_v2 ON userphrase_id = id",
)
.expect("SQL error");
Box::new(
Some(Box::new(
stmt.query_map([], |row| {
let (syllables_bytes, phrase, freq, time): (Vec<u8>, String, _, _) =
row.try_into()?;
Expand All @@ -331,7 +329,7 @@ impl Dictionary for SqliteDictionary {
.map(|r| r.unwrap())
.collect::<Vec<_>>()
.into_iter(),
)
))
}

fn about(&self) -> DictionaryInfo {
Expand Down Expand Up @@ -599,11 +597,10 @@ mod tests {
Phrase::new("策士", 9318).with_time(186613),
Phrase::new("測試", 9318).with_time(186613)
],
dict.lookup_phrase(&[
dict.lookup_all_phrases(&[
syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4],
syl![Bopomofo::SH, Bopomofo::TONE4],
])
.collect::<Vec<_>>()
);
}

Expand All @@ -621,11 +618,10 @@ mod tests {
)?;
assert_eq!(
vec![Phrase::new("測試", 9900).with_time(0)],
dict.lookup_phrase(&[
dict.lookup_all_phrases(&[
syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4],
syl![Bopomofo::SH, Bopomofo::TONE4],
])
.collect::<Vec<_>>()
);
Ok(())
}
Expand All @@ -641,11 +637,10 @@ mod tests {
dict.update_phrase(&syllables, ("測試", 9318).into(), 9900, 0)?;
assert_eq!(
vec![Phrase::new("測試", 9900).with_time(0)],
dict.lookup_phrase(&[
dict.lookup_all_phrases(&[
syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4],
syl![Bopomofo::SH, Bopomofo::TONE4],
])
.collect::<Vec<_>>()
);
Ok(())
}
Expand Down
Loading

0 comments on commit a42617e

Please sign in to comment.