diff options
-rw-r--r-- | src/hashmap.rs | 60 |
1 files changed, 49 insertions, 11 deletions
diff --git a/src/hashmap.rs b/src/hashmap.rs index 4095f15..6700087 100644 --- a/src/hashmap.rs +++ b/src/hashmap.rs @@ -12,6 +12,14 @@ use std::collections::HashMap; use crate::error::Error; +/// An iterator adapter to collect into a HashMap or error if the iterator yields a key twice +/// +/// # Note +/// +/// The FromIterator implementation for this type preallocates a hashmap using the +/// Iterator::size_hint() function for the size of the hashmap. +/// +/// For an adaptor that does not preallocate, have a look at `CollectOnceHashMapNoPrealloc`. pub struct CollectOnceHashMap<K, V, S = std::collections::hash_map::RandomState> where K: Eq + Hash + Debug { @@ -42,22 +50,52 @@ impl<K, V> FromIterator<(K, V)> for CollectOnceHashMap<K, V, std::collections::h } }; - let mut hm = HashMap::with_capacity(iter_size); + CollectOnceHashMap { + inner: collect_into_hm(HashMap::with_capacity(iter_size), iter) + } + } +} - for (element_key, element_value) in iter.into_iter() { - if hm.contains_key(&element_key) { - return CollectOnceHashMap { - inner: Err(Error::DuplicatedKey(element_key)) - } - } else { - hm.insert(element_key, element_value); - } +/// See `CollectOnceHashMap` +pub struct CollectOnceHashMapNoPrealloc<K, V, S = std::collections::hash_map::RandomState> + where K: Eq + Hash + Debug +{ + inner: std::result::Result<HashMap<K, V, S>, Error<K>> +} + +impl<K, V, S> From<CollectOnceHashMapNoPrealloc<K, V, S>> for CollectOnceHashMap<K, V, S> + where K: Eq + Hash + Debug +{ + fn from(cohm: CollectOnceHashMapNoPrealloc<K, V, S>) -> Self { + CollectOnceHashMap { inner: cohm.inner } + } +} + +impl<K, V> FromIterator<(K, V)> for CollectOnceHashMapNoPrealloc<K, V, std::collections::hash_map::RandomState> + where K: Eq + Hash + Debug +{ + fn from_iter<T>(iter: T) -> Self + where T: IntoIterator<Item = (K, V)> + { + CollectOnceHashMapNoPrealloc { + inner: collect_into_hm(HashMap::new(), iter) } + } +} - CollectOnceHashMap { - inner: Ok(hm) +fn collect_into_hm<K, V, T>(mut hm: HashMap<K, V>, iter: T) -> std::result::Result<HashMap<K, V>, Error<K>> + where K: Eq + Hash + Debug, + T: IntoIterator<Item = (K, V)> +{ + for (element_key, element_value) in iter.into_iter() { + if hm.contains_key(&element_key) { + return Err(Error::DuplicatedKey(element_key)) + } else { + hm.insert(element_key, element_value); } } + + Ok(hm) } |