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}