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_attr(coverage_nightly, coverage(off))]
227#[cfg(test)]
228mod tests {
229 use super::*;
230
231 #[test]
232 fn hash_source_new_and_name() {
233 let hs = HashSource::new("abc");
234 assert_eq!(hs.name(), "abc");
235 }
236
237 #[test]
238 fn hash_source_prefixed_and_builder_set() {
239 let mut hs = HashSource::new("test");
240 {
241 let mut builder = hs.prefixed();
242 builder.set("a", 1);
243 builder.set("b", "str");
244 }
245 let mut cache_a = crate::key::CacheString::new();
246 let mut ka = cache_a.new_key();
247 ka.push("a");
248 let mut cache_b = crate::key::CacheString::new();
249 let mut kb = cache_b.new_key();
250 kb.push("b");
251 match hs.get_value(&ka) {
252 Some(ConfigValue::Int(1)) => {}
253 _ => panic!("Expected Int(1)"),
254 }
255 match hs.get_value(&kb) {
256 Some(ConfigValue::StrRef("str")) => {}
257 Some(ConfigValue::Str(s)) if s == "str" => {}
258 _ => panic!("Expected StrRef(\"str\")"),
259 }
260 }
261
262 #[test]
263 fn hash_source_collect_keys() {
264 let mut hs = HashSource::new("test");
265 {
266 let mut builder = hs.prefixed();
267 builder.set("foo.bar", 1);
268 builder.set("foo.baz", 2);
269 builder.set("foo[0]", 3);
270 }
271 let mut collector = PartialKeyCollector::new();
272 let mut cache = crate::key::CacheString::new();
273 let mut key = cache.new_key();
274 key.push("foo");
275 hs.collect_keys(&key, &mut collector);
276 assert!(collector.str_key.iter().any(|&x| x == "bar"));
277 assert!(collector.str_key.iter().any(|&x| x == "baz"));
278 assert!(collector.int_key.iter().any(|&x| x == 1));
279 }
280
281 #[test]
282 fn hash_value_push_key_and_val() {
283 let mut hv = HashValue::new();
284 hv.push_key(&PartialKey::Str("abc"));
285 hv.push_key(&PartialKey::Int(2));
286 hv.push_key(&PartialKey::Int(1));
287 hv.push_val("val");
288 hv.push_val("should_not_overwrite");
289 assert!(hv.sub_str.contains("abc"));
290 assert_eq!(hv.sub_int, Some(2));
291 match hv.value {
292 Some(ConfigValue::Str(ref s)) => assert_eq!(s, "val"),
293 Some(ConfigValue::StrRef(s)) => assert_eq!(s, "val"),
294 _ => panic!("Expected Str(\"val\")"),
295 }
296 }
297
298 #[test]
299 fn config_source_builder_insert_map_and_array() {
300 struct Dummy;
301 impl ConfigSourceAdaptor for Dummy {
302 fn convert_source(
303 self,
304 builder: &mut ConfigSourceBuilder<'_>,
305 ) -> Result<(), ConfigError> {
306 builder.insert("dummy");
307 Ok(())
308 }
309 }
310 let mut hs = HashSource::new("test");
311 {
312 let mut builder = hs.prefixed();
313 let map = vec![("k1", Dummy), ("k2", Dummy)];
314 builder.insert_map(map).unwrap();
315 let arr = vec![Dummy, Dummy];
316 builder.insert_array(arr).unwrap();
317 }
318 assert!(hs.value.contains_key("k1"));
319 assert!(hs.value.contains_key("k2"));
320 assert!(hs.value.contains_key("[0]")); }
322
323 #[test]
324 fn config_source_builder_push_pop_curr_count() {
325 let mut hs = HashSource::new("test");
326 let mut builder = hs.prefixed();
327 assert_eq!(builder.curr(), "");
328 builder.push("foo");
329 assert_eq!(builder.curr(), "foo");
330 builder.push("bar");
331 assert_eq!(builder.curr(), "foo.bar");
332 builder.pop();
333 assert_eq!(builder.curr(), "foo");
334 builder.pop();
335 assert_eq!(builder.curr(), "");
336 let c = builder.count();
337 assert_eq!(c, 0);
338 }
339
340 #[test]
341 fn config_source_load_sets_values() {
342 let mut hs = HashSource::new("test");
343 {
344 let mut builder = hs.prefixed();
345 builder.set("x", 42);
346 }
347 let mut target = HashSource::new("target");
348 {
349 let mut builder = target.prefixed();
350 hs.load(&mut builder).unwrap();
351 }
352 let mut cache = crate::key::CacheString::new();
353 let mut key = cache.new_key();
354 key.push("x");
355 match target.get_value(&key) {
356 Some(ConfigValue::Int(42)) => {}
357 _ => panic!("Expected Int(42)"),
358 }
359 }
360
361 #[test]
362 fn hash_source_get_value_variants() {
363 let mut hs = HashSource::new("test");
364 {
365 let mut builder = hs.prefixed();
366 builder.set("s1", "abc");
367 builder.set("i1", 123);
368 builder.set("f1", 3.14);
369 builder.set("b1", true);
370 }
371 let mut cache = crate::key::CacheString::new();
373 let mut key = cache.new_key();
374 key.push("s1");
375 match hs.get_value(&key) {
376 Some(ConfigValue::StrRef("abc")) => {}
377 Some(ConfigValue::Str(s)) if s == "abc" => {}
378 _ => panic!("Expected StrRef(\"abc\")"),
379 }
380 let mut cache = crate::key::CacheString::new();
382 let mut key = cache.new_key();
383 key.push("i1");
384 match hs.get_value(&key) {
385 Some(ConfigValue::Int(123)) => {}
386 _ => panic!("Expected Int(123)"),
387 }
388 let mut cache = crate::key::CacheString::new();
390 let mut key = cache.new_key();
391 key.push("f1");
392 match hs.get_value(&key) {
393 Some(ConfigValue::Float(f)) if (f - 3.14).abs() < 1e-6 => {}
394 _ => panic!("Expected Float(3.14)"),
395 }
396 let mut cache = crate::key::CacheString::new();
398 let mut key = cache.new_key();
399 key.push("b1");
400 match hs.get_value(&key) {
401 Some(ConfigValue::Bool(true)) => {}
402 _ => panic!("Expected Bool(true)"),
403 }
404 let mut cache = crate::key::CacheString::new();
406 let mut key = cache.new_key();
407 key.push("notfound");
408 assert!(hs.get_value(&key).is_none());
409 }
410}