zng_ext_config/
switch.rs
1use zng_clone_move::clmv;
2use zng_var::MergeVarBuilder;
3
4use super::*;
5
6#[derive(Default)]
15pub struct SwitchConfig {
16 cfgs: Vec<SwitchCfg>,
17}
18impl SwitchConfig {
19 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn push(&mut self, match_key: impl Fn(&ConfigKey) -> Option<ConfigKey> + Send + Sync + 'static, config: impl AnyConfig) {
29 self.cfgs.push(SwitchCfg {
30 match_key: Box::new(match_key),
31 cfg: Box::new(config),
32 })
33 }
34
35 pub fn push_prefix(&mut self, prefix: impl Into<Txt>, config: impl AnyConfig) {
41 let prefix = prefix.into();
42 if prefix.is_empty() {
43 self.push(|key| Some(key.clone()), config)
44 } else {
45 self.push(move |key| key.strip_prefix(prefix.as_str()).map(Txt::from_str), config)
46 }
47 }
48
49 pub fn with(mut self, match_key: impl Fn(&ConfigKey) -> Option<ConfigKey> + Send + Sync + 'static, config: impl AnyConfig) -> Self {
55 self.push(match_key, config);
56 self
57 }
58
59 pub fn with_prefix(mut self, prefix: impl Into<Txt>, config: impl AnyConfig) -> Self {
65 self.push_prefix(prefix, config);
66 self
67 }
68
69 fn cfg_mut(&mut self, key: &ConfigKey) -> Option<(ConfigKey, &mut dyn AnyConfig)> {
70 for c in &mut self.cfgs {
71 if let Some(key) = (c.match_key)(key) {
72 return Some((key, &mut *c.cfg));
73 }
74 }
75 None
76 }
77}
78impl AnyConfig for SwitchConfig {
79 fn status(&self) -> BoxedVar<ConfigStatus> {
80 let mut s = MergeVarBuilder::with_capacity(self.cfgs.len());
81 for c in &self.cfgs {
82 s.push(c.cfg.status());
83 }
84 s.build(|status| ConfigStatus::merge_status(status.iter().cloned())).boxed()
85 }
86
87 fn get_raw(&mut self, key: ConfigKey, default: RawConfigValue, insert: bool, shared: bool) -> BoxedVar<RawConfigValue> {
88 match self.cfg_mut(&key) {
89 Some((key, cfg)) => cfg.get_raw(key, default, insert, shared),
90 None => LocalVar(default).boxed(),
91 }
92 }
93
94 fn contains_key(&mut self, key: ConfigKey) -> BoxedVar<bool> {
95 match self.cfg_mut(&key) {
96 Some((key, cfg)) => cfg.contains_key(key),
97 None => LocalVar(false).boxed(),
98 }
99 }
100
101 fn remove(&mut self, key: &ConfigKey) -> bool {
102 match self.cfg_mut(key) {
103 Some((key, cfg)) => cfg.remove(&key),
104 None => false,
105 }
106 }
107
108 fn low_memory(&mut self) {
109 for c in &mut self.cfgs {
110 c.cfg.low_memory();
111 }
112 }
113}
114impl Config for SwitchConfig {
115 fn get<T: ConfigValue>(&mut self, key: impl Into<ConfigKey>, default: T, insert: bool) -> BoxedVar<T> {
116 let key = key.into();
117 match self.cfg_mut(&key) {
118 Some((key, cfg)) => {
119 let source_var = cfg.get_raw(
120 key.clone(),
121 RawConfigValue::serialize(&default).unwrap_or_else(|e| panic!("invalid default value, {e}")),
122 insert,
123 false,
124 );
125 let var = var(RawConfigValue::deserialize(source_var.get()).unwrap_or(default));
126
127 source_var
128 .bind_filter_map_bidi(
129 &var,
130 clmv!(key, |raw| {
132 match RawConfigValue::deserialize(raw.clone()) {
133 Ok(value) => Some(value),
134 Err(e) => {
135 tracing::error!("switch config get({key:?}) error, {e:?}");
136 None
137 }
138 }
139 }),
140 clmv!(key, source_var, |value| {
142 let _strong_ref = &source_var;
143
144 match RawConfigValue::serialize(value) {
145 Ok(raw) => Some(raw),
146 Err(e) => {
147 tracing::error!("switch config set({key:?}) error, {e:?}");
148 None
149 }
150 }
151 }),
152 )
153 .perm();
154
155 var.boxed()
156 }
157 None => LocalVar(default).boxed(),
158 }
159 }
160}
161
162struct SwitchCfg {
163 match_key: Box<dyn Fn(&ConfigKey) -> Option<ConfigKey> + Send + Sync>,
164 cfg: Box<dyn AnyConfig>,
165}