rustfoundry/settings/
collections.rs

1//! Collections that implement [`Settings`] trait.
2//!
3//! [`Settings`]: super::Settings
4
5use super::Settings;
6use indexmap::map::{IntoIter, Iter, IterMut};
7use indexmap::IndexMap;
8use serde::de::DeserializeOwned;
9use serde::{Deserialize, Serialize};
10use std::collections::HashMap;
11use std::fmt::{Debug, Display};
12use std::hash::Hash;
13use std::ops::{Deref, DerefMut};
14
15/// An ordered hash map of items.
16///
17/// This is essentially a thin wrapper around [`indexmap::IndexMap`] that implements [`Settings`]
18/// trait.
19///
20/// For settings it's preferable for hash map items to be ordered, otherwise generation of
21/// default configuration will add a lot of ordering-related diffs between the runs which is
22/// undesirable.
23///
24/// This is the reason why [`Settings`] trait is not implemented for [`std::collections::HashMap`].
25/// In contrast, [`std::collections::BTreeMap`] provides lexicographic ordering of the keys, but
26/// its usage is still discoraged as the ordering is implicit and can differ from the intended by
27/// an implementor.
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct Map<K, V>(#[serde(bound = "")] IndexMap<K, V>)
30where
31    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
32    V: Settings;
33
34impl<K, V> Default for Map<K, V>
35where
36    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
37    V: Settings,
38{
39    fn default() -> Self {
40        Self(Default::default())
41    }
42}
43
44impl<K, V> Deref for Map<K, V>
45where
46    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
47    V: Settings,
48{
49    type Target = IndexMap<K, V>;
50
51    fn deref(&self) -> &Self::Target {
52        &self.0
53    }
54}
55
56impl<K, V> DerefMut for Map<K, V>
57where
58    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
59    V: Settings,
60{
61    fn deref_mut(&mut self) -> &mut Self::Target {
62        &mut self.0
63    }
64}
65
66impl<K, V> From<Map<K, V>> for IndexMap<K, V>
67where
68    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
69    V: Settings,
70{
71    fn from(value: Map<K, V>) -> Self {
72        value.0
73    }
74}
75
76impl<K, V> From<IndexMap<K, V>> for Map<K, V>
77where
78    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
79    V: Settings,
80{
81    fn from(value: IndexMap<K, V>) -> Self {
82        Self(value)
83    }
84}
85
86impl<K, V> FromIterator<(K, V)> for Map<K, V>
87where
88    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
89    V: Settings,
90{
91    fn from_iter<I: IntoIterator<Item = (K, V)>>(iterable: I) -> Self {
92        Self(IndexMap::from_iter(iterable))
93    }
94}
95
96impl<'a, K, V> IntoIterator for &'a Map<K, V>
97where
98    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
99    V: Settings,
100{
101    type Item = (&'a K, &'a V);
102    type IntoIter = Iter<'a, K, V>;
103
104    fn into_iter(self) -> Self::IntoIter {
105        self.0.iter()
106    }
107}
108
109impl<'a, K, V> IntoIterator for &'a mut Map<K, V>
110where
111    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
112    V: Settings,
113{
114    type Item = (&'a K, &'a mut V);
115    type IntoIter = IterMut<'a, K, V>;
116
117    fn into_iter(self) -> Self::IntoIter {
118        self.0.iter_mut()
119    }
120}
121
122impl<K, V> IntoIterator for Map<K, V>
123where
124    K: Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
125    V: Settings,
126{
127    type Item = (K, V);
128    type IntoIter = IntoIter<K, V>;
129
130    fn into_iter(self) -> Self::IntoIter {
131        self.0.into_iter()
132    }
133}
134
135impl<K, V> Settings for Map<K, V>
136where
137    K: Display + Eq + Hash + Clone + Serialize + DeserializeOwned + Debug + 'static,
138    V: Settings,
139{
140    fn add_docs(
141        &self,
142        parent_key: &[String],
143        docs: &mut HashMap<Vec<String>, &'static [&'static str]>,
144    ) {
145        for (k, v) in self.0.iter() {
146            let mut key = parent_key.to_vec();
147
148            key.push(k.to_string());
149
150            v.add_docs(&key, docs);
151        }
152    }
153}