From aba2108159bb44abb1edcd21757843a2a188e8da Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Mon, 5 Apr 2021 12:09:01 +0200 Subject: [PATCH] Replace JSON with RON for persistence (epi/eframe/glium/web) --- Cargo.lock | 17 ++++++++++++++--- egui_glium/Cargo.toml | 7 +++---- egui_glium/src/backend.rs | 2 +- egui_glium/src/persistence.rs | 26 +++++++++++++++----------- egui_glium/src/window_settings.rs | 6 ++---- egui_web/Cargo.toml | 4 ++-- egui_web/src/lib.rs | 14 +++++++------- epi/Cargo.toml | 4 ++-- epi/src/lib.rs | 15 +++++++++------ 9 files changed, 55 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be7f1a25..c950657c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -785,8 +785,8 @@ dependencies = [ "egui", "epi", "glium", + "ron", "serde", - "serde_json", "tts", "ureq", "webbrowser", @@ -799,8 +799,8 @@ dependencies = [ "egui", "epi", "js-sys", + "ron", "serde", - "serde_json", "tts", "wasm-bindgen", "wasm-bindgen-futures", @@ -851,8 +851,8 @@ name = "epi" version = "0.10.0" dependencies = [ "egui", + "ron", "serde", - "serde_json", ] [[package]] @@ -1865,6 +1865,17 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "ron" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "064ea8613fb712a19faf920022ec8ddf134984f100090764a4e1d768f3827f1f" +dependencies = [ + "base64", + "bitflags", + "serde", +] + [[package]] name = "rustc-demangle" version = "0.1.18" diff --git a/egui_glium/Cargo.toml b/egui_glium/Cargo.toml index 3b565e62..8e4febf3 100644 --- a/egui_glium/Cargo.toml +++ b/egui_glium/Cargo.toml @@ -30,8 +30,8 @@ ureq = { version = "2.0", optional = true } # feature "persistence": directories-next = { version = "2", optional = true } +ron = { version = "0.6", optional = true } serde = { version = "1", optional = true } -serde_json = { version = "1", optional = true } # feature screen_reader tts = { version = "0.14", optional = true } @@ -45,9 +45,8 @@ http = ["ureq"] persistence = [ "directories-next", "egui/persistence", - "epi/serde_json", - "epi/serde", - "serde_json", + "epi/persistence", + "ron", "serde", ] time = ["chrono"] # for seconds_since_midnight diff --git a/egui_glium/src/backend.rs b/egui_glium/src/backend.rs index 0cf6e903..f5507b85 100644 --- a/egui_glium/src/backend.rs +++ b/egui_glium/src/backend.rs @@ -111,7 +111,7 @@ fn create_storage(app_name: &str) -> Option> { None } else { let mut config_dir = data_dir; - config_dir.push("app.json"); + config_dir.push("app.ron"); let storage = crate::persistence::FileStorage::from_path(config_dir); Some(Box::new(storage)) } diff --git a/egui_glium/src/persistence.rs b/egui_glium/src/persistence.rs index f426a30d..3d523e4a 100644 --- a/egui_glium/src/persistence.rs +++ b/egui_glium/src/persistence.rs @@ -5,7 +5,7 @@ use std::{ // ---------------------------------------------------------------------------- -/// A key-value store backed by a JSON file on disk. +/// A key-value store backed by a [RON](https://github.com/ron-rs/ron) file on disk. /// Used to restore egui state, glium window position/size and app state. pub struct FileStorage { path: PathBuf, @@ -17,7 +17,7 @@ impl FileStorage { pub fn from_path(path: impl Into) -> Self { let path: PathBuf = path.into(); Self { - kv: read_json(&path).unwrap_or_default(), + kv: read_ron(&path).unwrap_or_default(), path, dirty: false, } @@ -39,7 +39,9 @@ impl epi::Storage for FileStorage { fn flush(&mut self) { if self.dirty { // eprintln!("Persisted to {}", self.path.display()); - serde_json::to_writer(std::fs::File::create(&self.path).unwrap(), &self.kv).unwrap(); + let file = std::fs::File::create(&self.path).unwrap(); + let config = Default::default(); + ron::ser::to_writer_pretty(file, &self.kv, config).unwrap(); self.dirty = false; } } @@ -47,17 +49,17 @@ impl epi::Storage for FileStorage { // ---------------------------------------------------------------------------- -pub fn read_json(json_path: impl AsRef) -> Option +pub fn read_ron(ron_path: impl AsRef) -> Option where T: serde::de::DeserializeOwned, { - match std::fs::File::open(json_path) { + match std::fs::File::open(ron_path) { Ok(file) => { let reader = std::io::BufReader::new(file); - match serde_json::from_reader(reader) { + match ron::de::from_reader(reader) { Ok(value) => Some(value), Err(err) => { - eprintln!("ERROR: Failed to parse json: {}", err); + eprintln!("ERROR: Failed to parse RON: {}", err); None } } @@ -71,8 +73,8 @@ where // ---------------------------------------------------------------------------- /// Alternative to `FileStorage` -pub fn read_memory(ctx: &egui::Context, memory_json_path: impl AsRef) { - let memory: Option = read_json(memory_json_path); +pub fn read_memory(ctx: &egui::Context, memory_file_path: impl AsRef) { + let memory: Option = read_ron(memory_file_path); if let Some(memory) = memory { *ctx.memory() = memory; } @@ -81,8 +83,10 @@ pub fn read_memory(ctx: &egui::Context, memory_json_path: impl AsRef, + memory_file_path: impl AsRef, ) -> Result<(), Box> { - serde_json::to_writer_pretty(std::fs::File::create(memory_json_path)?, &*ctx.memory())?; + let file = std::fs::File::create(memory_file_path)?; + let ron_config = Default::default(); + ron::ser::to_writer_pretty(file, &*ctx.memory(), ron_config)?; Ok(()) } diff --git a/egui_glium/src/window_settings.rs b/egui_glium/src/window_settings.rs index 2feaf901..8d490521 100644 --- a/egui_glium/src/window_settings.rs +++ b/egui_glium/src/window_settings.rs @@ -10,10 +10,8 @@ pub struct WindowSettings { impl WindowSettings { #[cfg(feature = "persistence")] - pub fn from_json_file( - settings_json_path: impl AsRef, - ) -> Option { - crate::persistence::read_json(settings_json_path) + pub fn from_ron_file(settings_ron_path: impl AsRef) -> Option { + crate::persistence::read_ron(settings_ron_path) } pub fn from_display(display: &glium::Display) -> Self { diff --git a/egui_web/Cargo.toml b/egui_web/Cargo.toml index d376926c..f40e1854 100644 --- a/egui_web/Cargo.toml +++ b/egui_web/Cargo.toml @@ -25,8 +25,8 @@ crate-type = ["cdylib", "rlib"] egui = { version = "0.10.0", path = "../egui" } epi = { version = "0.10.0", path = "../epi" } js-sys = "0.3" +ron = { version = "0.6", optional = true } serde = { version = "1", optional = true } -serde_json = { version = "1", optional = true } tts = { version = "0.14", optional = true } # feature screen_reader wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" @@ -41,7 +41,7 @@ http = [ "web-sys/RequestMode", "web-sys/Response", ] -persistence = ["egui/persistence", "serde", "serde_json"] +persistence = ["egui/persistence", "ron", "serde"] screen_reader = ["tts"] # experimental [dependencies.web-sys] diff --git a/egui_web/src/lib.rs b/egui_web/src/lib.rs index d7939a48..a11021ad 100644 --- a/egui_web/src/lib.rs +++ b/egui_web/src/lib.rs @@ -189,13 +189,13 @@ pub fn local_storage_remove(key: &str) { #[cfg(feature = "persistence")] pub fn load_memory(ctx: &egui::Context) { - if let Some(memory_string) = local_storage_get("egui_memory_json") { - match serde_json::from_str(&memory_string) { + if let Some(memory_string) = local_storage_get("egui_memory_ron") { + match ron::from_str(&memory_string) { Ok(memory) => { *ctx.memory() = memory; } Err(err) => { - console_error(format!("Failed to parse memory json: {}", err)); + console_error(format!("Failed to parse memory RON: {}", err)); } } } @@ -206,12 +206,12 @@ pub fn load_memory(_: &egui::Context) {} #[cfg(feature = "persistence")] pub fn save_memory(ctx: &egui::Context) { - match serde_json::to_string(&*ctx.memory()) { - Ok(json) => { - local_storage_set("egui_memory_json", &json); + match ron::to_string(&*ctx.memory()) { + Ok(ron) => { + local_storage_set("egui_memory_ron", &ron); } Err(err) => { - console_error(format!("Failed to serialize memory as json: {}", err)); + console_error(format!("Failed to serialize memory as RON: {}", err)); } } } diff --git a/epi/Cargo.toml b/epi/Cargo.toml index 5dc861f4..7450fa0d 100644 --- a/epi/Cargo.toml +++ b/epi/Cargo.toml @@ -21,10 +21,10 @@ include = [ [dependencies] egui = { version = "0.10.0", path = "../egui" } +ron = { version = "0.6", optional = true } serde = { version = "1", optional = true } -serde_json = { version = "1", optional = true } [features] default = [] http = [] -persistence = ["serde", "serde_json"] +persistence = ["ron", "serde"] diff --git a/epi/src/lib.rs b/epi/src/lib.rs index 80697e9b..7cb11772 100644 --- a/epi/src/lib.rs +++ b/epi/src/lib.rs @@ -294,18 +294,21 @@ impl Storage for DummyStorage { fn flush(&mut self) {} } -/// Get an deserialize the JSON stored at the given key. -#[cfg(feature = "serde_json")] +/// Get an deserialize the [RON](https://github.com/ron-rs/ron] stored at the given key. +#[cfg(feature = "ron")] pub fn get_value(storage: &dyn Storage, key: &str) -> Option { storage .get_string(key) - .and_then(|value| serde_json::from_str(&value).ok()) + .and_then(|value| ron::from_str(&value).ok()) } -/// Serialize the given value as JSON and store with the given key. -#[cfg(feature = "serde_json")] +/// Serialize the given value as [RON](https://github.com/ron-rs/ron] and store with the given key. +#[cfg(feature = "ron")] pub fn set_value(storage: &mut dyn Storage, key: &str, value: &T) { - storage.set_string(key, serde_json::to_string_pretty(value).unwrap()); + storage.set_string( + key, + ron::ser::to_string_pretty(value, Default::default()).unwrap(), + ); } /// [`Storage`] key used for app