#[macro_export]
macro_rules! vstkit_params {
(
$set_name:ident;
$(
$param_name:ident {
id: $id:expr,
name: $name:expr,
short_name: $short_name:expr,
unit: $unit:expr,
default: $default:expr,
min: $min:expr,
max: $max:expr,
step: $step:expr $(,)?
}
),* $(,)?
) => {
paste::paste! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum [<$set_name Id>] {
$(
$param_name = $id,
)*
}
impl ::std::convert::From<[<$set_name Id>]> for $crate::ParamId {
fn from(id: [<$set_name Id>]) -> Self {
$crate::ParamId(id as u32)
}
}
}
pub struct $set_name;
// Generate ParamSet implementation
paste::paste! {
impl $crate::ParamSet for $set_name {
type Id = [<$set_name Id>];
const SPECS: &'static [$crate::ParamSpec] = &[
$(
$crate::ParamSpec {
id: $crate::ParamId($id),
name: $name,
short_name: $short_name,
unit: $unit,
default: $default,
min: $min,
max: $max,
step: $step,
},
)*
];
fn spec(id: Self::Id) -> ::std::option::Option<&'static $crate::ParamSpec> {
Self::SPECS.iter().find(|s| s.id.0 == id as u32)
}
fn iter() -> impl ::std::iter::Iterator<Item = &'static $crate::ParamSpec> {
Self::SPECS.iter()
}
}
}
};
}
#[cfg(test)]
mod tests {
use crate::{ParamId, ParamSet};
vstkit_params! {
TestParams;
Gain {
id: 0,
name: "Gain",
short_name: "Gain",
unit: "dB",
default: 0.0,
min: -24.0,
max: 24.0,
step: 0.1,
},
Frequency {
id: 1,
name: "Frequency",
short_name: "Freq",
unit: "Hz",
default: 1000.0,
min: 20.0,
max: 20000.0,
step: 1.0,
},
}
#[test]
fn test_generated_enum() {
let gain_id = TestParamsId::Gain;
let freq_id = TestParamsId::Frequency;
assert_eq!(gain_id as u32, 0);
assert_eq!(freq_id as u32, 1);
}
#[test]
fn test_param_id_conversion() {
let gain_id: ParamId = TestParamsId::Gain.into();
assert_eq!(gain_id.0, 0);
}
#[test]
fn test_param_set_specs() {
assert_eq!(TestParams::SPECS.len(), 2);
assert_eq!(TestParams::count(), 2);
let gain_spec = &TestParams::SPECS[0];
assert_eq!(gain_spec.name, "Gain");
assert_eq!(gain_spec.unit, "dB");
assert_eq!(gain_spec.default, 0.0);
}
#[test]
fn test_param_set_spec_lookup() {
let gain_spec = TestParams::spec(TestParamsId::Gain);
assert!(gain_spec.is_some());
assert_eq!(gain_spec.unwrap().name, "Gain");
let freq_spec = TestParams::spec(TestParamsId::Frequency);
assert!(freq_spec.is_some());
assert_eq!(freq_spec.unwrap().name, "Frequency");
}
#[test]
fn test_param_set_iter() {
let names: Vec<&str> = TestParams::iter().map(|s| s.name).collect();
assert_eq!(names, vec!["Gain", "Frequency"]);
}
}