1
0
Fork 0

Use String instead of &'static str in Params

This may hurt performance in generic UIs a bit, but it will allow you to
programatically generate custom Params implementations for repeated
Parameters structs.
This commit is contained in:
Robbert van der Helm 2022-03-20 02:13:19 +01:00
parent 1a9db3ab8e
commit b9d79771cc
7 changed files with 22 additions and 20 deletions

View file

@ -149,12 +149,12 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
// The specific parameter types know how to convert themselves into the correct ParamPtr // The specific parameter types know how to convert themselves into the correct ParamPtr
// variant // variant
param_mapping_insert_tokens param_mapping_insert_tokens
.push(quote! { param_map.insert(#param_id, self.#field_name.as_ptr()); }); .push(quote! { param_map.insert(String::from(#param_id), self.#field_name.as_ptr()); });
// Top-level parameters have no group, and we'll prefix the group name specified in // Top-level parameters have no group, and we'll prefix the group name specified in
// the `#[nested = "..."]` attribute to fields coming from nested groups // the `#[nested = "..."]` attribute to fields coming from nested groups
param_groups_insert_tokens param_groups_insert_tokens
.push(quote! { param_groups.insert(#param_id, String::new()); }); .push(quote! { param_groups.insert(String::from(#param_id), String::new()); });
param_id_string_tokens.push(quote! { #param_id, }); param_id_string_tokens.push(quote! { String::from(#param_id), });
} }
(None, Some(stable_name)) => { (None, Some(stable_name)) => {
if !persist_ids.insert(stable_name.clone()) { if !persist_ids.insert(stable_name.clone()) {
@ -224,7 +224,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
impl #impl_generics Params for #struct_name #ty_generics #where_clause { impl #impl_generics Params for #struct_name #ty_generics #where_clause {
fn param_map( fn param_map(
self: std::pin::Pin<&Self>, self: std::pin::Pin<&Self>,
) -> std::collections::HashMap<&'static str, nih_plug::param::internals::ParamPtr> { ) -> std::collections::HashMap<String, nih_plug::param::internals::ParamPtr> {
// This may not be in scope otherwise, used to call .as_ptr() // This may not be in scope otherwise, used to call .as_ptr()
use ::nih_plug::param::Param; use ::nih_plug::param::Param;
@ -241,12 +241,12 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
fn param_groups( fn param_groups(
self: std::pin::Pin<&Self>, self: std::pin::Pin<&Self>,
) -> std::collections::HashMap<&'static str, String> { ) -> std::collections::HashMap<String, String> {
let mut param_groups = std::collections::HashMap::new(); let mut param_groups = std::collections::HashMap::new();
#(#param_groups_insert_tokens)* #(#param_groups_insert_tokens)*
let nested_params_fields: &[&dyn Params] = &[#(&self.#nested_params_field_idents),*]; let nested_params_fields: &[&dyn Params] = &[#(&self.#nested_params_field_idents),*];
let nested_params_groups: &[&'static str] = &[#(#nested_params_group_names),*]; let nested_params_groups: &[String] = &[#(String::from(#nested_params_group_names)),*];
for (nested_params, group_name) in for (nested_params, group_name) in
nested_params_fields.into_iter().zip(nested_params_groups) nested_params_fields.into_iter().zip(nested_params_groups)
{ {
@ -272,8 +272,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
param_groups param_groups
} }
fn param_ids(self: std::pin::Pin<&Self>) -> Vec<String> {
fn param_ids(self: std::pin::Pin<&Self>) -> Vec<&'static str> {
let mut ids = vec![#(#param_id_string_tokens)*]; let mut ids = vec![#(#param_id_string_tokens)*];
let nested_params_fields: &[&dyn Params] = &[#(&self.#nested_params_field_idents),*]; let nested_params_fields: &[&dyn Params] = &[#(&self.#nested_params_field_idents),*];

View file

@ -50,7 +50,7 @@ pub fn create(
.auto_shrink([false, false]) .auto_shrink([false, false])
.show(ui, |ui| { .show(ui, |ui| {
for (widget_idx, id) in param_ids.into_iter().enumerate() { for (widget_idx, id) in param_ids.into_iter().enumerate() {
let param = param_map[id]; let param = param_map[&id];
// This list looks weird without a little padding // This list looks weird without a little padding
if widget_idx > 0 { if widget_idx > 0 {

View file

@ -177,7 +177,7 @@ where
} }
for param_id in param_ids { for param_id in param_ids {
let param_ptr = param_map[param_id]; let param_ptr = param_map[&param_id];
// SAFETY: We only borrow each item once, and the plugin framework statically asserted // SAFETY: We only borrow each item once, and the plugin framework statically asserted
// that parameter indices are unique and this widget state cannot outlive this // that parameter indices are unique and this widget state cannot outlive this
// function // function

View file

@ -40,15 +40,18 @@ pub use serde_json::to_string as serialize_field;
/// This implementation is safe when using from the wrapper because the plugin object needs to be /// This implementation is safe when using from the wrapper because the plugin object needs to be
/// pinned, and it can never outlive the wrapper. /// pinned, and it can never outlive the wrapper.
pub trait Params { pub trait Params {
// NOTE: These types use `String` even though for the `Params` derive macro `&'static str` would
// have been fine to be able to support custom reusable Params implemnetations.
/// Create a mapping from unique parameter IDs to parameters. This is done for every parameter /// Create a mapping from unique parameter IDs to parameters. This is done for every parameter
/// field marked with `#[id = "stable_name"]`. Dereferencing the pointers stored in the values /// field marked with `#[id = "stable_name"]`. Dereferencing the pointers stored in the values
/// is only valid as long as this pinned object is valid. /// is only valid as long as this pinned object is valid.
fn param_map(self: Pin<&Self>) -> HashMap<&'static str, ParamPtr>; fn param_map(self: Pin<&Self>) -> HashMap<String, ParamPtr>;
/// Contains group names for each parameter in [`param_map()`][Self::param_map()]. This is /// Contains group names for each parameter in [`param_map()`][Self::param_map()]. This is
/// either an empty string for top level parameters, or a slash/delimited `"Group Name 1/Group /// either an empty string for top level parameters, or a slash/delimited `"Group Name 1/Group
/// Name 2"` string for parameters that belong to `#[nested = "Name"]` parameter objects. /// Name 2"` string for parameters that belong to `#[nested = "Name"]` parameter objects.
fn param_groups(self: Pin<&Self>) -> HashMap<&'static str, String>; fn param_groups(self: Pin<&Self>) -> HashMap<String, String>;
/// All parameter IDs from [`param_map()`][Self::param_map()], in a stable order. This order /// All parameter IDs from [`param_map()`][Self::param_map()], in a stable order. This order
/// will be used to display the parameters. /// will be used to display the parameters.
@ -57,7 +60,7 @@ pub trait Params {
/// that's become a bit more difficult since Rust does not have a convenient way to /// that's become a bit more difficult since Rust does not have a convenient way to
/// concatenate an arbitrary number of static slices. There's probably a better way to do /// concatenate an arbitrary number of static slices. There's probably a better way to do
/// this. /// this.
fn param_ids(self: Pin<&Self>) -> Vec<&'static str>; fn param_ids(self: Pin<&Self>) -> Vec<String>;
/// Serialize all fields marked with `#[persist = "stable_name"]` into a hash map containing /// 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 /// JSON-representations of those fields so they can be written to the plugin's state and

View file

@ -184,7 +184,7 @@ pub struct Wrapper<P: ClapPlugin> {
pub param_defaults_normalized: HashMap<u32, f32>, pub param_defaults_normalized: HashMap<u32, f32>,
/// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging /// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging
/// and when storing and restoring plugin state. /// and when storing and restoring plugin state.
param_id_to_hash: HashMap<&'static str, u32>, param_id_to_hash: HashMap<String, u32>,
/// The inverse mapping from [`param_by_hash`][Self::param_by_hash]. This is needed to be able /// The inverse mapping from [`param_by_hash`][Self::param_by_hash]. This is needed to be able
/// to have an ergonomic parameter setting API that uses references to the parameters instead of /// to have an ergonomic parameter setting API that uses references to the parameters instead of
/// having to add a setter function to the parameter (or even worse, have it be completely /// having to add a setter function to the parameter (or even worse, have it be completely
@ -365,7 +365,7 @@ impl<P: ClapPlugin> Wrapper<P> {
.collect(); .collect();
let param_id_to_hash = param_id_hashes_ptrs_groups let param_id_to_hash = param_id_hashes_ptrs_groups
.iter() .iter()
.map(|&(id, hash, _, _)| (*id, hash)) .map(|&(id, hash, _, _)| (id.clone(), hash))
.collect(); .collect();
let param_ptr_to_hash = param_id_hashes_ptrs_groups let param_ptr_to_hash = param_id_hashes_ptrs_groups
.into_iter() .into_iter()

View file

@ -39,7 +39,7 @@ pub(crate) struct State {
pub(crate) unsafe fn serialize( pub(crate) unsafe fn serialize(
plugin_params: Pin<&dyn Params>, plugin_params: Pin<&dyn Params>,
param_by_hash: &HashMap<u32, ParamPtr>, param_by_hash: &HashMap<u32, ParamPtr>,
param_id_to_hash: &HashMap<&'static str, u32>, param_id_to_hash: &HashMap<String, u32>,
bypass_param_id: &str, bypass_param_id: &str,
bypass_state: &AtomicBool, bypass_state: &AtomicBool,
) -> serde_json::Result<Vec<u8>> { ) -> serde_json::Result<Vec<u8>> {
@ -50,7 +50,7 @@ pub(crate) unsafe fn serialize(
let param_ptr = param_by_hash.get(hash)?; let param_ptr = param_by_hash.get(hash)?;
Some((param_id_str, param_ptr)) Some((param_id_str, param_ptr))
}) })
.map(|(&param_id_str, &param_ptr)| match param_ptr { .map(|(param_id_str, &param_ptr)| match param_ptr {
ParamPtr::FloatParam(p) => ( ParamPtr::FloatParam(p) => (
param_id_str.to_string(), param_id_str.to_string(),
ParamValue::F32((*p).plain_value()), ParamValue::F32((*p).plain_value()),
@ -95,7 +95,7 @@ pub(crate) unsafe fn deserialize(
state: &[u8], state: &[u8],
plugin_params: Pin<&dyn Params>, plugin_params: Pin<&dyn Params>,
param_by_hash: &HashMap<u32, ParamPtr>, param_by_hash: &HashMap<u32, ParamPtr>,
param_id_to_hash: &HashMap<&'static str, u32>, param_id_to_hash: &HashMap<String, u32>,
current_buffer_config: Option<&BufferConfig>, current_buffer_config: Option<&BufferConfig>,
bypass_param_id: &str, bypass_param_id: &str,
bypass_state: &AtomicBool, bypass_state: &AtomicBool,

View file

@ -92,7 +92,7 @@ pub(crate) struct WrapperInner<P: Vst3Plugin> {
pub param_defaults_normalized: HashMap<u32, f32>, pub param_defaults_normalized: HashMap<u32, f32>,
/// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging /// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging
/// and when storing and restorign plugin state. /// and when storing and restorign plugin state.
pub param_id_to_hash: HashMap<&'static str, u32>, pub param_id_to_hash: HashMap<String, u32>,
/// The inverse mapping from [`param_by_hash`][Self::param_by_hash]. This is needed to be able /// The inverse mapping from [`param_by_hash`][Self::param_by_hash]. This is needed to be able
/// to have an ergonomic parameter setting API that uses references to the parameters instead of /// to have an ergonomic parameter setting API that uses references to the parameters instead of
/// having to add a setter function to the parameter (or even worse, have it be completely /// having to add a setter function to the parameter (or even worse, have it be completely
@ -177,7 +177,7 @@ impl<P: Vst3Plugin> WrapperInner<P> {
.collect(); .collect();
let param_id_to_hash = param_id_hashes_ptrs_groups let param_id_to_hash = param_id_hashes_ptrs_groups
.iter() .iter()
.map(|&(id, hash, _, _)| (*id, hash)) .map(|&(id, hash, _, _)| (id.clone(), hash))
.collect(); .collect();
let param_ptr_to_hash = param_id_hashes_ptrs_groups let param_ptr_to_hash = param_id_hashes_ptrs_groups
.into_iter() .into_iter()