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}