1use std::{
3 borrow::Borrow,
4 collections::{HashMap, HashSet},
5 vec,
6};
7
8use crate::{
9 key::{PartialKey, PartialKeyIter},
10 source::{ConfigSource, ConfigSourceAdaptor},
11 value_ref::Refresher,
12 ConfigError, ConfigKey, ConfigValue, PartialKeyCollector,
13};
14
15#[doc(hidden)]
17#[allow(missing_debug_implementations, unreachable_pub)]
18pub struct HashSource {
19 pub(crate) value: HashMap<String, HashValue>,
20 name: String,
21 pub(crate) refs: Refresher,
22}
23
24impl ConfigSource for HashSource {
25 fn name(&self) -> &str {
26 &self.name
27 }
28 fn load(&self, builder: &mut ConfigSourceBuilder<'_>) -> Result<(), ConfigError> {
29 for (k, v) in &self.value {
30 if let Some(v) = &v.value {
31 builder.set(k, v.clone_static());
32 }
33 }
34 Ok(())
35 }
36}
37
38#[derive(Debug)]
40pub(crate) struct HashValue {
41 sub_str: HashSet<String>,
42 sub_int: Option<usize>,
43 value: Option<ConfigValue<'static>>,
44}
45
46#[derive(Debug)]
48pub struct ConfigSourceBuilder<'a> {
49 key: Vec<String>,
50 map: &'a mut HashMap<String, HashValue>,
51 count: usize,
52}
53
54impl HashValue {
55 #[inline]
56 fn new() -> Self {
57 Self {
58 sub_str: HashSet::new(),
59 sub_int: None,
60 value: None,
61 }
62 }
63
64 #[inline]
65 fn push_val<V: Into<ConfigValue<'static>>>(&mut self, val: V) {
66 if self.value.is_none() {
67 self.value = Some(val.into());
68 }
69 }
70
71 #[inline]
72 fn push_key(&mut self, key: &PartialKey<'_>) {
73 match key {
74 PartialKey::Str(i) => {
75 self.sub_str.insert(i.to_string());
76 }
77 PartialKey::Int(i) => {
78 let v = self.sub_int.get_or_insert(*i);
79 if *v < *i {
80 *v = *i;
81 }
82 }
83 }
84 }
85}
86
87impl HashSource {
88 pub(crate) fn new<K: Into<String>>(name: K) -> Self {
89 Self {
90 value: HashMap::new(),
91 name: name.into(),
92 refs: Refresher::new(),
93 }
94 }
95
96 #[inline]
97 pub(crate) fn prefixed(&mut self) -> ConfigSourceBuilder<'_> {
98 ConfigSourceBuilder {
99 key: vec![],
100 map: &mut self.value,
101 count: 0,
102 }
103 }
104
105 pub(crate) fn get_value(&self, key: &ConfigKey<'_>) -> Option<ConfigValue<'_>> {
106 let key = key.as_str();
107 self.value
108 .get(key)
109 .and_then(|f| f.value.as_ref())
110 .map(|v| match v {
111 ConfigValue::StrRef(v) => ConfigValue::StrRef(v),
112 ConfigValue::Str(v) => ConfigValue::StrRef(v),
113 ConfigValue::Int(v) => ConfigValue::Int(*v),
114 ConfigValue::Float(v) => ConfigValue::Float(*v),
115 ConfigValue::Bool(v) => ConfigValue::Bool(*v),
116 #[cfg(feature = "rand")]
117 ConfigValue::Rand(v) => ConfigValue::Rand(*v),
118 })
119 }
120
121 pub(crate) fn collect_keys<'a>(
122 &'a self,
123 prefix: &ConfigKey<'_>,
124 sub: &mut PartialKeyCollector<'a>,
125 ) {
126 if let Some(v) = self.value.get(prefix.as_str()) {
127 for k in v.sub_str.iter() {
128 sub.str_key.insert(k.as_str());
129 }
130 if let Some(i) = v.sub_int {
131 sub.insert_int(i);
132 }
133 }
134 }
135 pub(crate) fn set<K: Borrow<str>, V: Into<ConfigValue<'static>>>(mut self, k: K, v: V) -> Self {
136 let mut c = self.prefixed();
137 c.set(k.borrow(), v);
138 self
139 }
140}
141
142impl ConfigSourceBuilder<'_> {
143 #[allow(single_use_lifetimes)]
145 pub fn set<'b, K: Into<PartialKeyIter<'b>>, V: Into<ConfigValue<'static>>>(
146 &mut self,
147 k: K,
148 v: V,
149 ) {
150 self.push(k);
151 self.insert(v);
152 self.pop();
153 }
154
155 pub fn insert_map<I: IntoIterator<Item = (K, V)>, K: Borrow<str>, V: ConfigSourceAdaptor>(
157 &mut self,
158 iter: I,
159 ) -> Result<(), ConfigError> {
160 for (k, v) in iter {
161 self.push(k.borrow());
162 let x = v.convert_source(self);
163 self.pop();
164 x?;
165 }
166 Ok(())
167 }
168
169 pub fn insert_array<I: IntoIterator<Item = S>, S: ConfigSourceAdaptor>(
171 &mut self,
172 iter: I,
173 ) -> Result<(), ConfigError> {
174 for (i, s) in iter.into_iter().enumerate() {
175 self.push(i);
176 let x = s.convert_source(self);
177 self.pop();
178 x?;
179 }
180 Ok(())
181 }
182
183 #[inline]
184 fn push<'b, K: Into<PartialKeyIter<'b>>>(&mut self, key: K) {
185 let mut curr = self.curr();
186 let mut vs = vec![];
187 let iter: PartialKeyIter<'b> = key.into();
188 for k in iter {
189 let v = self.map.entry(curr.clone()).or_insert_with(HashValue::new);
190 v.push_key(&k);
191 k.update_string(&mut curr);
192 vs.push(k);
193 }
194 self.key.push(curr);
195 }
196
197 #[inline]
198 fn pop(&mut self) {
199 self.key.pop();
200 }
201
202 #[inline]
203 fn curr(&self) -> String {
204 self.key
205 .last()
206 .map(|f| f.as_str())
207 .unwrap_or("")
208 .to_string()
209 }
210
211 #[inline]
213 pub fn insert<V: Into<ConfigValue<'static>>>(&mut self, value: V) {
214 self.count += 1;
215 self.map
216 .entry(self.curr())
217 .or_insert_with(HashValue::new)
218 .push_val(value);
219 }
220
221 pub(crate) fn count(&self) -> usize {
222 self.count
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229
230 #[test]
231 fn hash_source_new_and_name() {
232 let hs = HashSource::new("abc");
233 assert_eq!(hs.name(), "abc");
234 }
235
236 #[test]
237 fn hash_source_prefixed_and_builder_set() {
238 let mut hs = HashSource::new("test");
239 {
240 let mut builder = hs.prefixed();
241 builder.set("a", 1);
242 builder.set("b", "str");
243 }
244 let mut cache_a = crate::key::CacheString::new();
245 let mut ka = cache_a.new_key();
246 ka.push("a");
247 let mut cache_b = crate::key::CacheString::new();
248 let mut kb = cache_b.new_key();
249 kb.push("b");
250 match hs.get_value(&ka) {
251 Some(ConfigValue::Int(1)) => {}
252 _ => panic!("Expected Int(1)"),
253 }
254 match hs.get_value(&kb) {
255 Some(ConfigValue::StrRef("str")) => {}
256 Some(ConfigValue::Str(s)) if s == "str" => {}
257 _ => panic!("Expected StrRef(\"str\")"),
258 }
259 }
260
261 #[test]
262 fn hash_source_collect_keys() {
263 let mut hs = HashSource::new("test");
264 {
265 let mut builder = hs.prefixed();
266 builder.set("foo.bar", 1);
267 builder.set("foo.baz", 2);
268 builder.set("foo[0]", 3);
269 }
270 let mut collector = PartialKeyCollector::new();
271 let mut cache = crate::key::CacheString::new();
272 let mut key = cache.new_key();
273 key.push("foo");
274 hs.collect_keys(&key, &mut collector);
275 assert!(collector.str_key.iter().any(|&x| x == "bar"));
276 assert!(collector.str_key.iter().any(|&x| x == "baz"));
277 assert!(collector.int_key.iter().any(|&x| x == 1));
278 }
279
280 #[test]
281 fn hash_value_push_key_and_val() {
282 let mut hv = HashValue::new();
283 hv.push_key(&PartialKey::Str("abc"));
284 hv.push_key(&PartialKey::Int(2));
285 hv.push_key(&PartialKey::Int(1));
286 hv.push_val("val");
287 hv.push_val("should_not_overwrite");
288 assert!(hv.sub_str.contains("abc"));
289 assert_eq!(hv.sub_int, Some(2));
290 match hv.value {
291 Some(ConfigValue::Str(ref s)) => assert_eq!(s, "val"),
292 Some(ConfigValue::StrRef(s)) => assert_eq!(s, "val"),
293 _ => panic!("Expected Str(\"val\")"),
294 }
295 }
296
297 #[test]
298 fn config_source_builder_insert_map_and_array() {
299 struct Dummy;
300 impl ConfigSourceAdaptor for Dummy {
301 fn convert_source(
302 self,
303 builder: &mut ConfigSourceBuilder<'_>,
304 ) -> Result<(), ConfigError> {
305 builder.insert("dummy");
306 Ok(())
307 }
308 }
309 let mut hs = HashSource::new("test");
310 {
311 let mut builder = hs.prefixed();
312 let map = vec![("k1", Dummy), ("k2", Dummy)];
313 builder.insert_map(map).unwrap();
314 let arr = vec![Dummy, Dummy];
315 builder.insert_array(arr).unwrap();
316 }
317 assert!(hs.value.contains_key("k1"));
318 assert!(hs.value.contains_key("k2"));
319 assert!(hs.value.contains_key("[0]")); }
321
322 #[test]
323 fn config_source_builder_push_pop_curr_count() {
324 let mut hs = HashSource::new("test");
325 let mut builder = hs.prefixed();
326 assert_eq!(builder.curr(), "");
327 builder.push("foo");
328 assert_eq!(builder.curr(), "foo");
329 builder.push("bar");
330 assert_eq!(builder.curr(), "foo.bar");
331 builder.pop();
332 assert_eq!(builder.curr(), "foo");
333 builder.pop();
334 assert_eq!(builder.curr(), "");
335 let c = builder.count();
336 assert_eq!(c, 0);
337 }
338
339 #[test]
340 fn config_source_load_sets_values() {
341 let mut hs = HashSource::new("test");
342 {
343 let mut builder = hs.prefixed();
344 builder.set("x", 42);
345 }
346 let mut target = HashSource::new("target");
347 {
348 let mut builder = target.prefixed();
349 hs.load(&mut builder).unwrap();
350 }
351 let mut cache = crate::key::CacheString::new();
352 let mut key = cache.new_key();
353 key.push("x");
354 match target.get_value(&key) {
355 Some(ConfigValue::Int(42)) => {}
356 _ => panic!("Expected Int(42)"),
357 }
358 }
359
360 #[test]
361 fn hash_source_get_value_variants() {
362 let mut hs = HashSource::new("test");
363 {
364 let mut builder = hs.prefixed();
365 builder.set("s1", "abc");
366 builder.set("i1", 123);
367 builder.set("f1", 3.14);
368 builder.set("b1", true);
369 }
370 let mut cache = crate::key::CacheString::new();
372 let mut key = cache.new_key();
373 key.push("s1");
374 match hs.get_value(&key) {
375 Some(ConfigValue::StrRef("abc")) => {}
376 Some(ConfigValue::Str(s)) if s == "abc" => {}
377 _ => panic!("Expected StrRef(\"abc\")"),
378 }
379 let mut cache = crate::key::CacheString::new();
381 let mut key = cache.new_key();
382 key.push("i1");
383 match hs.get_value(&key) {
384 Some(ConfigValue::Int(123)) => {}
385 _ => panic!("Expected Int(123)"),
386 }
387 let mut cache = crate::key::CacheString::new();
389 let mut key = cache.new_key();
390 key.push("f1");
391 match hs.get_value(&key) {
392 Some(ConfigValue::Float(f)) if (f - 3.14).abs() < 1e-6 => {}
393 _ => panic!("Expected Float(3.14)"),
394 }
395 let mut cache = crate::key::CacheString::new();
397 let mut key = cache.new_key();
398 key.push("b1");
399 match hs.get_value(&key) {
400 Some(ConfigValue::Bool(true)) => {}
401 _ => panic!("Expected Bool(true)"),
402 }
403 let mut cache = crate::key::CacheString::new();
405 let mut key = cache.new_key();
406 key.push("notfound");
407 assert!(hs.get_value(&key).is_none());
408 }
409}