Skip to content

Commit

Permalink
Add keys, values, values_mut methods
Browse files Browse the repository at this point in the history
  • Loading branch information
JustForFun88 committed Apr 10, 2022
1 parent 25d8a9e commit 726bf86
Show file tree
Hide file tree
Showing 4 changed files with 333 additions and 5 deletions.
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,32 @@

All notable changes to this project will be documented in this file.

## [v0.6.0] - 2022-04-10

### Added

- **`keys`** `DHashMap` method for creation an iterator visiting all keys in arbitrary order;
- **`values`** `DHashMap` method for creation an iterator visiting all values in arbitrary order;
- **`values_mut`** `DHashMap` method for creation an iterator visiting all values mutably in arbitrary order.

### Changed

Nothign

### Removed

Nothign

### Fixed

Nothing

## [v0.5.0] - 2022-04-05

### Added

- **`iter_mut`** `DHashMap` method for creation a mutable iterator visiting all keys-value tuples in arbitrary order.
- **`iter_mut`** `DHashMap` method for creation an iterator visiting all keys-value tuples in arbitrary
order, with mutable references to the values.

### Changed

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "double-map"
version = "0.5.0"
version = "0.6.0"
authors = ["Alisher Galiev <[email protected]>"]
description = "A HashMap with double key to single data/value"
edition = "2021"
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ interface. Look at [Change log](CHANGELOG.md) for more information.
- [x] `with_hasher`: Done since `v0.1.0`
- [x] `with_capacity_and_hasher`: Done since `v0.1.0`
- [x] `capacity`: Done since `v0.1.0`
- [ ] `keys`: Under development
- [x] `keys`: Done since `v0.6.0`
- [ ] `into_keys`: Under development
- [ ] `values`: Under development
- [ ] `values_mut`: Under development
- [x] `values`: Done since `v0.6.0`
- [x] `values_mut`: Done since `v0.6.0`
- [ ] `into_values`: Under development
- [x] `iter`: Done since `v0.4.0`
- [x] `iter_mut`: Done since `v0.5.0`
Expand Down
307 changes: 307 additions & 0 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,108 @@ impl<K1, K2, V, S> DHashMap<K1, K2, V, S> {
self.value_map.capacity()
}

/// An iterator visiting all keys in arbitrary order.
/// The iterator element is tuple of type `(&'a K1, &'a K2)`.
///
/// # Note
///
/// Internally [`DHashMap`] use two [`HashMap`](`std::collections::HashMap`). One of type
/// `HashMap<K1, (K2, V)>` to hold the `(K2, V)` tuple, and second one of type
/// `HashMap<K2, K1>` just for holding the primary key of type `K1`.
///
/// Created iterator iterate only through first [`HashMap`](`std::collections::HashMap`)
/// of type `HashMap<K1, (K2, V)>`.
/// So that, if you previously used [`insert_unchecked`](DHashMap::insert_unchecked) method,
/// this method can return false second keys (key #2) in case of **unsynchronization**
/// between first keys of type `K1` and second keys of type `K2`. See
/// [`insert_unchecked`](DHashMap::insert_unchecked) method documentation for more.
///
/// # Examples
///
/// ```
/// use double_map::DHashMap;
///
/// let mut map = DHashMap::new();
/// map.insert("a", 1, "One");
/// map.insert("b", 2, "Two");
/// map.insert("c", 3, "Three");
///
/// assert_eq!(map.len(), 3);
///
/// for (key1, key2) in map.keys() {
/// println!("key1: {}, key2: {}", key1, key2);
/// assert!(
/// (key1, key2) == (&"a", &1) ||
/// (key1, key2) == (&"b", &2) ||
/// (key1, key2) == (&"c", &3)
/// );
/// }
///
/// assert_eq!(map.len(), 3);
/// ```
pub fn keys(&self) -> Keys<'_, K1, K2, V> {
Keys { inner: self.iter() }
}

