1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Tools for [`Iterator`]s over maps ([`HashMap`], [`BTreeMap`], etc),
//! or any two-element tuple.
//!
//! Just import [`IterMap`] to get extra methods on iterators.
//!
//! # Examples
//!
//! Mapping keys:
//! ```
//! # use std::collections::HashMap;
//! #
//! use itermap::IterMap;
//!
//! let mut hash: HashMap<&str, &str> = HashMap::new();
//! hash.insert("a", "A");
//! hash.insert("b", "B");
//!
//! let hash: HashMap<String, &str> = hash
//!     .into_iter()
//!     .map_keys(String::from)
//!     .collect();
//! ```
//!
//! Mapping values:
//! ```
//! # use std::collections::HashMap;
//! #
//! use itermap::IterMap;
//!
//! let mut hash: HashMap<&str, &str> = HashMap::new();
//! hash.insert("a", "A");
//! hash.insert("b", "B");
//!
//! let hash: HashMap<&str, String> = hash
//!     .into_iter()
//!     .map_values(String::from)
//!     .collect();
//! ```
//!
//! You can, of course, chain both adaptors to map both keys and values:
//! ```
//! # use std::collections::HashMap;
//! #
//! use itermap::IterMap;
//!
//! let mut hash: HashMap<&str, &str> = HashMap::new();
//! hash.insert("a", "A");
//! hash.insert("b", "B");
//!
//! let hash: HashMap<String, char> = hash
//!     .into_iter()
//!     .map_keys(String::from)
//!     .map_values(|v| v.parse().unwrap())
//!     .collect();
//! ```
//!
//! It works with any iterator over a two-element tuple:
//! ```
//! use itermap::IterMap;
//!
//! let mut values: Vec<(&str, &str)> = Vec::new();
//! values.push(("a", "A"));
//! values.push(("b", "B"));
//!
//! let values: Vec<(String, char)> = values
//!     .into_iter()
//!     .map_keys(String::from)
//!     .map_values(|v| v.parse().unwrap())
//!     .collect();
//! ```
//!
//! [`HashMap`]: std::collections::HashMap
//! [`BTreeMap`]: std::collections::BTreeMap

mod iter;
mod map_keys;
mod map_values;
#[cfg(any(test, doctest))]
mod tests;

use core::iter::Iterator;

pub use self::{map_keys::MapKeys, map_values::MapValues};

/// Adds additional methods for `Iterator`s over maps (e.g., `HashMap`,
/// `BTreeMap`, etc.) and other two-element tuples (like `(K, V)`).
pub trait IterMap<I, K, V>: Sized {
    /// Maps map keys (or the first element of a two-element tuple like
    /// `(K, V)`), leaving other elements intact and untouched.
    ///
    /// # Example
    /// ```
    /// # use std::collections::HashMap;
    /// #
    /// use itermap::IterMap;
    ///
    /// let mut hash: HashMap<&str, &str> = HashMap::new();
    /// hash.insert("a", "A");
    /// hash.insert("b", "B");
    ///
    /// let hash: HashMap<String, &str> = hash
    ///     .into_iter()
    ///     .map_keys(String::from)
    ///     .collect();
    /// ```
    fn map_keys<Fk, J>(self, f: Fk) -> MapKeys<I, Fk>
    where
        Fk: FnMut(K) -> J;

    /// Maps map values (or the second element of a two-element tuple like
    /// `(K, V)`), leaving other elements intact and untouched.
    ///
    /// # Example
    /// ```
    /// # use std::collections::HashMap;
    /// #
    /// use itermap::IterMap;
    ///
    /// let mut hash: HashMap<&str, &str> = HashMap::new();
    /// hash.insert("a", "A");
    /// hash.insert("b", "B");
    ///
    /// let hash: HashMap<&str, String> = hash
    ///     .into_iter()
    ///     .map_values(String::from)
    ///     .collect();
    /// ```
    fn map_values<Fv, U>(self, f: Fv) -> MapValues<I, Fv>
    where
        Fv: FnMut(V) -> U;
}

impl<I, K, V> IterMap<I, K, V> for I
where
    I: Iterator<Item = (K, V)>,
{
    fn map_keys<Fk, J>(self, key_op: Fk) -> MapKeys<I, Fk>
    where
        Fk: FnMut(K) -> J,
    {
        MapKeys::new(self, key_op)
    }

    fn map_values<Fv, U>(self, value_op: Fv) -> MapValues<I, Fv>
    where
        Fv: FnMut(V) -> U,
    {
        MapValues::new(self, value_op)
    }
}