use std::path::Path;
use svara::phoneme::Phoneme;
use super::PronunciationDict;
use super::entry::DictEntry;
use super::format::binary;
use crate::error::{Result, ShabdakoshError};
pub struct LazyDict {
dict: PronunciationDict,
_mmap: memmap2::Mmap,
}
impl LazyDict {
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
let file = std::fs::File::open(path.as_ref())
.map_err(|e| ShabdakoshError::DictParseError(format!("failed to open file: {e}")))?;
let mmap = unsafe {
memmap2::MmapOptions::new()
.map(&file)
.map_err(|e| ShabdakoshError::DictParseError(format!("failed to mmap file: {e}")))?
};
let dict = binary::from_binary(&mmap)?;
Ok(Self { dict, _mmap: mmap })
}
#[must_use]
pub fn lookup(&self, word: &str) -> Option<&[Phoneme]> {
self.dict.lookup(word)
}
#[must_use]
pub fn lookup_entry(&self, word: &str) -> Option<&DictEntry> {
self.dict.lookup_entry(word)
}
#[must_use]
pub fn len(&self) -> usize {
self.dict.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.dict.is_empty()
}
#[must_use]
pub fn dict(&self) -> &PronunciationDict {
&self.dict
}
#[must_use]
pub fn into_dict(self) -> PronunciationDict {
self.dict
}
}
impl core::fmt::Debug for LazyDict {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LazyDict")
.field("entries", &self.dict.len())
.field("user_entries", &self.dict.user_len())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lazy_dict_roundtrip() {
let dict = PronunciationDict::english_minimal();
let tmp = std::env::temp_dir().join("shabdakosh_test_lazy.bin");
binary::save_binary_file(&dict, &tmp).unwrap();
let lazy = LazyDict::open(&tmp).unwrap();
assert_eq!(lazy.len(), dict.len());
assert_eq!(lazy.lookup("hello"), dict.lookup("hello"));
assert_eq!(lazy.lookup("the"), dict.lookup("the"));
assert!(lazy.lookup("xyzzy").is_none());
let _ = std::fs::remove_file(&tmp);
}
#[test]
fn test_lazy_dict_into_dict() {
let dict = PronunciationDict::english_minimal();
let tmp = std::env::temp_dir().join("shabdakosh_test_lazy_into.bin");
binary::save_binary_file(&dict, &tmp).unwrap();
let lazy = LazyDict::open(&tmp).unwrap();
let recovered = lazy.into_dict();
assert_eq!(recovered.len(), dict.len());
let _ = std::fs::remove_file(&tmp);
}
#[test]
fn test_lazy_dict_open_nonexistent() {
let result = LazyDict::open("/tmp/nonexistent_shabdakosh.bin");
assert!(result.is_err());
}
#[test]
fn test_lazy_dict_debug() {
let dict = PronunciationDict::english_minimal();
let tmp = std::env::temp_dir().join("shabdakosh_test_lazy_debug.bin");
binary::save_binary_file(&dict, &tmp).unwrap();
let lazy = LazyDict::open(&tmp).unwrap();
let debug = format!("{lazy:?}");
assert!(debug.contains("LazyDict"));
let _ = std::fs::remove_file(&tmp);
}
}