to_vec/
lib.rs

1//! `to_vec`, to_set and`to_map` are specializations of `collect` in the
2//! usual case where you do want these containers.
3//!
4//! ```
5//! use to_vec::ToVec;
6//!
7//! let v = "one two three".split_whitespace().to_vec();
8//! assert_eq!(v,&["one","two","three"]);
9//! ```
10//! There's a specialized form for collecting `Result<T,E>` into
11//! `Result<Vec<T>,E>`, where the error is the _first_ error encountered.
12//!
13//! ```
14//! use to_vec::ToVecResult;
15//!
16//! let numbers = "23E 5F5 FF00".split_whitespace()
17//!     .map(|s| u32::from_str_radix(s,16)).to_vec_result().unwrap();
18//!
19//! assert_eq!(numbers,&[0x23E, 0x5F5, 0xFF00]);
20//! ```
21//!
22//! `to_map` and `to_set` are different - they operate on iterators
23//! of _references_ and implicitly clone this.
24//!
25//! ```
26//! use to_vec::ToMap;
27//! const VALUES: &[(&str,i32)] = &[("hello",10),("dolly",20)];
28//!
29//! let map = VALUES.iter().to_map();
30//!
31//! assert_eq!(map.get("hello"),Some(&10));
32//! assert_eq!(map.get("dolly"),Some(&20));
33//! ```
34//!
35//! This implicit cloning behaviour is very useful for sets (here defined
36//! as `HashSet`):
37//!
38//! ```
39//! use to_vec::ToSet;
40//!
41//! let colours = ["green","orange","blue"].iter().to_set();
42//! let fruit = ["apple","banana","orange"].iter().to_set();
43//! let common = colours.intersection(&fruit).to_set();
44//! assert_eq!(common, ["orange"].iter().to_set());
45//! ```
46
47use std::collections::{HashMap,HashSet};
48use std::iter::FromIterator;
49use std::cmp::Eq;
50use std::hash::Hash;
51use std::result::Result;
52
53/// to_vec() method on iterators
54pub trait ToVec<T> {
55    /// a more definite alternative to `collect`
56    /// which collects an iterator's values into a Vec
57    fn to_vec(self) -> Vec<T>;
58}
59
60/// to_vec_result() method on iterators
61pub trait ToVecResult<T,E> {
62    /// this collects an iterator of `Result<T,E>`
63    /// into a result of `Result<Vec<T>,E>`
64    fn to_vec_result(self) -> Result<Vec<T>,E>;
65}
66
67/// to_map() method on iterators of references
68pub trait ToMap<K,V> {
69    /// collect references into a HashMap by cloning
70    fn to_map(self) -> HashMap<K,V>;
71}
72
73/// to_set() method on iterators of references
74pub trait ToSet<K> {
75    /// collect values into a HashSet by cloning
76    fn to_set(self) -> HashSet<K>;
77}
78
79impl <T,I> ToVec<T> for I
80where I: Iterator<Item=T> {
81    fn to_vec(self) -> Vec<T> {
82        FromIterator::from_iter(self)
83    }
84}
85
86impl <T,E,I> ToVecResult<T,E> for I
87where I: Iterator<Item=Result<T,E>> {
88    fn to_vec_result(self) -> Result<Vec<T>,E> {
89        FromIterator::from_iter(self)
90    }
91}
92
93impl <'a, K,V,I> ToMap<K,V> for I
94where K: Eq + Hash + Clone +'a, V: Clone +'a, I: Iterator<Item=&'a (K,V)>   {
95    fn to_map(self) -> HashMap<K,V> {
96        FromIterator::from_iter(self.cloned())
97    }
98}
99
100
101impl <'a, K,I> ToSet<K> for I
102where K: Eq + Hash + Clone + 'a, I: Iterator<Item=&'a K>   {
103    fn to_set(self) -> HashSet<K> {
104        FromIterator::from_iter(self.cloned())
105    }
106}
107
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn test_to_vec() {
115        let v = "one two three".split_whitespace().to_vec();
116        assert_eq!(v,&["one","two","three"]);
117    }
118
119    #[test]
120    fn test_to_vec_result() {
121        let numbers = "23E 5F5 FF00".split_whitespace()
122            .map(|s| u32::from_str_radix(s,16)).to_vec_result().unwrap();
123
124        assert_eq!(numbers,&[0x23E, 0x5F5, 0xFF00]);
125    }
126
127    #[test]
128    fn test_to_set() {
129        let set1 = [10,5,2,5,10].iter().to_set();
130        let set2 = [2,5,10].iter().to_set();
131
132        assert_eq!(set1,set2);
133
134        let set3 = set1.intersection(&set2).to_set();
135        assert_eq!(set3,set1);
136
137        let colours = ["green","orange","blue"].iter().to_set();
138        let fruit = ["apple","banana","orange"].iter().to_set();
139        let common = colours.intersection(&fruit).to_set();
140        assert_eq!(common, ["orange"].iter().to_set());
141    }
142
143    const VALUES: &[(&str,i32)] = &[("hello",10),("dolly",20)];
144
145    #[test]
146    fn test_to_map() {
147
148        let map = VALUES.iter().to_map();
149
150        assert_eq!(map.get("hello"),Some(&10));
151        assert_eq!(map.get("dolly"),Some(&20));
152
153    }
154
155
156}