/// An iterator visiting all values in arbitrary order.
/// The iterator element type is `&'a V`.
///
/// # Examples
///
/// ```
/// use double_map::DHashMap;
///
/// let mut map = DHashMap::new();
/// map.insert("a", 1, "One");
/// map.insert("b", 2, "Two");
/// map.insert("c", 3, "Three");
///
/// assert_eq!(map.len(), 3);
///
/// for value in map.values() {
/// println!("value = {}", value);
/// assert!(value == &"One" || value == &"Two" || value == &"Three");
/// }
///
/// assert_eq!(map.len(), 3);
/// ```
pub fn values(&self) -> Values<'_, K1, K2, V> {
Values { inner: self.iter() }
}

/// An iterator visiting all values mutably in arbitrary order.
/// The iterator element type is `&'a mut V`.
///
/// # Examples
///
/// ```
/// use double_map::DHashMap;
///
/// let mut map = DHashMap::new();
///
/// map.insert("a", "One", 1);
/// map.insert("b", "Two", 2);
/// map.insert("c", "Three", 3);
///
/// assert_eq!(map.len(), 3);
///
/// for value in map.values_mut() {
/// *value = *value + 10;
/// }
///
/// for value in map.values() {
/// println!("value = {}", value);
/// assert!(value == &11 || value == &12 || value == &13);
/// }
///
/// assert_eq!(map.len(), 3);
/// ```
pub fn values_mut(&mut self) -> ValuesMut<'_, K1, K2, V> {
ValuesMut {
inner: self.iter_mut(),
}
}

