1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use std::any::Any;
use crate::{Tuneable, TUNA_STATE};
pub trait AsTuneable: Any + Clone + Sized {
type Result: std::fmt::Debug;
fn make_tuneable(&self) -> Tuneable;
fn update(tuneable: &mut Tuneable, var: Self::Result) -> bool;
fn reset(tuneable: &mut Tuneable);
fn from_tuneable(v: &Tuneable) -> Option<Self::Result>;
}
pub fn register<T: AsTuneable>(category: &str, name: &str, value: &T) {
let mut tuna = TUNA_STATE.write();
log::debug!(
"Registering variable: {}/{} -> {:?}",
category,
name,
std::any::type_name::<T>(),
);
if !tuna.contains_key(category) {
tuna.insert(category.to_owned(), Default::default());
}
let group = tuna.get_mut(category).expect("must be inserted above");
if group.contains_key(name) {
return;
}
group.insert(name.to_owned(), value.make_tuneable());
}
pub fn get<T: AsTuneable>(category: &str, name: &str) -> Option<T::Result> {
let tuna = TUNA_STATE.read();
let res: Option<T::Result> = tuna
.get(category)
.and_then(|group| group.get(name))
.and_then(|value| T::from_tuneable(value));
log::trace!("Reading variable {}/{} as {:?}", category, name, res);
res
}
pub fn set<T: AsTuneable>(category: &str, name: &str, value: T::Result) -> bool {
let mut tuna = TUNA_STATE.write();
if let Some(tuneable) = tuna.get_mut(category).and_then(|group| group.get_mut(name)) {
log::debug!("Setting variable {}/{} to {:?}", category, name, value);
T::update(tuneable, value)
} else {
false
}
}
pub fn reset<T: AsTuneable>(category: &str, name: &str) {
let mut tuna = TUNA_STATE.write();
if let Some(tuneable) = tuna.get_mut(category).and_then(|group| group.get_mut(name)) {
T::reset(tuneable);
}
}
pub fn is_registered(category: &str, name: &str) -> bool {
let mut tuna = TUNA_STATE.write();
tuna.get_mut(category)
.and_then(|group| group.get_mut(name))
.is_some()
}