Store persistent fields as plain JSON strings
On second thought, this is much better. The resulting file size will be much smaller because only double quotes need to be escaped. It's also easier to read at a glance.
This commit is contained in:
parent
3111d75b29
commit
6494d1ed5f
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -8,12 +8,6 @@ version = "1.0.53"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "gain"
|
||||
version = "0.1.0"
|
||||
|
@ -37,7 +31,6 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
name = "nih_plug"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"lazy_static",
|
||||
"nih_plug_derive",
|
||||
"serde",
|
||||
|
|
|
@ -10,7 +10,6 @@ members = ["nih_plug_derive", "plugins/gain", "xtask"]
|
|||
|
||||
[dependencies]
|
||||
nih_plug_derive = { path = "nih_plug_derive" }
|
||||
base64 = "0.13"
|
||||
lazy_static = "1.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
|
|
@ -158,7 +158,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
|||
param_map
|
||||
}
|
||||
|
||||
fn serialize_fields(&self) -> ::std::collections::HashMap<String, Vec<u8>> {
|
||||
fn serialize_fields(&self) -> ::std::collections::HashMap<String, String> {
|
||||
let mut serialized = ::std::collections::HashMap::new();
|
||||
|
||||
#(#field_serialize_tokens)*
|
||||
|
@ -166,7 +166,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
|||
serialized
|
||||
}
|
||||
|
||||
fn deserialize_fields(&self, serialized: &::std::collections::HashMap<String, Vec<u8>>) {
|
||||
fn deserialize_fields(&self, serialized: &::std::collections::HashMap<String, String>) {
|
||||
for (field_name, data) in serialized {
|
||||
match field_name.as_str() {
|
||||
#(#field_deserialize_tokens)*
|
||||
|
|
|
@ -25,9 +25,9 @@ pub type FloatParam = PlainParam<f32>;
|
|||
pub type IntParam = PlainParam<i32>;
|
||||
|
||||
/// Re-export for use in the [Params] proc-macro.
|
||||
pub use serde_json::from_slice as deserialize_field;
|
||||
pub use serde_json::from_str as deserialize_field;
|
||||
/// Re-export for use in the [Params] proc-macro.
|
||||
pub use serde_json::to_vec as serialize_field;
|
||||
pub use serde_json::to_string as serialize_field;
|
||||
|
||||
/// The functinoality needed for persisting a field to the plugin's state, and for restoring values
|
||||
/// when loading old state.
|
||||
|
@ -357,13 +357,13 @@ pub trait Params {
|
|||
/// Serialize all fields marked with `#[persist = "stable_name"]` into a hash map containing
|
||||
/// JSON-representations of those fields so they can be written to the plugin's state and
|
||||
/// recalled later. This uses [serialize_field] under the hood.
|
||||
fn serialize_fields(&self) -> HashMap<String, Vec<u8>>;
|
||||
fn serialize_fields(&self) -> HashMap<String, String>;
|
||||
|
||||
/// Restore all fields marked with `#[persist = "stable_name"]` from a hashmap created by
|
||||
/// [Self::serialize_fields]. All of thse fields should be wrapped in a [PersistentField] with
|
||||
/// thread safe interior mutability, like an `RwLock` or a `Mutex`. This gets called when the
|
||||
/// plugin's state is being restored. This uses [deserialize_field] under the hood.
|
||||
fn deserialize_fields(&self, serialized: &HashMap<String, Vec<u8>>);
|
||||
fn deserialize_fields(&self, serialized: &HashMap<String, String>);
|
||||
}
|
||||
|
||||
/// Internal pointers to parameters. This is an implementation detail used by the wrappers.
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
//! Utilities for saving a [crate::plugin::Plugin]'s state.
|
||||
|
||||
use serde::de::Error;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
@ -40,38 +39,7 @@ pub(crate) struct State {
|
|||
/// on the [Params] struct that's annotated with `#[persist = "stable_name"]` will be persisted
|
||||
/// this way.
|
||||
///
|
||||
/// The individual JSON-serialized fields are encoded as base64 strings so they don't take up as
|
||||
/// much space in the preset. Storing them as a plain JSON string would have also been possible,
|
||||
/// but that can get messy with escaping since those will likely also contain double quotes.
|
||||
#[serde(serialize_with = "encode_fields")]
|
||||
#[serde(deserialize_with = "decode_fields")]
|
||||
pub fields: HashMap<String, Vec<u8>>,
|
||||
}
|
||||
|
||||
fn encode_fields<S>(bytes: &HashMap<String, Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.collect_map(
|
||||
bytes
|
||||
.into_iter()
|
||||
.map(|(id, json)| (id, base64::encode(json))),
|
||||
)
|
||||
}
|
||||
|
||||
fn decode_fields<'de, D>(deserializer: D) -> Result<HashMap<String, Vec<u8>>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let base64_map: HashMap<String, String> = HashMap::deserialize(deserializer)?;
|
||||
let decoded_map: Result<HashMap<String, Vec<u8>>, D::Error> = base64_map
|
||||
.into_iter()
|
||||
.map(|(id, base64)| {
|
||||
base64::decode(base64)
|
||||
.map(|decoded| (id, decoded))
|
||||
.map_err(|err| D::Error::custom(format!("base64 decode failed: {}", err)))
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(decoded_map?)
|
||||
/// The individual fields are also serialized as JSON so they can safely be restored
|
||||
/// independently of the other fields.
|
||||
pub fields: HashMap<String, String>,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue