Skip to main content

opendict/
lib.rs

1pub mod error;
2pub mod types;
3pub mod stardict;
4pub mod mdict;
5
6use std::path;
7
8pub use error::{Error, Result};
9pub use types::{DictEntry, DictInfo};
10
11pub trait Dictionary {
12    fn lookup(&self, word: &str) -> Result<Option<Vec<DictEntry>>>;
13    fn lookup_synonym(&self, word: &str) -> Result<Option<Vec<DictEntry>>>;
14    fn word_list(&self) -> Vec<&str>;
15    fn word_count(&self) -> usize;
16    fn info(&self) -> &DictInfo;
17    fn search_prefix(&self, prefix: &str, limit: usize) -> Vec<String>;
18}
19
20pub fn open(dir: impl AsRef<path::Path>) -> Result<Box<dyn Dictionary + Send + Sync>> {
21    let dir = dir.as_ref();
22
23    // Try StarDict first (.ifo), then MDict (.mdx)
24    let stardict_err = match stardict::StarDictDictionary::open_dir(dir) {
25        Ok(dict) => return Ok(Box::new(dict)),
26        Err(e) => e,
27    };
28
29    let mdict_err = match mdict::MdictDictionary::open(dir) {
30        Ok(dict) => return Ok(Box::new(dict)),
31        Err(e) => e,
32    };
33
34    // Both formats failed.
35    // If both hit I/O errors (e.g. directory doesn't exist), propagate the I/O error.
36    // Otherwise report both errors so the user can see what went wrong.
37    if matches!((&stardict_err, &mdict_err), (Error::Io(_), Error::Io(_))) {
38        return Err(stardict_err);
39    }
40
41    Err(Error::InvalidFormat(format!(
42        "not a recognized dictionary: StarDict: {}; MDict: {}",
43        stardict_err, mdict_err
44    )))
45}