├── .gitignore ├── .travis.yml ├── Cargo.toml ├── README.md ├── benches └── bench_slice.rs ├── src ├── ext.rs ├── impls │ ├── mod.rs │ ├── slice.rs │ └── vec.rs ├── lib.rs └── utils.rs └── tests └── test.rs /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *~ 3 | *# 4 | *.o 5 | *.so 6 | *.swp 7 | *.dylib 8 | *.dSYM 9 | *.dll 10 | *.rlib 11 | *.dummy 12 | *.exe 13 | *-test 14 | /doc/ 15 | /target/ 16 | /examples/* 17 | !/examples/*.rs 18 | Cargo.lock 19 | 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "traverse" 4 | version = "0.0.12" 5 | authors = ["Jonathan Reem ", 6 | "Alexis Beingessner "] 7 | repository = "https://github.com/reem/rust-traverse.git" 8 | description = "Proof-of-concept trait for internal iterators called traversals." 9 | readme = "README.md" 10 | license = "MIT/Apache-2.0" 11 | 12 | [dependencies.num] 13 | 14 | [dev-dependencies] 15 | quickcheck = "*" 16 | rand = "*" 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Traverse 2 | 3 | > Proof-of-concept trait for internal iterators called traversals. 4 | 5 | ## Usage 6 | 7 | Use the crates.io repository; add this to your `Cargo.toml` along 8 | with the rest of your dependencies: 9 | 10 | ```toml 11 | [dependencies] 12 | traverse = "*" 13 | ``` 14 | 15 | ## Author 16 | 17 | [Jonathan Reem](https://medium.com/@jreem) and 18 | [Alexis Beingessner](https://github.com/gankro) 19 | are the primary authors and maintainers of traverse. 20 | 21 | ## License 22 | 23 | MIT 24 | 25 | -------------------------------------------------------------------------------- /benches/bench_slice.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | extern crate traverse; 5 | extern crate rand; 6 | 7 | use traverse::Traversal; 8 | use test::Bencher; 9 | 10 | #[bench] 11 | fn bench_internal(bench: &mut Bencher) { 12 | use rand::random; 13 | 14 | let data: Vec = (0..10000).map(|_| random()).collect(); 15 | bench.iter(|| { 16 | data.run(|x| { ::test::black_box(x); }); 17 | }); 18 | } 19 | 20 | #[bench] 21 | fn bench_external(bench: &mut Bencher) { 22 | use rand::random; 23 | 24 | let data: Vec = (0..10000).map(|_| random()).collect(); 25 | bench.iter(|| { 26 | for datum in data.iter() { 27 | ::test::black_box(datum); 28 | } 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /src/ext.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | use std::ops::Deref; 3 | 4 | impl O> 5 | Traversal for Map { 6 | type Item = F::Output; 7 | 8 | fn foreach(self, mut f: F1) where F1: FnMut(F::Output) -> bool { 9 | let mut closure = self.closure; 10 | self.iter.foreach(move |t| { 11 | f(closure(t)) 12 | }); 13 | } 14 | } 15 | 16 | impl bool> 17 | Traversal for Filter { 18 | type Item = I::Item; 19 | 20 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool{ 21 | let mut predicate = self.predicate; 22 | self.iter.foreach(move |t| { 23 | if predicate(&t) { f(t) } else { false } 24 | }); 25 | } 26 | } 27 | 28 | impl Option> 29 | Traversal for FilterMap { 30 | type Item = O; 31 | 32 | fn foreach(self, mut f: F1) where F1: FnMut(O) -> bool { 33 | let mut predicate = self.predicate; 34 | self.iter.foreach(move |t| { 35 | match predicate(t) { 36 | Some(o) => f(o), 37 | None => false 38 | } 39 | }); 40 | } 41 | } 42 | 43 | impl 44 | Traversal for Enumerate { 45 | type Item = (usize, I::Item); 46 | 47 | fn foreach(self, mut f: F1) where F1: FnMut((usize, I::Item)) -> bool { 48 | let mut counter = 0; 49 | self.0.foreach(|t| { 50 | let res = f((counter, t)); 51 | counter += 1; 52 | res 53 | }) 54 | } 55 | } 56 | 57 | impl 58 | Traversal for Skip { 59 | type Item = I::Item; 60 | 61 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool { 62 | let mut counter = 0; 63 | let n = self.n; 64 | 65 | self.iter.foreach(|t| { 66 | if counter != n { 67 | counter += 1; 68 | false 69 | } else { 70 | f(t) 71 | } 72 | }) 73 | } 74 | } 75 | 76 | impl 77 | Traversal for Take { 78 | type Item = I::Item; 79 | 80 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool { 81 | let mut counter = 0; 82 | let n = self.n; 83 | 84 | self.iter.foreach(|t| { 85 | if counter != n { 86 | counter += 1; 87 | f(t) 88 | } else { 89 | true 90 | } 91 | }) 92 | } 93 | } 94 | 95 | impl bool> 96 | Traversal for SkipWhile { 97 | type Item = I::Item; 98 | 99 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool { 100 | let mut predicate = self.predicate; 101 | let mut flag = false; 102 | self.iter.foreach(move |t| { 103 | // Done skipping 104 | if !flag { 105 | if predicate(&t) { 106 | false 107 | } else { 108 | flag = true; 109 | f(t) 110 | } 111 | } else { 112 | f(t) 113 | } 114 | }); 115 | } 116 | } 117 | 118 | impl bool> 119 | Traversal for TakeWhile { 120 | type Item = I::Item; 121 | 122 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool { 123 | let mut predicate = self.predicate; 124 | self.iter.foreach(move |t| { 125 | if predicate(&t) { f(t) } else { true } 126 | }); 127 | } 128 | } 129 | 130 | impl 131 | Traversal for Inspect { 132 | type Item = I::Item; 133 | 134 | fn foreach(self, mut f: F1) where F1: FnMut(I::Item) -> bool { 135 | let mut closure = self.closure; 136 | self.iter.foreach(move |t| { 137 | closure(&t); 138 | f(t) 139 | }); 140 | } 141 | } 142 | 143 | impl, O: Traversal> 144 | Traversal for Chain { 145 | type Item = T; 146 | 147 | fn foreach(self, mut f: F1) where F1: FnMut(T) -> bool { 148 | let mut flag = false; 149 | self.one.foreach(|t: T| { 150 | flag = f(t); flag 151 | }); 152 | 153 | if !flag { 154 | self.two.foreach(|t: T| { 155 | f(t) 156 | }); 157 | } 158 | } 159 | } 160 | 161 | impl O> 162 | Traversal for FlatMap { 163 | type Item = ::Item; 164 | 165 | fn foreach(self, mut f: F1) 166 | where F1: FnMut(Self::Item) -> bool { 167 | let mut producer = self.producer; 168 | let mut flag = false; 169 | self.iter.foreach(|t| { 170 | producer(t).foreach(|o| { 171 | flag = f(o); flag 172 | }); 173 | flag 174 | }); 175 | } 176 | } 177 | 178 | impl 179 | Traversal for Cloned 180 | where I::Item: Deref, 181 | ::Target: Clone { 182 | type Item = ::Target; 183 | 184 | fn foreach(self, mut f: F) where F: FnMut(Self::Item) -> bool { 185 | self.iter.foreach(|d| { 186 | f(d.deref().clone()) 187 | }); 188 | } 189 | } 190 | 191 | #[cfg(test)] 192 | mod test { 193 | use utils::*; 194 | use Traversal; 195 | 196 | #[test] 197 | fn map() { 198 | let vec: Vec<_> = range(0, 5).map(|x| x * 2).collect(); 199 | assert_eq!(vec, &[0, 2, 4, 6, 8]); 200 | } 201 | 202 | #[test] 203 | fn filter() { 204 | let vec: Vec<_> = range(0, 10).filter(|x| x % 2 == 0).collect(); 205 | assert_eq!(vec, &[0, 2, 4, 6, 8]); 206 | } 207 | 208 | #[test] 209 | fn filter_map() { 210 | let vec: Vec<_> = range(0, 10).filter_map(|x| if x % 2 == 0 { 211 | Some(x / 2) 212 | } else { 213 | None 214 | }).collect(); 215 | assert_eq!(vec, &[0, 1, 2, 3, 4]); 216 | } 217 | 218 | #[test] 219 | fn enumerate() { 220 | let vec: Vec<_> = range(1, 5).enumerate().collect(); 221 | assert_eq!(vec, &[(0, 1), (1, 2), (2, 3), (3, 4)]); 222 | } 223 | 224 | #[test] 225 | fn take() { 226 | let vec: Vec<_> = range(0, 10).take(5).collect(); 227 | assert_eq!(vec, &[0, 1, 2, 3, 4]); 228 | } 229 | 230 | #[test] 231 | fn skip() { 232 | let vec: Vec<_> = range(0, 10).skip(5).collect(); 233 | assert_eq!(vec, &[5, 6, 7, 8, 9]); 234 | } 235 | 236 | #[test] 237 | fn take_while() { 238 | let vec: Vec<_> = range(0, 10).take_while(|&x| x < 5).collect(); 239 | assert_eq!(vec, &[0, 1, 2, 3, 4]); 240 | } 241 | 242 | #[test] 243 | fn skip_while() { 244 | let vec: Vec<_> = range(0, 10).skip_while(|&x| x < 5).collect(); 245 | assert_eq!(vec, &[5, 6, 7, 8, 9]); 246 | } 247 | 248 | #[test] 249 | fn inspect() { 250 | let mut x = 0; 251 | let vec: Vec<_> = range(0, 5).inspect(|&y| x += y).collect(); 252 | assert_eq!(vec, &[0, 1, 2, 3, 4]); 253 | assert_eq!(x, 10); 254 | } 255 | 256 | #[test] 257 | fn chain() { 258 | let vec: Vec<_> = range(5, 10).chain(range(0, 5)).collect(); 259 | assert_eq!(vec, &[5, 6, 7, 8, 9, 0, 1, 2, 3, 4]); 260 | } 261 | 262 | #[test] 263 | fn cloned() { 264 | let x = 0; 265 | let vec: Vec<_> = repeat(&x).cloned().take(5).collect(); 266 | assert_eq!(vec, &[0, 0, 0, 0, 0]); 267 | } 268 | } 269 | -------------------------------------------------------------------------------- /src/impls/mod.rs: -------------------------------------------------------------------------------- 1 | use std::collections::*; 2 | use std::hash::Hash; 3 | use super::*; 4 | 5 | mod slice; 6 | mod vec; 7 | 8 | impl FromTraversal for VecDeque { 9 | fn from_traversal>(traversable: I) -> Self { 10 | let trav = traversable.into_traversal(); 11 | let mut new = Self::with_capacity(trav.size_hint().0); 12 | trav.run(|elem| { 13 | new.push_back(elem); 14 | }); 15 | new 16 | } 17 | } 18 | 19 | impl FromTraversal for LinkedList { 20 | fn from_traversal>(traversable: I) -> Self { 21 | let trav = traversable.into_traversal(); 22 | let mut new = Self::new(); 23 | trav.run(|elem| { 24 | new.push_back(elem); 25 | }); 26 | new 27 | } 28 | } 29 | 30 | impl FromTraversal<(K, V)> for HashMap { 31 | fn from_traversal>(traversable: I) -> Self { 32 | let trav = traversable.into_traversal(); 33 | let mut new = Self::with_capacity(trav.size_hint().0); 34 | trav.run(|(k, v)| { 35 | new.insert(k, v); 36 | }); 37 | new 38 | } 39 | } 40 | 41 | impl FromTraversal<(K, V)> for BTreeMap { 42 | fn from_traversal>(traversable: I) -> Self { 43 | let trav = traversable.into_traversal(); 44 | let mut new = Self::new(); 45 | trav.run(|(k, v)| { 46 | new.insert(k, v); 47 | }); 48 | new 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/impls/slice.rs: -------------------------------------------------------------------------------- 1 | use {Traversal, Internal}; 2 | 3 | impl<'a, T> Traversal for &'a [T] { 4 | type Item = &'a T; 5 | 6 | #[inline] 7 | fn foreach(self, f: F) where F: FnMut(&'a T) -> bool { 8 | Internal::new(self).foreach(f) 9 | } 10 | } 11 | 12 | impl<'a, T> Traversal for &'a mut [T] { 13 | type Item = &'a mut T; 14 | 15 | #[inline] 16 | fn foreach(self, f: F) where F: FnMut(&'a mut T) -> bool { 17 | Internal::new(self).foreach(f) 18 | } 19 | } 20 | 21 | #[cfg(test)] 22 | mod test { 23 | use Traversal; 24 | 25 | #[test] 26 | fn test_basic() { 27 | let data = [1, 2, 5, 4, 6, 7]; 28 | let traversal: Vec = data.map(|&x| x).collect(); 29 | assert_eq!(traversal, data); 30 | } 31 | 32 | #[test] 33 | fn test_zero_size() { 34 | let data = [(), (), ()]; 35 | let traversal: Vec<()> = data.map(|&x| x).collect(); 36 | assert_eq!(traversal, data); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/impls/vec.rs: -------------------------------------------------------------------------------- 1 | use std::vec; 2 | use {Traversal, IntoTraversal, FromTraversal, Internal}; 3 | 4 | impl IntoTraversal for Vec { 5 | type IntoTrav = Internal>; 6 | type Item = T; 7 | 8 | fn into_traversal(self) -> Self::IntoTrav { 9 | Internal::new(self.into_iter()) 10 | } 11 | } 12 | 13 | impl FromTraversal for Vec { 14 | fn from_traversal>(traversable: I) -> Self { 15 | let trav = traversable.into_traversal(); 16 | let mut new = Self::with_capacity(trav.size_hint().0); 17 | trav.run(|elem| { 18 | new.push(elem); 19 | }); 20 | new 21 | } 22 | } 23 | 24 | #[cfg(test)] 25 | mod test { 26 | use {Traversal, IntoTraversal}; 27 | 28 | #[test] 29 | fn test_basic() { 30 | let data = vec![1, 2, 5, 4, 6, 7]; 31 | let traversal: Vec = data.clone().into_traversal().collect(); 32 | assert_eq!(traversal, data); 33 | } 34 | 35 | #[test] 36 | fn test_zero_size() { 37 | let data = vec![(), (), ()]; 38 | let traversal: Vec<()> = data.clone().into_traversal().collect(); 39 | assert_eq!(traversal, data); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //#![deny(missing_docs, warnings)] 2 | 3 | //! Proof-of-concept trait for internal iterators. 4 | 5 | #![cfg_attr(all(test, feature = "nightly"), feature(test))] 6 | #[cfg(all(test, feature = "nightly"))] extern crate test; 7 | #[cfg(all(test, feature = "nightly"))] extern crate rand; 8 | 9 | // For CheckedAdd 10 | extern crate num; 11 | 12 | mod ext; 13 | pub mod utils; 14 | mod impls; 15 | 16 | /// An iterator that runs all at once 17 | pub trait Traversal: Sized { 18 | type Item; 19 | 20 | /// Run this Iterator using the provided closure. 21 | /// 22 | /// Return true from the closure to end the iteration. 23 | fn foreach(self, F) where F: FnMut(Self::Item) -> bool; 24 | 25 | /// Run this Iterator using the provided closure. 26 | /// 27 | /// This is a utility method for non-cancelling iterations. 28 | fn run(self, mut f: F) where F: FnMut(Self::Item) { 29 | self.foreach(|t| { f(t); false }) 30 | } 31 | 32 | fn size_hint(&self) -> (usize, Option) { (0, None) } 33 | 34 | fn map(self, f: F) -> Map 35 | where F: FnMut(Self::Item) -> O { 36 | Map { iter: self, closure: f } 37 | } 38 | 39 | fn filter(self, pred: F) -> Filter 40 | where F: FnMut(&Self::Item) -> bool { 41 | Filter { iter: self, predicate: pred } 42 | } 43 | 44 | fn filter_map(self, pred: F) -> FilterMap 45 | where F: FnMut(Self::Item) -> Option { 46 | FilterMap { iter: self, predicate: pred } 47 | } 48 | 49 | fn enumerate(self) -> Enumerate { 50 | Enumerate(self) 51 | } 52 | 53 | fn skip(self, n: usize) -> Skip { 54 | Skip { iter: self, n: n } 55 | } 56 | 57 | fn take(self, n: usize) -> Take { 58 | Take { iter: self, n: n } 59 | } 60 | 61 | fn skip_while(self, pred: F) -> SkipWhile 62 | where F: FnMut(&Self::Item) -> bool { 63 | SkipWhile { iter: self, predicate: pred } 64 | } 65 | 66 | fn take_while(self, pred: F) -> TakeWhile 67 | where F: FnMut(&Self::Item) -> bool { 68 | TakeWhile { iter: self, predicate: pred } 69 | } 70 | 71 | fn inspect(self, f: F) -> Inspect 72 | where F: FnMut(&Self::Item) { 73 | Inspect { iter: self, closure: f } 74 | } 75 | 76 | fn flat_map(self, f: F) -> FlatMap 77 | where U: Traversal, 78 | F: FnMut(Self::Item) -> U { 79 | FlatMap { iter: self, producer: f } 80 | } 81 | 82 | fn chain(self, other: O) -> Chain 83 | where O: Traversal { 84 | Chain { one: self, two: other } 85 | } 86 | 87 | fn count(self) -> usize { 88 | let mut count = 0; 89 | self.run(|_| { count += 1; }); 90 | count 91 | } 92 | 93 | fn cloned(self) -> Cloned { 94 | Cloned { iter: self } 95 | } 96 | 97 | fn collect(self) -> D 98 | where D: FromTraversal { 99 | FromTraversal::from_traversal(self) 100 | } 101 | } 102 | 103 | pub trait FromTraversal { 104 | fn from_traversal>(traversable: I) -> Self; 105 | } 106 | 107 | pub trait IntoTraversal { 108 | type IntoTrav: Traversal; 109 | type Item; 110 | fn into_traversal(self) -> Self::IntoTrav; 111 | } 112 | 113 | impl IntoTraversal for T { 114 | type IntoTrav = Self; 115 | type Item = ::Item; 116 | 117 | fn into_traversal(self) -> Self::IntoTrav { 118 | self 119 | } 120 | } 121 | 122 | pub struct Internal { 123 | iter: I 124 | } 125 | 126 | impl Internal { 127 | pub fn new>(iterable: It) -> Self { 128 | Internal { iter: iterable.into_iter() } 129 | } 130 | } 131 | 132 | impl Traversal for Internal { 133 | type Item = I::Item; 134 | 135 | fn foreach(self, mut f: F) where F: FnMut(I::Item) -> bool { 136 | for elem in self.iter { 137 | if f(elem) { break } 138 | } 139 | } 140 | } 141 | 142 | /// An Traversal that maps over the contents of 143 | /// another Traversal. 144 | #[derive(Copy, Clone)] 145 | pub struct Map { 146 | iter: I, 147 | closure: F, 148 | } 149 | 150 | #[derive(Copy, Clone)] 151 | pub struct Filter { 152 | iter: I, 153 | predicate: F 154 | } 155 | 156 | #[derive(Copy, Clone)] 157 | pub struct FilterMap { 158 | iter: I, 159 | predicate: F 160 | } 161 | 162 | #[derive(Copy, Clone)] 163 | pub struct Enumerate(I); 164 | 165 | #[derive(Copy, Clone)] 166 | pub struct Skip { 167 | iter: I, 168 | n: usize 169 | } 170 | 171 | #[derive(Copy, Clone)] 172 | pub struct Take { 173 | iter: I, 174 | n: usize 175 | } 176 | 177 | #[derive(Copy, Clone)] 178 | pub struct SkipWhile { 179 | iter: I, 180 | predicate: F 181 | } 182 | 183 | #[derive(Copy, Clone)] 184 | pub struct TakeWhile { 185 | iter: I, 186 | predicate: F 187 | } 188 | 189 | #[derive(Copy, Clone)] 190 | pub struct Inspect { 191 | iter: I, 192 | closure: F 193 | } 194 | 195 | #[derive(Copy, Clone)] 196 | pub struct Chain { 197 | one: I, 198 | two: O 199 | } 200 | 201 | #[derive(Copy, Clone)] 202 | pub struct FlatMap { 203 | iter: I, 204 | producer: F 205 | } 206 | 207 | #[derive(Copy, Clone)] 208 | pub struct Cloned { 209 | iter: I, 210 | } 211 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use Traversal; 2 | use std::ops::Add; 3 | 4 | use num::traits::PrimInt; 5 | 6 | /// An infinite iterator starting at `start` and advancing by `step` with each 7 | /// iteration 8 | #[derive(Copy, Clone)] 9 | pub struct Counter { 10 | /// The current state the counter is at (next value to be yielded) 11 | start: A, 12 | /// The amount that this iterator is stepping by 13 | step: A, 14 | } 15 | 16 | /// Creates a new counter with the specified start/step 17 | #[inline] 18 | pub fn count(start: A, step: A) -> Counter { 19 | Counter{ start: start, step: step } 20 | } 21 | 22 | impl + Clone> Traversal for Counter { 23 | type Item = A; 24 | 25 | #[inline] 26 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 27 | let mut i = self.start; 28 | loop { 29 | let old = i; 30 | // This is what std does, so I guess it's legit... 31 | i = old.clone() + self.step.clone(); 32 | if f(old) { return; } 33 | } 34 | } 35 | } 36 | 37 | /// An iterator over the range [start, stop) 38 | #[derive(Copy, Clone)] 39 | pub struct Range { 40 | start: A, 41 | stop: A, 42 | } 43 | 44 | /// Returns an iterator over the given range [start, stop) (that is, starting 45 | /// at start (inclusive), and ending at stop (exclusive)). 46 | #[inline] 47 | pub fn range(start: A, stop: A) -> Range { 48 | Range { start: start, stop: stop } 49 | } 50 | 51 | // FIXME: rust-lang/rust#10414: Unfortunate type bound 52 | impl Traversal for Range { 53 | type Item = A; 54 | 55 | #[inline] 56 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 57 | let mut i = self.start; 58 | let one = A::one(); 59 | while i < self.stop { 60 | let old = i; 61 | i = old + one; 62 | if f(old) { return; } 63 | } 64 | } 65 | } 66 | 67 | /// An iterator over the range [start, stop] 68 | #[derive(Copy, Clone)] 69 | pub struct RangeInclusive { 70 | start: A, 71 | stop: A, 72 | } 73 | 74 | /// Return an iterator over the range [start, stop] 75 | #[inline] 76 | pub fn range_inclusive(start: A, stop: A) -> RangeInclusive { 77 | RangeInclusive { start: start, stop: stop } 78 | } 79 | 80 | impl Traversal for RangeInclusive { 81 | type Item = A; 82 | 83 | #[inline] 84 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 85 | let mut i = self.start; 86 | let one = A::one(); 87 | while i <= self.stop { 88 | let old = i; 89 | i = old + one; 90 | if f(old) { return; } 91 | } 92 | } 93 | } 94 | 95 | /// An iterator over the range [start, stop) by `step`. It handles overflow by stopping. 96 | #[derive(Copy, Clone)] 97 | pub struct RangeStep { 98 | start: A, 99 | stop: A, 100 | step: A, 101 | } 102 | 103 | /// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping. 104 | #[inline] 105 | pub fn range_step(start: A, stop: A, step: A) -> RangeStep { 106 | RangeStep { start: start, stop: stop, step: step } 107 | } 108 | 109 | impl Traversal for RangeStep { 110 | type Item = A; 111 | 112 | #[inline] 113 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 114 | let mut i = self.start; 115 | // branch once and duplicate trivial logic for the perf 116 | if self.step > A::zero() { 117 | while i < self.stop { 118 | let old = i; 119 | let temp = i.checked_add(&self.step); 120 | if f(old) { return; } 121 | i = match temp { None => return, Some(x) => x } 122 | } 123 | } else { 124 | while i > self.stop { 125 | let old = i; 126 | let temp = i.checked_add(&self.step); 127 | if f(old) { return; } 128 | i = match temp { None => return, Some(x) => x } 129 | } 130 | } 131 | } 132 | } 133 | 134 | /// An iterator over the range [start, stop] by `step`. It handles overflow by stopping. 135 | #[derive(Copy, Clone)] 136 | pub struct RangeStepInclusive { 137 | start: A, 138 | stop: A, 139 | step: A, 140 | } 141 | 142 | /// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping. 143 | #[inline] 144 | pub fn range_step_inclusive(start: A, stop: A, step: A) -> RangeStepInclusive { 145 | RangeStepInclusive { start: start, stop: stop, step: step } 146 | } 147 | 148 | impl Traversal for RangeStepInclusive { 149 | type Item = A; 150 | 151 | #[inline] 152 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 153 | let mut i = self.start; 154 | // branch once and duplicate trivial logic for the perf 155 | if self.step > A::zero() { 156 | while i <= self.stop { 157 | let old = i; 158 | let temp = i.checked_add(&self.step); 159 | if f(old) { return; } 160 | i = match temp { None => return, Some(x) => x } 161 | } 162 | } else { 163 | while i >= self.stop { 164 | let old = i; 165 | let temp = i.checked_add(&self.step); 166 | if f(old) { return; } 167 | i = match temp { None => return, Some(x) => x } 168 | } 169 | } 170 | } 171 | } 172 | 173 | /// Create a new iterator that endlessly repeats the element `elt`. 174 | #[inline] 175 | pub fn repeat(elt: T) -> Repeat { 176 | Repeat{ element: elt } 177 | } 178 | 179 | /// An iterator that repeats an element endlessly 180 | #[derive(Copy, Clone)] 181 | pub struct Repeat { 182 | element: A 183 | } 184 | 185 | impl Traversal for Repeat { 186 | type Item = A; 187 | 188 | #[inline] 189 | fn foreach(self, mut f: F) where F: FnMut(A) -> bool { 190 | loop { 191 | if f(self.element.clone()) { return; } 192 | } 193 | } 194 | } 195 | 196 | /// An iterator that repeatedly applies a given function, starting 197 | /// from a given seed value. 198 | #[derive(Copy, Clone)] 199 | pub struct Iterate { 200 | seed: T, 201 | iter: F, 202 | } 203 | 204 | /// Create a new iterator that produces an infinite sequence of 205 | /// repeated applications of the given function `f`. 206 | #[inline] 207 | pub fn iterate(seed: T, f: F) -> Iterate where 208 | T: Clone, 209 | F: FnMut(T) -> T 210 | { 211 | Iterate { seed: seed, iter: f } 212 | } 213 | 214 | impl Traversal for Iterate where 215 | A: Clone, 216 | I: FnMut(A) -> A { 217 | type Item = A; 218 | 219 | #[inline] 220 | fn foreach(mut self, mut f: F) where F: FnMut(A) -> bool { 221 | if !f(self.seed.clone()) { 222 | let mut cur = self.seed; 223 | loop { 224 | let next = (self.iter)(cur); 225 | if f(next.clone()) { return; } 226 | cur = next; 227 | } 228 | } 229 | } 230 | } 231 | 232 | 233 | 234 | #[cfg(test)] 235 | mod test { 236 | use super::*; 237 | use Traversal; 238 | 239 | #[test] 240 | fn test_range() { 241 | assert_eq!(range(0, 5).collect::>(), vec![0, 1, 2, 3, 4]); 242 | assert_eq!(range(-10, -1).collect::>(), 243 | vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]); 244 | assert_eq!(range(200i32, -5).count(), 0); 245 | assert_eq!(range(200i32, 200).count(), 0); 246 | } 247 | 248 | #[test] 249 | fn test_range_inclusive() { 250 | assert_eq!(range_inclusive(0, 5).collect::>(), vec![0, 1, 2, 3, 4, 5]); 251 | assert_eq!(range_inclusive(200i32, -5).count(), 0); 252 | assert_eq!(range_inclusive(200, 200).collect::>(), vec![200]); 253 | } 254 | 255 | #[test] 256 | fn test_range_step() { 257 | assert_eq!(range_step(0, 20, 5).collect::>(), vec![0, 5, 10, 15]); 258 | assert_eq!(range_step(20, 0, -5).collect::>(), vec![20, 15, 10, 5]); 259 | assert_eq!(range_step(20, 0, -6).collect::>(), vec![20, 14, 8, 2]); 260 | assert_eq!(range_step(200u8, 255, 50).collect::>(), vec![200u8, 250]); 261 | assert_eq!(range_step(200, -5, 1).collect::>(), vec![]); 262 | assert_eq!(range_step(200, 200, 1).collect::>(), vec![]); 263 | } 264 | 265 | #[test] 266 | fn test_range_step_inclusive() { 267 | assert_eq!(range_step_inclusive(0, 20, 5).collect::>(), vec![0, 5, 10, 15, 20]); 268 | assert_eq!(range_step_inclusive(20, 0, -5).collect::>(), vec![20, 15, 10, 5, 0]); 269 | assert_eq!(range_step_inclusive(20, 0, -6).collect::>(), vec![20, 14, 8, 2]); 270 | assert_eq!(range_step_inclusive(200, 255, 50).collect::>(), vec![200, 250]); 271 | assert_eq!(range_step_inclusive(200, -5, 1).collect::>(), vec![]); 272 | assert_eq!(range_step_inclusive(200, 200, 1).collect::>(), vec![200]); 273 | } 274 | 275 | 276 | #[test] 277 | fn test_iterate() { 278 | assert_eq!(iterate(1, |x| x * 2).take(5).collect::>(), vec![1, 2, 4, 8, 16]); 279 | } 280 | 281 | #[test] 282 | fn test_repeat() { 283 | assert_eq!(repeat(42).take(5).collect::>(), vec![42, 42, 42, 42, 42]); 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /tests/test.rs: -------------------------------------------------------------------------------- 1 | extern crate quickcheck; 2 | extern crate traverse; 3 | 4 | use traverse::Traversal; 5 | 6 | #[test] 7 | fn quickcheck_map() { 8 | fn add_one(x: &u32) -> u32 { *x + 1 } 9 | 10 | fn prop(vec: Vec) -> bool { 11 | let expected: Vec<_> = vec.iter().map(add_one).collect(); 12 | let result: Vec<_> = vec.map(add_one).collect(); 13 | expected == result 14 | } 15 | 16 | quickcheck::quickcheck(prop as fn(Vec) -> bool); 17 | } 18 | 19 | #[test] 20 | fn quickcheck_filter() { 21 | fn is_even(x: & &u32) -> bool { **x % 2 == 0 } 22 | 23 | fn prop(vec: Vec) -> bool { 24 | let expected: Vec<&u32> = vec.iter().filter(is_even).collect(); 25 | let result: Vec<&u32> = vec.filter(is_even).collect(); 26 | expected == result 27 | } 28 | 29 | quickcheck::quickcheck(prop as fn(Vec) -> bool); 30 | } 31 | --------------------------------------------------------------------------------