1#![doc(html_root_url = "https://docs.rs/toad-map/0.0.0")]
6#![cfg_attr(any(docsrs, feature = "docs"), feature(doc_cfg))]
7#![allow(clippy::unused_unit)]
10#![deny(missing_docs)]
13#![deny(missing_debug_implementations)]
14#![deny(missing_copy_implementations)]
15#![cfg_attr(not(test), deny(unsafe_code))]
16#![cfg_attr(not(test), warn(unreachable_pub))]
19#![cfg_attr(not(feature = "std"), no_std)]
22
23#[cfg(feature = "alloc")]
24extern crate alloc as std_alloc;
25
26use core::borrow::Borrow;
27use core::hash::Hash;
28use core::ops::{Deref, DerefMut};
29use core::{iter, slice};
30#[cfg(feature = "std")]
31use std::collections::{hash_map, HashMap};
32
33#[cfg(feature = "alloc")]
34use std_alloc::collections::{btree_map, BTreeMap};
35use toad_len::Len;
36
37#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
39pub enum InsertError<V> {
40 Exists(V),
42 CapacityExhausted,
44}
45
46pub trait Map<K: Ord + Eq + Hash, V>:
60 Default + Len + Extend<(K, V)> + FromIterator<(K, V)> + IntoIterator<Item = (K, V)>
61{
62 fn insert(&mut self, key: K, val: V) -> Result<(), InsertError<V>>;
64
65 fn remove<Q>(&mut self, key: &Q) -> Option<V>
67 where K: Borrow<Q>,
68 Q: Hash + Eq + Ord;
69
70 fn get<'a, Q: Hash + Eq + Ord>(&'a self, key: &Q) -> Option<&'a V>
72 where K: Borrow<Q> + 'a;
73
74 fn get_mut<'a, Q: Hash + Eq + Ord>(&'a mut self, key: &Q) -> Option<&'a mut V>
76 where K: Borrow<Q> + 'a;
77
78 fn has<Q: Hash + Eq + Ord>(&self, key: &Q) -> bool
80 where K: Borrow<Q>
81 {
82 self.get(key).is_some()
83 }
84
85 fn iter(&self) -> Iter<'_, K, V>;
87
88 fn iter_mut(&mut self) -> IterMut<'_, K, V>;
90}
91
92#[cfg(feature = "alloc")]
93impl<K: Eq + Hash + Ord, V> Map<K, V> for BTreeMap<K, V> {
94 fn insert(&mut self, key: K, val: V) -> Result<(), InsertError<V>> {
95 match self.insert(key, val).map(InsertError::Exists).ok_or(()) {
96 | Ok(e) => Err(e),
97 | Err(()) => Ok(()),
98 }
99 }
100
101 fn remove<Q: Ord>(&mut self, key: &Q) -> Option<V>
102 where K: Borrow<Q>
103 {
104 self.remove(key)
105 }
106
107 fn get<'a, Q: Hash + Eq + Ord>(&'a self, key: &Q) -> Option<&'a V>
108 where K: Borrow<Q> + 'a
109 {
110 self.get(key)
111 }
112
113 fn get_mut<'a, Q: Hash + Eq + Ord>(&'a mut self, key: &Q) -> Option<&'a mut V>
114 where K: Borrow<Q> + 'a
115 {
116 self.get_mut(key)
117 }
118
119 fn iter(&self) -> Iter<'_, K, V> {
120 Iter { array_iter: None,
121 #[cfg(feature = "std")]
122 hashmap_iter: None,
123 btreemap_iter: Some(self.iter()) }
124 }
125
126 fn iter_mut(&mut self) -> IterMut<'_, K, V> {
127 IterMut { array_iter: None,
128 #[cfg(feature = "std")]
129 hashmap_iter: None,
130 btreemap_iter: Some(self.iter_mut()) }
131 }
132}
133
134#[cfg(feature = "std")]
135impl<K: Eq + Hash + Ord, V> Map<K, V> for HashMap<K, V> {
136 fn iter(&self) -> Iter<'_, K, V> {
137 Iter { array_iter: None,
138 btreemap_iter: None,
139 hashmap_iter: Some(self.iter()) }
140 }
141
142 fn iter_mut(&mut self) -> IterMut<'_, K, V> {
143 IterMut { array_iter: None,
144 btreemap_iter: None,
145 hashmap_iter: Some(self.iter_mut()) }
146 }
147
148 fn get<'a, Q: Hash + Eq + Ord>(&'a self, key: &Q) -> Option<&'a V>
149 where K: Borrow<Q> + 'a
150 {
151 self.get(key)
152 }
153
154 fn get_mut<'a, Q: Hash + Eq + Ord>(&'a mut self, key: &Q) -> Option<&'a mut V>
155 where K: Borrow<Q> + 'a
156 {
157 self.get_mut(key)
158 }
159
160 fn insert(&mut self, key: K, val: V) -> Result<(), InsertError<V>> {
161 match self.insert(key, val).map(InsertError::Exists).ok_or(()) {
162 | Ok(e) => Err(e),
163 | Err(()) => Ok(()),
164 }
165 }
166
167 fn remove<Q: Hash + Eq + Ord>(&mut self, key: &Q) -> Option<V>
168 where K: Borrow<Q>
169 {
170 self.remove(key)
171 }
172}
173
174impl<A: tinyvec::Array<Item = (K, V)>, K: Eq + Hash + Ord, V> Map<K, V> for tinyvec::ArrayVec<A> {
175 fn insert(&mut self, key: K, mut val: V) -> Result<(), InsertError<V>> {
176 match self.iter_mut().find(|(k, _)| k == &&key) {
177 | Some((_, exist)) => {
178 core::mem::swap(exist, &mut val);
179 Err(InsertError::Exists(val))
180 },
181 | None => match self.is_full() {
182 | true => Err(InsertError::CapacityExhausted),
183 | false => {
184 self.push((key, val));
185 Ok(())
186 },
187 },
188 }
189 }
190
191 fn remove<Q: Hash + Eq + Ord>(&mut self, key: &Q) -> Option<V>
192 where K: Borrow<Q>
193 {
194 match self.iter()
195 .enumerate()
196 .find(|(_, (k, _))| Borrow::<Q>::borrow(*k) == key)
197 {
198 | Some((ix, _)) => Some(self.remove(ix).1),
199 | None => None,
200 }
201 }
202
203 fn get<'a, Q: Hash + Eq + Ord>(&'a self, key: &Q) -> Option<&'a V>
204 where K: Borrow<Q> + 'a
205 {
206 match self.iter().find(|(k, _)| Borrow::<Q>::borrow(*k) == key) {
207 | Some((_, v)) => Some(v),
208 | None => None,
209 }
210 }
211
212 fn get_mut<'a, Q: Hash + Eq + Ord>(&'a mut self, key: &Q) -> Option<&'a mut V>
213 where K: Borrow<Q> + 'a
214 {
215 match self.iter_mut()
216 .find(|(k, _)| Borrow::<Q>::borrow(*k) == key)
217 {
218 | Some((_, v)) => Some(v),
219 | None => None,
220 }
221 }
222
223 fn iter(&self) -> Iter<'_, K, V> {
224 Iter { array_iter: Some(self.deref().iter().map(Iter::coerce_array_iter)),
225 #[cfg(feature = "alloc")]
226 btreemap_iter: None,
227 #[cfg(feature = "std")]
228 hashmap_iter: None }
229 }
230
231 fn iter_mut(&mut self) -> IterMut<'_, K, V> {
232 IterMut { array_iter: Some(self.deref_mut().iter_mut().map(IterMut::coerce_array_iter)),
233 #[cfg(feature = "alloc")]
234 btreemap_iter: None,
235 #[cfg(feature = "std")]
236 hashmap_iter: None }
237 }
238}
239
240#[cfg(feature = "alloc")]
241impl<K, V> Map<K, V> for std_alloc::vec::Vec<(K, V)> where K: Ord + Hash
242{
243 fn insert(&mut self, key: K, mut val: V) -> Result<(), InsertError<V>> {
244 match self.iter_mut().find(|(k, _)| k == &&key) {
245 | Some((_, exist)) => {
246 core::mem::swap(exist, &mut val);
247 Err(InsertError::Exists(val))
248 },
249 | None => match self.is_full() {
250 | true => Err(InsertError::CapacityExhausted),
251 | false => {
252 self.push((key, val));
253 Ok(())
254 },
255 },
256 }
257 }
258
259 fn remove<Q>(&mut self, key: &Q) -> Option<V>
260 where K: Borrow<Q>,
261 Q: Hash + Eq + Ord
262 {
263 match self.iter()
264 .enumerate()
265 .find(|(_, (k, _))| Borrow::<Q>::borrow(*k) == key)
266 {
267 | Some((ix, _)) => Some(self.remove(ix).1),
268 | None => None,
269 }
270 }
271
272 fn get<'a, Q: Hash + Eq + Ord>(&'a self, key: &Q) -> Option<&'a V>
273 where K: Borrow<Q> + 'a
274 {
275 match self.iter().find(|(k, _)| Borrow::<Q>::borrow(*k) == key) {
276 | Some((_, v)) => Some(v),
277 | None => None,
278 }
279 }
280
281 fn get_mut<'a, Q: Hash + Eq + Ord>(&'a mut self, key: &Q) -> Option<&'a mut V>
282 where K: Borrow<Q> + 'a
283 {
284 match self.iter_mut()
285 .find(|(k, _)| Borrow::<Q>::borrow(*k) == key)
286 {
287 | Some((_, v)) => Some(v),
288 | None => None,
289 }
290 }
291
292 fn iter(&self) -> Iter<'_, K, V> {
293 Iter { array_iter: Some(self.deref().iter().map(Iter::coerce_array_iter)),
294 #[cfg(feature = "alloc")]
295 btreemap_iter: None,
296 #[cfg(feature = "std")]
297 hashmap_iter: None }
298 }
299
300 fn iter_mut(&mut self) -> IterMut<'_, K, V> {
301 IterMut { array_iter: Some(self.deref_mut().iter_mut().map(IterMut::coerce_array_iter)),
302 #[cfg(feature = "alloc")]
303 btreemap_iter: None,
304 #[cfg(feature = "std")]
305 hashmap_iter: None }
306 }
307}
308
309type ArrayIterCoercer<'a, K, V> = fn(&'a (K, V)) -> (&'a K, &'a V);
310type ArrayIterMapped<'a, K, V> = iter::Map<slice::Iter<'a, (K, V)>, ArrayIterCoercer<'a, K, V>>;
311
312type ArrayIterMutCoercer<'a, K, V> = fn(&'a mut (K, V)) -> (&'a K, &'a mut V);
313type ArrayIterMutMapped<'a, K, V> =
314 iter::Map<slice::IterMut<'a, (K, V)>, ArrayIterMutCoercer<'a, K, V>>;
315
316#[derive(Debug)]
337pub struct Iter<'a, K: Eq + Hash, V> {
338 #[cfg(feature = "std")]
339 hashmap_iter: Option<hash_map::Iter<'a, K, V>>,
340 #[cfg(feature = "alloc")]
341 btreemap_iter: Option<btree_map::Iter<'a, K, V>>,
342 array_iter: Option<ArrayIterMapped<'a, K, V>>,
343}
344
345impl<'a, K: Eq + Hash, V> Iter<'a, K, V> {
346 #[inline(always)]
347 fn coerce_array_iter((k, v): &'a (K, V)) -> (&'a K, &'a V) {
348 (k, v)
349 }
350
351 #[allow(unreachable_code)]
352 fn get_iter(&mut self) -> &mut dyn Iterator<Item = (&'a K, &'a V)> {
353 #[cfg(feature = "std")]
354 {
355 let (a, b, c) = (self.hashmap_iter.as_mut().map(|a| a as &mut _),
356 self.array_iter.as_mut().map(|a| a as &mut _),
357 self.btreemap_iter.as_mut().map(|a| a as &mut _));
358 return a.or(b).or(c).unwrap();
359 };
360
361 #[cfg(feature = "alloc")]
362 {
363 let (a, b) = (self.array_iter.as_mut().map(|a| a as &mut _),
364 self.btreemap_iter.as_mut().map(|a| a as &mut _));
365 return a.or(b).unwrap();
366 }
367
368 self.array_iter.as_mut().map(|a| a as &mut _).unwrap()
370 }
371}
372
373impl<'a, K: Eq + Hash, V> Iterator for Iter<'a, K, V> {
374 type Item = (&'a K, &'a V);
375
376 fn next(&mut self) -> Option<Self::Item> {
377 self.get_iter().next()
378 }
379}
380
381#[derive(Debug)]
402pub struct IterMut<'a, K: Eq + Hash, V> {
403 #[cfg(feature = "std")]
404 hashmap_iter: Option<hash_map::IterMut<'a, K, V>>,
405 #[cfg(feature = "alloc")]
406 btreemap_iter: Option<btree_map::IterMut<'a, K, V>>,
407 array_iter: Option<ArrayIterMutMapped<'a, K, V>>,
408}
409
410impl<'a, K: Eq + Hash, V> IterMut<'a, K, V> {
411 #[inline(always)]
412 fn coerce_array_iter((k, v): &'a mut (K, V)) -> (&'a K, &'a mut V) {
413 (k, v)
414 }
415
416 #[allow(unreachable_code)]
417 fn get_iter(&mut self) -> &mut dyn Iterator<Item = (&'a K, &'a mut V)> {
418 #[cfg(feature = "std")]
419 {
420 let (a, b, c) = (self.hashmap_iter.as_mut().map(|a| a as &mut _),
421 self.array_iter.as_mut().map(|a| a as &mut _),
422 self.btreemap_iter.as_mut().map(|a| a as &mut _));
423 return a.or(b).or(c).unwrap();
424 };
425
426 #[cfg(feature = "alloc")]
427 {
428 let (a, b) = (self.array_iter.as_mut().map(|a| a as &mut _),
429 self.btreemap_iter.as_mut().map(|a| a as &mut _));
430 return a.or(b).unwrap();
431 }
432
433 self.array_iter.as_mut().map(|a| a as &mut _).unwrap()
435 }
436}
437
438impl<'a, K: Eq + Hash, V> Iterator for IterMut<'a, K, V> {
439 type Item = (&'a K, &'a mut V);
440
441 fn next(&mut self) -> Option<Self::Item> {
442 self.get_iter().next()
443 }
444}
445
446#[cfg(test)]
447mod tests {
448 use super::*;
449
450 fn impls(
451 )
452 -> (impl Map<String, String>,
453 impl Map<String, String>,
454 impl Map<String, String>,
455 impl Map<String, String>)
456 {
457 (HashMap::<String, String>::from([("foo".into(), "bar".into())]),
458 BTreeMap::<String, String>::from([("foo".into(), "bar".into())]),
459 tinyvec::array_vec!([(String, String); 16] => ("foo".into(), "bar".into())),
460 vec![("foo".to_string(), "bar".to_string())])
461 }
462
463 macro_rules! each_impl {
464 ($work:expr) => {{
465 let (hm, bt, av, vc) = impls();
466 println!("hashmap");
467 $work(hm);
468 println!("btreemap");
469 $work(bt);
470 println!("arrayvec");
471 $work(av);
472 println!("vec");
473 $work(vc);
474 }};
475 }
476
477 #[test]
478 fn get() {
479 fn test_get<M: Map<String, String>>(map: M) {
480 assert_eq!(map.get(&"foo".to_string()), Some(&"bar".into()));
481 assert_eq!(map.get(&"foot".to_string()), None);
482 }
483
484 each_impl!(test_get);
485 }
486
487 #[test]
488 fn get_mut() {
489 fn test_get_mut<M: Map<String, String>>(mut map: M) {
490 let old = map.get_mut(&"foo".to_string()).unwrap();
491 *old = format!("{}f", old);
492
493 assert_eq!(map.get(&"foo".to_string()), Some(&"barf".into()));
494 }
495
496 each_impl!(test_get_mut);
497 }
498
499 #[test]
500 fn insert() {
501 fn test_insert<M: Map<String, String>>(mut map: M) {
502 let old = map.insert("foot".to_string(), "butt".to_string());
503
504 assert_eq!(old, Ok(()));
505 assert_eq!(map.get(&"foo".to_string()).unwrap().as_str(), "bar");
506 assert_eq!(map.get(&"foot".to_string()).unwrap().as_str(), "butt");
507
508 let old = map.insert("foot".to_string(), "squat".to_string());
509 assert_eq!(old, Err(InsertError::Exists("butt".to_string())));
510 assert_eq!(map.get(&"foot".to_string()).unwrap().as_str(), "squat");
511 }
512
513 each_impl!(test_insert);
514 }
515
516 #[test]
517 fn remove() {
518 fn test_remove<M: Map<String, String>>(mut map: M) {
519 let old = map.remove(&"foo".to_string());
520 assert_eq!(old, Some("bar".to_string()));
521
522 let old = map.remove(&"foo".to_string());
523 assert_eq!(old, None);
524 }
525
526 each_impl!(test_remove);
527 }
528
529 #[test]
530 fn has() {
531 fn test_has<M: Map<String, String>>(map: M) {
532 assert!(map.has(&"foo".to_string()));
533 assert!(!map.has(&"foot".to_string()));
534 }
535
536 each_impl!(test_has);
537 }
538
539 #[test]
540 fn into_iter() {
541 fn test_into_iter<M: Map<String, String>>(mut map: M) {
542 map.insert("a".into(), "a".into()).unwrap();
543 map.insert("b".into(), "b".into()).unwrap();
544 map.insert("c".into(), "c".into()).unwrap();
545
546 let mut kvs = map.into_iter().collect::<Vec<_>>();
547 kvs.sort();
548
549 assert_eq!(kvs,
550 vec![("a".into(), "a".into()),
551 ("b".into(), "b".into()),
552 ("c".into(), "c".into()),
553 ("foo".into(), "bar".into()),]);
554 }
555
556 each_impl!(test_into_iter);
557 }
558
559 #[test]
560 fn iter() {
561 fn test_iter<M: Map<String, String>>(mut map: M) {
562 map.insert("a".into(), "a".into()).unwrap();
563 map.insert("b".into(), "b".into()).unwrap();
564 map.insert("c".into(), "c".into()).unwrap();
565
566 let mut kvs = map.iter().collect::<Vec<_>>();
567 kvs.sort();
568
569 assert_eq!(kvs,
570 vec![(&"a".into(), &"a".into()),
571 (&"b".into(), &"b".into()),
572 (&"c".into(), &"c".into()),
573 (&"foo".into(), &"bar".into()),]);
574 }
575
576 each_impl!(test_iter);
577 }
578
579 #[test]
580 fn iter_mut() {
581 fn test_iter_mut<M: Map<String, String>>(mut map: M) {
582 map.insert("a".into(), "a".into()).unwrap();
583 map.insert("b".into(), "b".into()).unwrap();
584 map.insert("c".into(), "c".into()).unwrap();
585
586 let mut kvs = map.iter_mut().collect::<Vec<_>>();
587 kvs.sort();
588
589 assert_eq!(kvs,
590 vec![(&"a".into(), &mut "a".into()),
591 (&"b".into(), &mut "b".into()),
592 (&"c".into(), &mut "c".into()),
593 (&"foo".into(), &mut "bar".into()),]);
594 }
595
596 each_impl!(test_iter_mut);
597 }
598}