Replace JSON with RON for persistence (epi/eframe/glium/web)
This commit is contained in:
parent
4fc3c6d375
commit
aba2108159
9 changed files with 55 additions and 40 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -111,7 +111,7 @@ fn create_storage(app_name: &str) -> Option<Box<dyn epi::Storage>> {
|
|||
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))
|
||||
}
|
||||
|
|
|
@ -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<PathBuf>) -> 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<T>(json_path: impl AsRef<Path>) -> Option<T>
|
||||
pub fn read_ron<T>(ron_path: impl AsRef<Path>) -> Option<T>
|
||||
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<std::path::Path>) {
|
||||
let memory: Option<egui::Memory> = read_json(memory_json_path);
|
||||
pub fn read_memory(ctx: &egui::Context, memory_file_path: impl AsRef<std::path::Path>) {
|
||||
let memory: Option<egui::Memory> = 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<std::path::
|
|||
/// Alternative to `FileStorage`
|
||||
pub fn write_memory(
|
||||
ctx: &egui::Context,
|
||||
memory_json_path: impl AsRef<std::path::Path>,
|
||||
memory_file_path: impl AsRef<std::path::Path>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
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(())
|
||||
}
|
||||
|
|
|
@ -10,10 +10,8 @@ pub struct WindowSettings {
|
|||
|
||||
impl WindowSettings {
|
||||
#[cfg(feature = "persistence")]
|
||||
pub fn from_json_file(
|
||||
settings_json_path: impl AsRef<std::path::Path>,
|
||||
) -> Option<WindowSettings> {
|
||||
crate::persistence::read_json(settings_json_path)
|
||||
pub fn from_ron_file(settings_ron_path: impl AsRef<std::path::Path>) -> Option<WindowSettings> {
|
||||
crate::persistence::read_ron(settings_ron_path)
|
||||
}
|
||||
|
||||
pub fn from_display(display: &glium::Display) -> Self {
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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<T: serde::de::DeserializeOwned>(storage: &dyn Storage, key: &str) -> Option<T> {
|
||||
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<T: serde::Serialize>(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
|
||||
|
|
Loading…
Reference in a new issue