From ad0db689807f36f83c7550b8d8050c8a8c2d4e37 Mon Sep 17 00:00:00 2001 From: Finn Brewer Date: Sat, 27 Jul 2024 16:23:34 -0700 Subject: [PATCH] refactor: move cache into separate cache file --- Cargo.lock | 29 +++++++++++++++++++++++++++ src-tauri/Cargo.toml | 1 + src-tauri/src/dictionary.rs | 16 ++++++--------- src-tauri/src/main.rs | 39 ++++++++++++++++++++++++++++++++++--- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86fbb17..648c655 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -89,6 +89,7 @@ dependencies = [ "log", "lol_html", "reqwest", + "rmp-serde", "select", "serde", "serde_json", @@ -2143,6 +2144,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pathdiff" version = "0.2.1" @@ -2663,6 +2670,28 @@ dependencies = [ "windows 0.37.0", ] +[[package]] +name = "rmp" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "rusqlite" version = "0.31.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 02374d6..f8430d4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,6 +35,7 @@ tokio = { version = "1.29.1", features = ["sync"] } log = "0.4.22" spyglys = "0.2.2" url = "2.5.2" +rmp-serde = "1.3.0" [dependencies.simple_logger] version = "5.0.0" diff --git a/src-tauri/src/dictionary.rs b/src-tauri/src/dictionary.rs index ff21d14..38d99dd 100644 --- a/src-tauri/src/dictionary.rs +++ b/src-tauri/src/dictionary.rs @@ -143,12 +143,9 @@ pub async fn get_defs( .clone() .expect("current language should already be selected"); if let Some(v) = state - .to_save - .language_specific + .language_cached_data .get(&language) - .expect("language to already have data to save") - .cached_defs - .get(&lemma) + .and_then(|v| v.definitions.get(&lemma)) { Ok(v.clone()) } else { @@ -183,11 +180,10 @@ pub async fn get_defs( defs.push(def); } state - .to_save - .language_specific - .get_mut(&language) - .expect("language to already have data to save") - .cached_defs + .language_cached_data + .entry(language) + .or_default() + .definitions .insert(lemma, defs.clone()); Ok(defs) } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index bd5ba55..f95159f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -50,6 +50,8 @@ enum SakinyjeError { Utf8Error(#[from] std::string::FromUtf8Error), #[error(transparent)] Stardict(#[from] stardict::error::Error), + #[error(transparent)] + CacheDecode(#[from] rmp_serde::decode::Error), #[error("No operating system {0} directory was found")] MissingDir(String), #[error("Anki is not available. This may be because it is not open or ankiconnect is not installed.")] @@ -90,6 +92,12 @@ struct SharedInfo { dict_info: Arc>, errors: Vec, can_save: bool, + language_cached_data: HashMap, +} + +#[derive(Debug, Deserialize, Serialize, Default)] +struct CachedData { + definitions: HashMap>, } struct LanguageParser { @@ -110,7 +118,6 @@ struct ToSave { #[derive(Serialize, Deserialize, Default)] struct LanguageSpecficToSave { words: HashMap, - cached_defs: HashMap>, previous_file: Option, lemmas_to_replace: HashMap, previous_amount: usize, @@ -153,6 +160,22 @@ impl Default for SharedInfo { } }; + let language_cached_data = match dirs::cache_dir() + .ok_or_else(|| SakinyjeError::MissingDir(String::from("cache"))) + .and_then(|cache_dir| { + fs::read(cache_dir.join("sakinyje.cache")) + .map_err(SakinyjeError::Io) + .and_then(|v| rmp_serde::from_slice(&v).map_err(SakinyjeError::CacheDecode)) + }) { + Ok(v) => v, + Err(e) => { + if !matches!(e, SakinyjeError::Io(_)) { + errors.push(e); + } + HashMap::new() + } + }; + set_word_knowledge_from_anki(&mut to_save, &settings.languages); if let Some(cmds) = &settings.to_run { @@ -177,6 +200,7 @@ impl Default for SharedInfo { current_language, dict_info: Default::default(), can_save, + language_cached_data, } } } @@ -339,6 +363,15 @@ fn handle_window_event(event: GlobalWindowEvent) { toml::to_string(&locked_state.to_save).expect("Error serializing to toml"); fs::write(saved_state_file, conts).expect("error writing to file"); } + let cache_file = dirs::cache_dir() + .expect("cache dir does not exist") + .join("sakinyje.cache"); + fs::write( + cache_file, + rmp_serde::to_vec(&locked_state.language_cached_data) + .expect("error serializing cache"), + ) + .expect("error writing cache"); } _ => (), } @@ -441,8 +474,8 @@ async fn write_settings( for (language, specific_settings) in &cloned_languages { if let Some(new_specific_settings) = settings.languages.get(language) { if new_specific_settings.dicts != specific_settings.dicts { - if let Some(saved_details) = state.to_save.language_specific.get_mut(language) { - saved_details.cached_defs.clear(); + if let Some(language_cache) = state.language_cached_data.get_mut(language) { + language_cache.definitions.clear(); } } }