Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ What's New in libchewing (unreleased)
and without the break word.
- rust: simplified dictionary API.
- rust: logging now depends on tracing and tracing-subscriber.
- rust: the DictionaryMut trait is merged back to the Dictionary trait.

* Dictionary
- Default symbols.dat now includes commonly used emojis.
Expand Down
6 changes: 2 additions & 4 deletions src/conversion/chewing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ use std::{

use tracing::trace;

use super::{Composition, ConversionEngine, Gap, Interval, Symbol};
use super::{Composition, ConversionEngine, Gap, Interval, Outcome, Symbol};
use crate::{
conversion::Outcome,
dictionary::{Dictionary, LookupStrategy, Phrase},
zhuyin::Syllable,
};
Expand Down Expand Up @@ -681,8 +680,7 @@ mod tests {
#[test]
fn convert_zero_length_entry() {
let mut dict = test_dictionary();
let dict_mut = dict.as_dict_mut().unwrap();
dict_mut.add_phrase(&[], ("", 0).into()).unwrap();
dict.add_phrase(&[], ("", 0).into()).unwrap();
let engine = ChewingEngine::new();
let mut composition = Composition::new();
for sym in [
Expand Down
4 changes: 2 additions & 2 deletions src/conversion/fuzzy.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{ChewingEngine, ConversionEngine};
use crate::{conversion::Outcome, dictionary::LookupStrategy};
use super::{ChewingEngine, ConversionEngine, Outcome};
use crate::dictionary::LookupStrategy;

/// Same conversion method as Chewing but uses fuzzy phrase search.
#[derive(Debug, Default)]
Expand Down
10 changes: 5 additions & 5 deletions src/conversion/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
//! Algorithms to convert syllables to Chinese characters.

mod chewing;
mod fuzzy;
mod simple;
mod symbol;

use std::{
cmp::{max, min},
fmt::Debug,
Expand All @@ -16,6 +11,11 @@ pub use self::simple::SimpleEngine;
pub(crate) use self::symbol::{full_width_symbol_input, special_symbol_input};
use crate::{dictionary::Dictionary, zhuyin::Syllable};

mod chewing;
mod fuzzy;
mod simple;
mod symbol;

/// Converts a composition buffer to list of intervals.
///
/// [`Composition`] contains all user inputs and selection information. The out
Expand Down
6 changes: 2 additions & 4 deletions src/conversion/simple.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::{Composition, ConversionEngine, Interval};
use crate::{
conversion::Outcome,
conversion::{Composition, ConversionEngine, Interval, Outcome},
dictionary::{Dictionary, LookupStrategy},
};

Expand Down Expand Up @@ -136,8 +135,7 @@ mod tests {
#[test]
fn convert_zero_length_entry() {
let mut dict = test_dictionary();
let dict_mut = dict.as_dict_mut().unwrap();
dict_mut.add_phrase(&[], ("", 0).into()).unwrap();
dict.add_phrase(&[], ("", 0).into()).unwrap();
let engine = SimpleEngine::new();
let mut composition = Composition::new();
for sym in [
Expand Down
56 changes: 13 additions & 43 deletions src/dictionary/layered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use std::{

use tracing::error;

use super::{
Dictionary, DictionaryInfo, DictionaryMut, Entries, LookupStrategy, Phrase,
UpdateDictionaryError,
};
use super::{Dictionary, DictionaryInfo, Entries, LookupStrategy, Phrase, UpdateDictionaryError};
use crate::zhuyin::Syllable;

/// A collection of dictionaries that returns the union of the lookup results.
Expand Down Expand Up @@ -143,26 +140,12 @@ impl Dictionary for Layered {
None
}

fn as_dict_mut(&mut self) -> Option<&mut dyn DictionaryMut> {
self.user_dict.as_dict_mut()
}
}

impl DictionaryMut for Layered {
fn reopen(&mut self) -> Result<(), UpdateDictionaryError> {
if let Some(writer) = self.user_dict.as_dict_mut() {
writer.reopen()
} else {
Ok(())
}
self.user_dict.reopen()
}

fn flush(&mut self) -> Result<(), UpdateDictionaryError> {
if let Some(writer) = self.user_dict.as_dict_mut() {
writer.flush()
} else {
Ok(())
}
self.user_dict.flush()
}

fn add_phrase(
Expand All @@ -174,11 +157,7 @@ impl DictionaryMut for Layered {
error!("BUG! added phrase is empty");
return Ok(());
}
if let Some(writer) = self.user_dict.as_dict_mut() {
writer.add_phrase(syllables, phrase)
} else {
Ok(())
}
self.user_dict.add_phrase(syllables, phrase)
}

fn update_phrase(
Expand All @@ -192,23 +171,16 @@ impl DictionaryMut for Layered {
error!("BUG! added phrase is empty");
return Ok(());
}
if let Some(writer) = self.user_dict.as_dict_mut() {
writer.update_phrase(syllables, phrase, user_freq, time)
} else {
Ok(())
}
self.user_dict
.update_phrase(syllables, phrase, user_freq, time)
}

fn remove_phrase(
&mut self,
syllables: &[Syllable],
phrase_str: &str,
) -> Result<(), UpdateDictionaryError> {
if let Some(writer) = self.user_dict.as_dict_mut() {
writer.remove_phrase(syllables, phrase_str)
} else {
Ok(())
}
self.user_dict.remove_phrase(syllables, phrase_str)
}
}

Expand All @@ -222,8 +194,7 @@ mod tests {
use super::Layered;
use crate::{
dictionary::{
Dictionary, DictionaryBuilder, DictionaryMut, LookupStrategy, Phrase, Trie, TrieBuf,
TrieBuilder,
Dictionary, DictionaryBuilder, LookupStrategy, Phrase, Trie, TrieBuf, TrieBuilder,
},
syl,
zhuyin::Bopomofo,
Expand Down Expand Up @@ -354,15 +325,14 @@ mod tests {
),
);
let _ = dict.about();
assert!(dict.as_dict_mut().is_none());
assert!(dict.reopen().is_ok());
assert!(dict.flush().is_ok());
assert!(dict.reopen().is_err());
assert!(dict.flush().is_err());
assert!(
dict.add_phrase(
&[syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]],
("冊", 100).into()
)
.is_ok()
.is_err()
);
assert!(
dict.update_phrase(
Expand All @@ -371,11 +341,11 @@ mod tests {
0,
0,
)
.is_ok()
.is_err()
);
assert!(
dict.remove_phrase(&[syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]], "冊")
.is_ok()
.is_err()
);
Ok(())
}
Expand Down
8 changes: 0 additions & 8 deletions src/dictionary/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,10 @@ impl UserDictionaryLoader {
let freq = phrase.freq();
let last_used = phrase.last_used().unwrap_or_default();
fresh_dict
.as_dict_mut()
.unwrap()
.update_phrase(&syllables, phrase, freq, last_used)
.map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e)))?;
}
fresh_dict
.as_dict_mut()
.unwrap()
.flush()
.map_err(|e| io::Error::new(io::ErrorKind::Other, Box::new(e)))?;
}
Expand All @@ -197,14 +193,10 @@ impl UserDictionaryLoader {
let freq = phrase.freq();
let last_used = phrase.last_used().unwrap_or_default();
fresh_dict
.as_dict_mut()
.unwrap()
.update_phrase(&syllables, phrase, freq, last_used)
.map_err(|e| io::Error::other(Box::new(e)))?;
}
fresh_dict
.as_dict_mut()
.unwrap()
.flush()
.map_err(|e| io::Error::other(Box::new(e)))?;
}
Expand Down
61 changes: 31 additions & 30 deletions src/dictionary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@ use std::{
path::Path,
};

pub use layered::Layered;
pub use loader::{
pub use self::layered::Layered;
pub use self::loader::{
DEFAULT_DICT_NAMES, LoadDictionaryError, SingleDictionaryLoader, SystemDictionaryLoader,
UserDictionaryLoader,
};
#[cfg(feature = "sqlite")]
pub use sqlite::{SqliteDictionary, SqliteDictionaryBuilder, SqliteDictionaryError};
pub use trie::{Trie, TrieBuilder, TrieOpenOptions, TrieStatistics};
pub use trie_buf::TrieBuf;

pub use self::sqlite::{SqliteDictionary, SqliteDictionaryBuilder, SqliteDictionaryError};
pub use self::trie::{Trie, TrieBuilder, TrieOpenOptions, TrieStatistics};
pub use self::trie_buf::TrieBuf;
use crate::zhuyin::Syllable;

mod layered;
Expand Down Expand Up @@ -323,7 +322,7 @@ pub enum LookupStrategy {
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
///
/// use chewing::{dictionary::{Dictionary, DictionaryMut, LookupStrategy, TrieBuf}, syl, zhuyin::Bopomofo};
/// use chewing::{dictionary::{Dictionary, LookupStrategy, TrieBuf}, syl, zhuyin::Bopomofo};
///
/// let mut dict = TrieBuf::new_in_memory();
/// dict.add_phrase(&[syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]], ("測", 100).into())?;
Expand All @@ -348,21 +347,20 @@ pub trait Dictionary: Debug {
fn about(&self) -> DictionaryInfo;
/// Returns the dictionary file path if it's backed by a file.
fn path(&self) -> Option<&Path>;
fn as_dict_mut(&mut self) -> Option<&mut dyn DictionaryMut>;
}

/// An interface for updating dictionaries.
pub trait DictionaryMut: Debug {
/// Reopens the dictionary if it was changed by a different process
///
/// It should not fail if the dictionary is read-only or able to sync across
/// processes automatically.
fn reopen(&mut self) -> Result<(), UpdateDictionaryError>;
fn reopen(&mut self) -> Result<(), UpdateDictionaryError> {
Err(UpdateDictionaryError { source: None })
}
/// Flushes all the changes back to the filesystem
///
/// The change made to the dictionary might not be persisted without
/// calling this method.
fn flush(&mut self) -> Result<(), UpdateDictionaryError>;
fn flush(&mut self) -> Result<(), UpdateDictionaryError> {
Err(UpdateDictionaryError { source: None })
}
/// An method for updating dictionaries.
///
/// For more about the concept of dictionaries generally, please see the
Expand All @@ -373,7 +371,7 @@ pub trait DictionaryMut: Debug {
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
///
/// use chewing::{dictionary::{DictionaryMut, TrieBuf}, syl, zhuyin::Bopomofo};
/// use chewing::{dictionary::{Dictionary, TrieBuf}, syl, zhuyin::Bopomofo};
///
/// let mut dict = TrieBuf::new_in_memory();
/// dict.add_phrase(&[syl![Bopomofo::C, Bopomofo::E, Bopomofo::TONE4]], ("測", 100).into())?;
Expand All @@ -383,25 +381,29 @@ pub trait DictionaryMut: Debug {
/// TODO: doc
fn add_phrase(
&mut self,
syllables: &[Syllable],
phrase: Phrase,
) -> Result<(), UpdateDictionaryError>;

_syllables: &[Syllable],
_phrase: Phrase,
) -> Result<(), UpdateDictionaryError> {
Err(UpdateDictionaryError { source: None })
}
/// TODO: doc
fn update_phrase(
&mut self,
syllables: &[Syllable],
phrase: Phrase,
user_freq: u32,
time: u64,
) -> Result<(), UpdateDictionaryError>;

_syllables: &[Syllable],
_phrase: Phrase,
_user_freq: u32,
_time: u64,
) -> Result<(), UpdateDictionaryError> {
Err(UpdateDictionaryError { source: None })
}
/// TODO: doc
fn remove_phrase(
&mut self,
syllables: &[Syllable],
phrase_str: &str,
) -> Result<(), UpdateDictionaryError>;
_syllables: &[Syllable],
_phrase_str: &str,
) -> Result<(), UpdateDictionaryError> {
Err(UpdateDictionaryError { source: None })
}
}

/// Errors during dictionary construction.
Expand Down Expand Up @@ -447,12 +449,11 @@ pub trait DictionaryBuilder {

#[cfg(test)]
mod tests {
use crate::dictionary::{Dictionary, DictionaryBuilder, DictionaryMut};
use crate::dictionary::{Dictionary, DictionaryBuilder};

#[test]
fn ensure_object_safe() {
const _: Option<&dyn Dictionary> = None;
const _: Option<&dyn DictionaryMut> = None;
const _: Option<&dyn DictionaryBuilder> = None;
}
}
Loading
Loading