ron/value/
map.rs

1use core::{
2    cmp::{Eq, Ordering},
3    hash::{Hash, Hasher},
4    iter::FromIterator,
5    ops::{Index, IndexMut},
6};
7
8use serde_derive::{Deserialize, Serialize};
9
10use super::Value;
11
12/// A [`Value`] to [`Value`] map.
13///
14/// This structure either uses a [`BTreeMap`](alloc::collections::BTreeMap) or the
15/// [`IndexMap`](indexmap::IndexMap) internally.
16/// The latter can be used by enabling the `indexmap` feature. This can be used
17/// to preserve the order of the parsed map.
18#[derive(Clone, Debug, Default, Deserialize, Serialize)]
19#[serde(transparent)]
20pub struct Map(pub(crate) MapInner);
21
22#[cfg(not(feature = "indexmap"))]
23type MapInner = alloc::collections::BTreeMap<Value, Value>;
24#[cfg(feature = "indexmap")]
25type MapInner = indexmap::IndexMap<Value, Value, std::collections::hash_map::RandomState>;
26
27impl Map {
28    /// Creates a new, empty [`Map`].
29    #[must_use]
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    /// Returns the number of elements in the map.
35    #[must_use]
36    pub fn len(&self) -> usize {
37        self.0.len()
38    }
39
40    /// Returns `true` if `self.len() == 0`, `false` otherwise.
41    #[must_use]
42    pub fn is_empty(&self) -> bool {
43        self.0.is_empty()
44    }
45
46    /// Immutably looks up an element by its `key`.
47    #[must_use]
48    pub fn get(&self, key: &Value) -> Option<&Value> {
49        self.0.get(key)
50    }
51
52    /// Mutably looks up an element by its `key`.
53    pub fn get_mut(&mut self, key: &Value) -> Option<&mut Value> {
54        self.0.get_mut(key)
55    }
56
57    /// Inserts a new element, returning the previous element with this `key` if
58    /// there was any.
59    pub fn insert(&mut self, key: impl Into<Value>, value: impl Into<Value>) -> Option<Value> {
60        self.0.insert(key.into(), value.into())
61    }
62
63    /// Removes an element by its `key`.
64    pub fn remove(&mut self, key: &Value) -> Option<Value> {
65        #[cfg(feature = "indexmap")]
66        {
67            self.0.shift_remove(key)
68        }
69        #[cfg(not(feature = "indexmap"))]
70        {
71            self.0.remove(key)
72        }
73    }
74
75    /// Iterate all key-value pairs.
76    #[must_use]
77    pub fn iter(&self) -> impl DoubleEndedIterator<Item = (&Value, &Value)> {
78        self.0.iter()
79    }
80
81    /// Iterate all key-value pairs mutably.
82    #[must_use]
83    pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (&Value, &mut Value)> {
84        self.0.iter_mut()
85    }
86
87    /// Iterate all keys.
88    #[must_use]
89    pub fn keys(&self) -> impl DoubleEndedIterator<Item = &Value> {
90        self.0.keys()
91    }
92
93    /// Iterate all values.
94    #[must_use]
95    pub fn values(&self) -> impl DoubleEndedIterator<Item = &Value> {
96        self.0.values()
97    }
98
99    /// Iterate all values mutably.
100    #[must_use]
101    pub fn values_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut Value> {
102        self.0.values_mut()
103    }
104
105    /// Retains only the elements specified by the `keep` predicate.
106    ///
107    /// In other words, remove all pairs `(k, v)` for which `keep(&k, &mut v)`
108    /// returns `false`.
109    ///
110    /// The elements are visited in iteration order.
111    pub fn retain<F>(&mut self, keep: F)
112    where
113        F: FnMut(&Value, &mut Value) -> bool,
114    {
115        self.0.retain(keep);
116    }
117}
118
119impl Index<&Value> for Map {
120    type Output = Value;
121
122    #[allow(clippy::expect_used)]
123    fn index(&self, index: &Value) -> &Self::Output {
124        self.get(index).expect("no entry found for key")
125    }
126}
127
128impl IndexMut<&Value> for Map {
129    #[allow(clippy::expect_used)]
130    fn index_mut(&mut self, index: &Value) -> &mut Self::Output {
131        self.get_mut(index).expect("no entry found for key")
132    }
133}
134
135impl IntoIterator for Map {
136    type Item = (Value, Value);
137
138    type IntoIter = <MapInner as IntoIterator>::IntoIter;
139
140    fn into_iter(self) -> Self::IntoIter {
141        self.0.into_iter()
142    }
143}
144
145impl<K: Into<Value>, V: Into<Value>> FromIterator<(K, V)> for Map {
146    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
147        Map(iter
148            .into_iter()
149            .map(|(key, value)| (key.into(), value.into()))
150            .collect())
151    }
152}
153
154/// Note: equality is only given if both values and order of values match
155impl PartialEq for Map {
156    fn eq(&self, other: &Map) -> bool {
157        self.cmp(other).is_eq()
158    }
159}
160
161/// Note: equality is only given if both values and order of values match
162impl Eq for Map {}
163
164impl PartialOrd for Map {
165    fn partial_cmp(&self, other: &Map) -> Option<Ordering> {
166        Some(self.cmp(other))
167    }
168}
169
170impl Ord for Map {
171    fn cmp(&self, other: &Map) -> Ordering {
172        self.iter().cmp(other.iter())
173    }
174}
175
176impl Hash for Map {
177    fn hash<H: Hasher>(&self, state: &mut H) {
178        self.iter().for_each(|x| x.hash(state));
179    }
180}
181
182#[cfg(test)]
183mod tests {
184    use alloc::{vec, vec::Vec};
185
186    use super::{Map, Value};
187
188    #[test]
189    fn map_usage() {
190        let mut map = Map::new();
191        assert_eq!(map.len(), 0);
192        assert!(map.is_empty());
193
194        map.insert("a", 42);
195        assert_eq!(map.len(), 1);
196        assert!(!map.is_empty());
197
198        assert_eq!(map.keys().collect::<Vec<_>>(), vec![&Value::from("a")]);
199        assert_eq!(map.values().collect::<Vec<_>>(), vec![&Value::from(42)]);
200        assert_eq!(
201            map.iter().collect::<Vec<_>>(),
202            vec![(&Value::from("a"), &Value::from(42))]
203        );
204
205        assert_eq!(map.get(&Value::from("a")), Some(&Value::from(42)));
206        assert_eq!(map.get(&Value::from("b")), None);
207        assert_eq!(map.get_mut(&Value::from("a")), Some(&mut Value::from(42)));
208        assert_eq!(map.get_mut(&Value::from("b")), None);
209
210        map[&Value::from("a")] = Value::from(24);
211        assert_eq!(&map[&Value::from("a")], &Value::from(24));
212
213        for (key, value) in map.iter_mut() {
214            if key == &Value::from("a") {
215                *value = Value::from(42);
216            }
217        }
218        assert_eq!(&map[&Value::from("a")], &Value::from(42));
219
220        map.values_mut().for_each(|value| *value = Value::from(24));
221        assert_eq!(&map[&Value::from("a")], &Value::from(24));
222
223        map.insert("b", 42);
224        assert_eq!(map.len(), 2);
225        assert!(!map.is_empty());
226        assert_eq!(map.get(&Value::from("a")), Some(&Value::from(24)));
227        assert_eq!(map.get(&Value::from("b")), Some(&Value::from(42)));
228
229        map.retain(|key, value| {
230            if key == &Value::from("a") {
231                *value = Value::from(42);
232                true
233            } else {
234                false
235            }
236        });
237        assert_eq!(map.len(), 1);
238        assert_eq!(map.get(&Value::from("a")), Some(&Value::from(42)));
239        assert_eq!(map.get(&Value::from("b")), None);
240
241        assert_eq!(map.remove(&Value::from("b")), None);
242        assert_eq!(map.remove(&Value::from("a")), Some(Value::from(42)));
243        assert_eq!(map.remove(&Value::from("a")), None);
244    }
245
246    #[cfg(feature = "std")]
247    #[test]
248    fn map_hash() {
249        assert_same_hash(&Map::new(), &Map::new());
250        assert_same_hash(
251            &[("a", 42)].into_iter().collect(),
252            &[("a", 42)].into_iter().collect(),
253        );
254        assert_same_hash(
255            &[("b", 24), ("c", 42)].into_iter().collect(),
256            &[("b", 24), ("c", 42)].into_iter().collect(),
257        );
258    }
259
260    #[cfg(feature = "std")]
261    fn assert_same_hash(a: &Map, b: &Map) {
262        use core::hash::{Hash, Hasher};
263        use std::collections::hash_map::DefaultHasher;
264
265        assert_eq!(a, b);
266        assert!(a.cmp(b).is_eq());
267        assert_eq!(a.partial_cmp(b), Some(core::cmp::Ordering::Equal));
268
269        let mut hasher = DefaultHasher::new();
270        a.hash(&mut hasher);
271        let h1 = hasher.finish();
272
273        let mut hasher = DefaultHasher::new();
274        b.hash(&mut hasher);
275        let h2 = hasher.finish();
276
277        assert_eq!(h1, h2);
278    }
279
280    #[test]
281    #[should_panic(expected = "no entry found for key")]
282    fn map_index_panic() {
283        let _ = &Map::new()[&Value::Unit];
284    }
285
286    #[test]
287    #[should_panic(expected = "no entry found for key")]
288    fn map_index_mut_panic() {
289        let _ = &mut Map::new()[&Value::Unit];
290    }
291}