summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Beyer <mail@beyermatthias.de>2021-09-01 15:15:43 +0200
committerMatthias Beyer <mail@beyermatthias.de>2021-09-01 15:15:53 +0200
commitb3620079ad18aa84ec57245bcd0723d1dc24656e (patch)
tree71e28389f80e964b6c1ba9cdee92ee069672d7de
parent0c9ad7e14fd0b828ddbd02a35251900c960abbb7 (diff)
Add same iterator adapter for BTreeMap
Signed-off-by: Matthias Beyer <mail@beyermatthias.de>
-rw-r--r--README.md15
-rw-r--r--src/btreemap.rs99
-rw-r--r--src/lib.rs3
3 files changed, 114 insertions, 3 deletions
diff --git a/README.md b/README.md
index e0ec639..2af017b 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
# collect-once-hashmap
-This crate provides a type `CollectOnceHashMap` that can be collected from an
-iterator just like a normal `std::collections::HashMap`, but it makes sure that
-a duplicated key results in an error.
+This crate provides a type `CollectOnceHashMap` (and the same for `BTreeMap`
+that can be collected from an iterator just like a normal
+`std::collections::HashMap`, but it makes sure that a duplicated key results in
+an error.
Example:
@@ -15,6 +16,14 @@ let hm = vec![(1, 1), (1, 2)]
assert!(hm.is_err());
assert!(std::matches!(hm, Err(Error::DuplicatedKey(1))));
+
+let bm = vec![(1, 1), (1, 2)]
+ .into_iter()
+ .collect::<CollectOnceBTreeMap<u8, u8>>()
+ .into_inner();
+
+assert!(bm.is_err());
+assert!(std::matches!(bm, Err(Error::DuplicatedKey(1))));
```
diff --git a/src/btreemap.rs b/src/btreemap.rs
new file mode 100644
index 0000000..2ada9aa
--- /dev/null
+++ b/src/btreemap.rs
@@ -0,0 +1,99 @@
+use std::cmp::Ord;
+use std::collections::BTreeMap;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::iter::FromIterator;
+use std::iter::IntoIterator;
+
+#[derive(Debug, thiserror::Error)]
+pub enum Error<K>
+ where K: Debug,
+{
+ #[error("duplicated key in iterator: {:?}", _0)]
+ DuplicatedKey(K),
+
+ #[error("unknown error")]
+ Unknown,
+}
+
+pub struct CollectOnceBTreeMap<K, V>
+ where K: Eq + Ord + Hash + Debug
+{
+ inner: std::result::Result<BTreeMap<K, V>, Error<K>>
+}
+
+impl<K, V> CollectOnceBTreeMap<K, V>
+ where K: Eq + Ord + Hash + Debug
+{
+ pub fn into_inner(self) -> std::result::Result<BTreeMap<K, V>, Error<K>> {
+ self.inner
+ }
+}
+
+impl<K, V> FromIterator<(K, V)> for CollectOnceBTreeMap<K, V>
+ where K: Eq + Ord + Hash + Debug
+{
+ fn from_iter<T>(iter: T) -> Self
+ where T: IntoIterator<Item = (K, V)>
+ {
+ let mut hm = BTreeMap::new();
+
+ for (element_key, element_value) in iter.into_iter() {
+ if hm.contains_key(&element_key) {
+ return CollectOnceBTreeMap {
+ inner: Err(Error::DuplicatedKey(element_key))
+ }
+ } else {
+ hm.insert(element_key, element_value);
+ }
+ }
+
+ CollectOnceBTreeMap {
+ inner: Ok(hm)
+ }
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+ use super::CollectOnceBTreeMap;
+ use super::Error;
+
+ #[test]
+ fn test_empty() {
+ let hm = vec![]
+ .into_iter()
+ .collect::<CollectOnceBTreeMap<u8, u8>>()
+ .into_inner()
+ .unwrap();
+
+ assert_eq!(0, hm.keys().count());
+ }
+
+ #[test]
+ fn test_simple() {
+ let hm = vec![(1, 1)]
+ .into_iter()
+ .collect::<CollectOnceBTreeMap<u8, u8>>()
+ .into_inner()
+ .unwrap();
+
+ assert_eq!(1, hm.keys().count());
+ assert!(hm.contains_key(&1));
+ assert!(hm.keys().all(|k| *k == 1));
+ assert!(hm.values().all(|k| *k == 1));
+ }
+
+ #[test]
+ fn test_duplicate() {
+ let hm = vec![(1, 1), (1, 2)]
+ .into_iter()
+ .collect::<CollectOnceBTreeMap<u8, u8>>()
+ .into_inner();
+
+ assert!(hm.is_err());
+ assert!(std::matches!(hm, Err(Error::DuplicatedKey(1))));
+ }
+}
+
diff --git a/src/lib.rs b/src/lib.rs
index f4fcff3..f669f75 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -9,3 +9,6 @@
mod hashmap;
pub use hashmap::*;
+mod btreemap;
+pub use btreemap::*;
+