/// An iterator visiting all keys-value tuples in arbitrary order.
/// The iterator element is tuple of type `(&'a K1, &'a K2, &'a V)`.
///
Expand Down Expand Up @@ -1628,6 +1730,150 @@ impl<'a, K1, K2, V> ExactSizeIterator for Iter<'a, K1, K2, V> {

impl<K1, K2, V> FusedIterator for Iter<'_, K1, K2, V> {}

/// An iterator over the keys of a `DHashMap` in arbitrary order.
/// The iterator element is tuple of type `(&'a K1, &'a K2)`.
///
/// This `struct` is created by the [`keys`](DHashMap::keys) method
/// on [`DHashMap`]. See its documentation for more.
///
/// # Example
///
/// ```
/// use double_map::{DHashMap, dhashmap};
///
/// let map = dhashmap!{
/// 1, "a" => "One",
/// 2, "b" => "Two",
/// 3, "c" => "Three",
/// };
/// let mut keys = map.keys();
/// let item1 = keys.next();
/// let item2 = keys.next();
/// let item3 = keys.next();
/// assert!(
/// item1 == Some((&1, &"a")) ||
/// item1 == Some((&2, &"b")) ||
/// item1 == Some((&3, &"c"))
/// );
/// assert!(
/// item2 == Some((&1, &"a")) ||
/// item2 == Some((&2, &"b")) ||
/// item2 == Some((&3, &"c"))
/// );
/// assert!(
/// item3 == Some((&1, &"a")) ||
/// item3 == Some((&2, &"b")) ||
/// item3 == Some((&3, &"c"))
/// );
/// assert_eq!(keys.next(), None);
///
/// // It is fused iterator
/// assert_eq!(keys.next(), None);
/// assert_eq!(keys.next(), None);
/// ```
#[derive(Clone, Debug)]
pub struct Keys<'a, K1: 'a, K2: 'a, V: 'a> {
inner: Iter<'a, K1, K2, V>,
}

impl<'a, K1, K2, V> Iterator for Keys<'a, K1, K2, V> {
type Item = (&'a K1, &'a K2);

#[inline]
fn next(&mut self) -> Option<(&'a K1, &'a K2)> {
// We do not use Option::map for performance purpose
match self.inner.next() {
Some((k1, k2, _)) => Some((k1, k2)),
None => None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

impl<'a, K1, K2, V> ExactSizeIterator for Keys<'a, K1, K2, V> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}

impl<K1, K2, V> FusedIterator for Keys<'_, K1, K2, V> {}

/// An iterator over the values of a `DHashMap` in arbitrary order.
/// The iterator element is `&'a V`.
///
/// This `struct` is created by the [`values`](DHashMap::values) method
/// on [`DHashMap`]. See its documentation for more.
///
/// # Example
///
/// ```
/// use double_map::{DHashMap, dhashmap};
///
/// let map = dhashmap!{
/// 1, "a" => "One",
/// 2, "b" => "Two",
/// 3, "c" => "Three",
/// };
/// let mut values = map.values();
/// let item1 = values.next();
/// let item2 = values.next();
/// let item3 = values.next();
/// assert!(
/// item1 == Some(&"One") ||
/// item1 == Some(&"Two") ||
/// item1 == Some(&"Three")
/// );
/// assert!(
/// item2 == Some(&"One") ||
/// item2 == Some(&"Two") ||
/// item2 == Some(&"Three")
/// );
/// assert!(
/// item3 == Some(&"One") ||
/// item3 == Some(&"Two") ||
/// item3 == Some(&"Three")
/// );
/// assert_eq!(values.next(), None);
///
/// // It is fused iterator
/// assert_eq!(values.next(), None);
/// assert_eq!(values.next(), None);
/// ```
#[derive(Clone, Debug)]
pub struct Values<'a, K1: 'a, K2: 'a, V: 'a> {
inner: Iter<'a, K1, K2, V>,
}

impl<'a, K1, K2, V> Iterator for Values<'a, K1, K2, V> {
type Item = &'a V;

#[inline]
fn next(&mut self) -> Option<&'a V> {
// We do not use Option::map for performance purpose
match self.inner.next() {
Some((_, _, val)) => Some(val),
None => None
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

impl<'a, K1, K2, V> ExactSizeIterator for Values<'a, K1, K2, V> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}

impl<K1, K2, V> FusedIterator for Values<'_, K1, K2, V> {}

/// A mutable iterator over the entries of a `DHashMap` in arbitrary order.
/// The iterator element is tuple of type`(&'a K1, &'a K2, &'a mut V)`.
///
Expand Down Expand Up @@ -1689,6 +1935,67 @@ impl<'a, K1, K2, V> ExactSizeIterator for IterMut<'a, K1, K2, V> {

impl<K1, K2, V> FusedIterator for IterMut<'_, K1, K2, V> {}

/// A mutable iterator over the values of a `DHashMap` in arbitrary order.
/// The iterator element is `&'a mut V`.
///
/// This `struct` is created by the [`values_mut`](DHashMap::values_mut) method
/// on [`DHashMap`]. See its documentation for more.
///
/// # Example
///
/// ```
/// use double_map::{DHashMap, dhashmap};
///
/// let mut map = dhashmap!{
/// 1, "a" => "One".to_owned(),
/// 2, "b" => "Two".to_owned(),
/// 3, "c" => "Three".to_owned(),
/// };
///
/// let mut values = map.values_mut();
/// values.next().map(|v| v.push_str(" coin"));
/// values.next().map(|v| v.push_str(" coin"));
/// values.next().map(|v| v.push_str(" coin"));
///
/// // It is fused iterator
/// assert_eq!(values.next(), None);
/// assert_eq!(values.next(), None);
///
/// assert_eq!(map.get_key1(&1).unwrap(), &"One coin".to_owned() );
/// assert_eq!(map.get_key1(&2).unwrap(), &"Two coin".to_owned() );
/// assert_eq!(map.get_key1(&3).unwrap(), &"Three coin".to_owned());
/// ```
#[derive(Debug)]
pub struct ValuesMut<'a, K1: 'a, K2: 'a, V: 'a> {
inner: IterMut<'a, K1, K2, V>,
}

impl<'a, K1, K2, V> Iterator for ValuesMut<'a, K1, K2, V> {
type Item = &'a mut V;

#[inline]
fn next(&mut self) -> Option<&'a mut V> {
// We do not use Option::map for performance purpose
match self.inner.next() {
Some((_, _, val)) => Some(val),
None => None,
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}

impl<'a, K1, K2, V> ExactSizeIterator for ValuesMut<'a, K1, K2, V> {
#[inline]
fn len(&self) -> usize {
self.inner.len()
}
}

impl<K1, K2, V> FusedIterator for ValuesMut<'_, K1, K2, V> {}

/// A view into an occupied entry in a [`DHashMap`].
/// It is part of the [`Entry`] enum and [`OccupiedError`] struct.
#[derive(Debug)]
Expand Down

0 comments on commit 726bf86

Please sign in to comment.