seq_map/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/piot/seq-map
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5use std::{
6    collections::HashMap,
7    error::Error,
8    fmt::{self, Debug, Display, Formatter},
9    hash::{Hash, Hasher},
10    ops::Index,
11};
12
13/// A deterministic map that preserves insertion order.
14///
15/// Internally, it uses a [`HashMap`] for quick key lookups and a [`Vec`] to maintain the order
16/// of inserted key-value pairs.
17#[derive(Clone)]
18pub struct SeqMap<K, V> {
19    key_to_index: HashMap<K, usize>, // Maps keys to their index in `entries`
20    entries: Vec<(K, V)>,            // Stores key-value pairs in insertion order
21}
22
23impl<K, V> Hash for SeqMap<K, V>
24where
25    K: Hash,
26    V: Hash,
27{
28    fn hash<H: Hasher>(&self, state: &mut H) {
29        for (key, value) in &self.entries {
30            key.hash(state);
31            value.hash(state);
32        }
33    }
34}
35
36impl<K, V> PartialEq for SeqMap<K, V>
37where
38    K: Eq,
39    V: Eq,
40{
41    fn eq(&self, other: &Self) -> bool {
42        if self.entries.len() != other.entries.len() {
43            return false;
44        }
45        self.entries
46            .iter()
47            .zip(other.entries.iter())
48            .all(|(a, b)| a == b)
49    }
50}
51
52impl<K, V> Eq for SeqMap<K, V>
53where
54    K: Eq,
55    V: Eq,
56{
57}
58
59impl<K, V> Display for SeqMap<K, V>
60where
61    K: Eq + Hash + Display,
62    V: Display,
63{
64    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65        write!(f, "SeqMap({})", self.entries.len())?;
66        for (key, value) in &self.entries {
67            write!(f, "\n{key}: {value}")?;
68        }
69        Ok(())
70    }
71}
72
73impl<K, V> Debug for SeqMap<K, V>
74where
75    K: Eq + Hash + Debug,
76    V: Debug,
77{
78    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
79        write!(f, "SeqMap(")?;
80        let mut first = true;
81        for (key, value) in &self.entries {
82            if !first {
83                write!(f, ", ")?;
84            }
85            first = false;
86            write!(f, "{key:?}: {value:?}")?;
87        }
88        write!(f, ")")
89    }
90}
91
92/// Errors that can occur when manipulating a `SeqMap`.
93#[derive(Debug)]
94pub enum SeqMapError {
95    /// Occurs when attempting to insert a key that already exists in the map.
96    KeyAlreadyExists,
97}
98
99impl Display for SeqMapError {
100    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
101        match self {
102            SeqMapError::KeyAlreadyExists => write!(f, "The key already exists in the SeqMap."),
103        }
104    }
105}
106
107impl Error for SeqMapError {}
108
109impl<K, V> SeqMap<K, V>
110where
111    K: Eq + Hash + Clone, // Clone is because we add it to two containers
112{
113    /// Creates a new, empty `SeqMap`.
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use seq_map::SeqMap;
119    /// let map: SeqMap<String, i32> = SeqMap::new();
120    /// ```
121    pub fn new() -> Self {
122        Self {
123            key_to_index: HashMap::new(),
124            entries: Vec::new(),
125        }
126    }
127
128    /// Inserts a key-value pair into the map.
129    ///
130    /// Returns an error if the key already exists.
131    ///
132    /// # Errors
133    ///
134    /// Returns `SeqMapError::KeyAlreadyExists` if the key is already present.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use seq_map::SeqMap;
140    /// let mut map = SeqMap::new();
141    /// map.insert("key".to_string(), 42).unwrap();
142    /// assert!(map.insert("key".to_string(), 43).is_err());
143    /// ```
144    pub fn insert(&mut self, key: K, value: V) -> Result<(), SeqMapError> {
145        #[allow(clippy::map_entry)]
146        if self.key_to_index.contains_key(&key) {
147            Err(SeqMapError::KeyAlreadyExists)
148        } else {
149            self.entries.push((key.clone(), value));
150            self.key_to_index.insert(key, self.entries.len() - 1);
151            Ok(())
152        }
153    }
154
155    /// Checks if the map contains a key.
156    pub fn contains_key(&self, key: &K) -> bool {
157        self.key_to_index.contains_key(key)
158    }
159
160    /// Returns a mutable reference to the value corresponding to the key.
161    ///
162    /// Returns `None` if the key does not exist.
163    ///
164    /// # Examples
165    ///
166    /// ```
167    /// use seq_map::SeqMap;
168    /// let mut map = SeqMap::new();
169    /// map.insert("key".to_string(), 42).unwrap();
170    /// if let Some(value) = map.get_mut(&"key".to_string()) {
171    ///     *value = 100;
172    /// }
173    /// assert_eq!(map[&"key".to_string()], 100);
174    /// ```
175    pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
176        self.key_to_index
177            .get(key)
178            .map(|&index| &mut self.entries[index].1)
179    }
180
181    /// Returns the number of key-value pairs in the map.
182    ///
183    /// # Examples
184    ///
185    /// ```
186    /// use seq_map::SeqMap;
187    /// let mut map = SeqMap::new();
188    /// assert_eq!(map.len(), 0);
189    /// map.insert("key", 42).unwrap();
190    /// assert_eq!(map.len(), 1);
191    /// ```
192    pub fn len(&self) -> usize {
193        self.entries.len()
194    }
195
196    /// Returns `true` if the map contains no elements.
197    ///
198    /// # Examples
199    ///
200    /// ```
201    /// use seq_map::SeqMap;
202    /// let map: SeqMap<String, i32> = SeqMap::new();
203    /// assert!(map.is_empty());
204    /// ```
205    pub fn is_empty(&self) -> bool {
206        self.entries.is_empty()
207    }
208
209    /// Returns an iterator over the keys of the map in insertion order.
210    ///
211    /// # Examples
212    ///
213    /// ```
214    /// use seq_map::SeqMap;
215    /// let mut map = SeqMap::new();
216    /// map.insert("a".to_string(), 1).unwrap();
217    /// map.insert("b".to_string(), 2).unwrap();
218    /// let keys: Vec<_> = map.keys().cloned().collect();
219    /// assert_eq!(keys, vec!["a", "b"]);
220    /// ```
221    pub fn keys(&self) -> impl Iterator<Item = &K> {
222        self.entries.iter().map(|(k, _)| k)
223    }
224
225    /// Returns an iterator over the values of the map in insertion order.
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// use seq_map::SeqMap;
231    /// let mut map = SeqMap::new();
232    /// map.insert("a".to_string(), 1).unwrap();
233    /// map.insert("b".to_string(), 2).unwrap();
234    /// let values: Vec<_> = map.values().cloned().collect();
235    /// assert_eq!(values, vec![1, 2]);
236    /// ```
237    pub fn values(&self) -> impl Iterator<Item = &V> {
238        self.entries.iter().map(|(_, v)| v)
239    }
240
241    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
242        self.entries.iter_mut().map(|(_, v)| v)
243    }
244
245    pub fn get_index(&self, key: &K) -> Option<usize> {
246        self.key_to_index.get(key).copied()
247    }
248
249    pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
250        self.entries.iter().map(|(k, v)| (k, v))
251    }
252
253    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, &mut V)> {
254        self.entries.iter_mut().map(|(k, v)| (&*k, v))
255    }
256
257    /// Retrieves a reference to the value corresponding to the key.
258    ///
259    /// This method performs a faster lookup using the internal `HashMap`.
260    ///
261    /// For a slower but simpler lookup, see [`slow_get`](Self::slow_get).
262    ///
263    /// # Examples
264    ///
265    /// ```
266    /// use seq_map::SeqMap;
267    /// let mut map = SeqMap::new();
268    /// map.insert("key".to_string(), 42).unwrap();
269    /// assert_eq!(map.get(&"key".to_string()), Some(&42));
270    /// ```
271    pub fn get(&self, key: &K) -> Option<&V> {
272        self.key_to_index
273            .get(key)
274            .map(|&index| &self.entries[index].1)
275    }
276
277    /// Removes all elements from the map
278    pub fn clear(&mut self) {
279        self.key_to_index.clear();
280        self.entries.clear();
281    }
282
283    /// Removes a key from the map, returning the value if it existed
284    pub fn remove(&mut self, key: &K) -> Option<V> {
285        if let Some(&index) = self.key_to_index.get(key) {
286            self.key_to_index.remove(key);
287            // Update indices for all elements after the removed one
288            for k in self.entries[index + 1..].iter().map(|(k, _)| k) {
289                if let Some(idx) = self.key_to_index.get_mut(k) {
290                    *idx -= 1;
291                }
292            }
293            Some(self.entries.remove(index).1)
294        } else {
295            None
296        }
297    }
298
299    /// Removes all elements from the map and returns them as an iterator
300    pub fn drain(&mut self) -> impl Iterator<Item = (K, V)> + '_ {
301        self.key_to_index.clear();
302        self.entries.drain(..)
303    }
304}
305
306impl<K, V> Index<&K> for SeqMap<K, V>
307where
308    K: Eq + Hash + Clone,
309    V: Clone,
310{
311    type Output = V;
312
313    /// Allows accessing values using the indexing syntax (`map[&key]`).
314    ///
315    /// # Panics
316    ///
317    /// Panics if the key is not present in the map.
318    ///
319    /// # Examples
320    ///
321    /// ```
322    /// use seq_map::SeqMap;
323    /// let mut map = SeqMap::new();
324    /// map.insert("key".to_string(), 42).unwrap();
325    /// assert_eq!(map[&"key".to_string()], 42);
326    /// ```
327    fn index(&self, key: &K) -> &Self::Output {
328        self.get(key).expect("Key not found in SeqMap")
329    }
330}
331
332impl<K, V> From<&[(K, V)]> for SeqMap<K, V>
333where
334    K: Eq + Hash + Clone,
335    V: Clone,
336{
337    /// Creates a `SeqMap` from a slice of key-value pairs.
338    ///
339    /// If duplicate keys are present in the slice, the first occurrence is kept, and subsequent
340    /// duplicates are ignored.
341    ///
342    /// # Examples
343    ///
344    /// ```
345    /// use seq_map::SeqMap;
346    /// let pairs = vec![
347    ///     ("a".to_string(), 1),
348    ///     ("b".to_string(), 2),
349    /// ];
350    /// let map: SeqMap<_, _> = SeqMap::from(&pairs[..]);
351    /// assert_eq!(map.len(), 2);
352    /// ```
353    fn from(slice: &[(K, V)]) -> Self {
354        let mut map = SeqMap::new();
355        for (key, value) in slice {
356            // Ignore errors to keep the first occurrence
357            let _ = map.insert(key.clone(), value.clone());
358        }
359        map
360    }
361}
362
363/// Creates a `SeqMap` from an iterator of key-value pairs.
364///
365/// If duplicate keys are present in the iterator, the first occurrence is kept,
366/// and subsequent duplicates are silently ignored.
367impl<K: Hash, V> FromIterator<(K, V)> for SeqMap<K, V>
368where
369    K: Eq + Clone,
370    V: Clone,
371{
372    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
373        let mut map = SeqMap::new();
374        for (k, v) in iter {
375            let _ = map.insert(k, v); // Intentionally ignore errors for this trait
376        }
377        map
378    }
379}
380
381impl<'a, K, V> IntoIterator for &'a SeqMap<K, V>
382where
383    K: Eq + Hash + Clone,
384{
385    type Item = (&'a K, &'a V);
386    type IntoIter = std::iter::Map<std::slice::Iter<'a, (K, V)>, fn(&'a (K, V)) -> (&'a K, &'a V)>;
387
388    /// Returns an iterator over references to the key-value pairs in insertion order.
389    ///
390    /// This implementation allows you to iterate over references to the keys and values
391    /// without consuming the `SeqMap`. It's useful for scenarios where you want to inspect
392    /// the contents of the map without modifying it.
393    ///
394    /// # Examples
395    ///
396    /// ## Iterating Over References
397    ///
398    /// ```rust
399    /// use seq_map::SeqMap;
400    ///
401    /// let mut map = SeqMap::new();
402    /// map.insert("a".to_string(), 1).unwrap();
403    /// map.insert("b".to_string(), 2).unwrap();
404    /// map.insert("c".to_string(), 3).unwrap();
405    ///
406    /// for (key, value) in &map {
407    ///     println!("{}: {}", key, value);
408    /// }
409    /// ```
410    ///
411    /// ## Collecting into a Vector of References
412    ///
413    /// ```rust
414    /// use seq_map::SeqMap;
415    ///
416    /// let mut map = SeqMap::new();
417    /// map.insert("x".to_string(), 100).unwrap();
418    /// map.insert("y".to_string(), 200).unwrap();
419    ///
420    /// let entries: Vec<_> = (&map).into_iter().collect();
421    /// assert_eq!(
422    ///     entries,
423    ///     vec![
424    ///         (&"x".to_string(), &100),
425    ///         (&"y".to_string(), &200),
426    ///     ]
427    /// );
428    /// ```
429    fn into_iter(self) -> Self::IntoIter {
430        self.entries.iter().map(|(k, v)| (k, v))
431    }
432}
433
434impl<K, V> Default for SeqMap<K, V> {
435    /// Creates a new, empty `SeqMap`.
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// use seq_map::SeqMap;
441    /// let map: SeqMap<String, i32> = SeqMap::default();
442    /// ```
443    fn default() -> Self {
444        Self {
445            key_to_index: HashMap::default(),
446            entries: Vec::default(),
447        }
448    }
449}
450
451// Mutable reference iterator
452impl<'a, K, V> IntoIterator for &'a mut SeqMap<K, V>
453where
454    K: Eq + Hash + Clone,
455{
456    type Item = (&'a K, &'a mut V);
457    type IntoIter =
458        std::iter::Map<std::slice::IterMut<'a, (K, V)>, fn(&'a mut (K, V)) -> (&'a K, &'a mut V)>;
459
460    fn into_iter(self) -> Self::IntoIter {
461        self.entries.iter_mut().map(|(k, v)| (&*k, v))
462    }
463}
464
465// Consuming iterator
466impl<K, V> IntoIterator for SeqMap<K, V>
467where
468    K: Eq + Hash + Clone,
469{
470    type Item = (K, V);
471    type IntoIter = std::vec::IntoIter<(K, V)>;
472
473    fn into_iter(self) -> Self::IntoIter {
474        self.entries.into_iter()
475    }
476}
477
478impl<K, V> SeqMap<K, V>
479where
480    K: Eq + Hash + Clone,
481{
482    pub fn into_keys(self) -> impl Iterator<Item = K> {
483        self.entries.into_iter().map(|(k, _)| k)
484    }
485
486    pub fn into_values(self) -> impl Iterator<Item = V> {
487        self.entries.into_iter().map(|(_, v)| v)
488    }
489}
490
491impl<K, V> Extend<(K, V)> for SeqMap<K, V>
492where
493    K: Eq + Hash + Clone,
494{
495    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
496        for (k, v) in iter {
497            let _ = self.insert(k, v);
498        }
499    }
500}
501
502#[cfg(test)]
503mod tests {
504    use crate::SeqMap;
505
506    #[test]
507    fn test_clear_and_drain() {
508        let mut map = SeqMap::new();
509        map.insert("a", 1).unwrap();
510        map.insert("b", 2).unwrap();
511
512        let mut other_map = SeqMap::new();
513        for (k, v) in map.drain() {
514            other_map.insert(k, v).unwrap();
515        }
516        assert!(map.is_empty());
517        assert_eq!(other_map.len(), 2);
518
519        other_map.clear();
520        assert!(other_map.is_empty());
521        assert_eq!(other_map.key_to_index.len(), 0);
522        assert_eq!(other_map.entries.len(), 0);
523    }
524}