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