1#![warn(missing_docs)]
19
20extern crate num_traits;
21
22use num_traits::One;
23use std::iter::FromIterator;
24use std::ops::{AddAssign, SubAssign};
25
26pub fn from<Idx>(i: Idx) -> From<Idx> {
39 From { from: i }
40}
41
42#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
46pub struct From<Idx> {
47 from: Idx,
48}
49
50impl<Idx> From<Idx> {
51 pub fn up_to(self, x: Idx) -> Range<Idx, Upwards> {
53 Range {
54 from: self.from,
55 to: x,
56 direction: Upwards,
57 }
58 }
59
60 pub fn down_to(self, x: Idx) -> Range<Idx, Downwards> {
62 Range {
63 from: self.from,
64 to: x,
65 direction: Downwards,
66 }
67 }
68}
69
70#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
78pub struct Range<Idx, Direction> {
79 direction: Direction,
80 from: Idx,
81 to: Idx,
82}
83
84#[doc(hidden)]
85#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
86pub struct Upwards;
87
88#[doc(hidden)]
89#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd)]
90pub struct Downwards;
91
92impl<Idx> Range<Idx, Upwards>
94where
95 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
96{
97 pub fn collect<B>(self) -> B
101 where
102 B: FromIterator<Idx>,
103 {
104 self.into_iter().collect()
105 }
106
107 pub fn to_vec(&self) -> Vec<Idx> {
109 self.clone().into_iter().collect()
110 }
111}
112
113impl<Idx> Range<Idx, Downwards>
115where
116 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
117{
118 pub fn collect<B>(self) -> B
122 where
123 B: FromIterator<Idx>,
124 {
125 self.into_iter().collect()
126 }
127
128 pub fn to_vec(&self) -> Vec<Idx> {
130 self.clone().into_iter().collect()
131 }
132}
133
134impl<Idx> IntoIterator for Range<Idx, Upwards>
135where
136 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
137{
138 type Item = Idx;
139 type IntoIter = RangeIter<Idx, Upwards>;
140
141 fn into_iter(self) -> Self::IntoIter {
142 RangeIter {
143 current: self.from,
144 limit: self.to,
145 direction: self.direction,
146 init: false,
147 }
148 }
149}
150
151impl<Idx> IntoIterator for Range<Idx, Downwards>
152where
153 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
154{
155 type Item = Idx;
156 type IntoIter = RangeIter<Idx, Downwards>;
157
158 fn into_iter(self) -> Self::IntoIter {
159 RangeIter {
160 current: self.from,
161 limit: self.to,
162 direction: self.direction,
163 init: false,
164 }
165 }
166}
167
168pub struct RangeIter<Idx, Direction> {
170 current: Idx,
171 limit: Idx,
172 #[allow(unused)]
173 direction: Direction,
174 init: bool,
175}
176
177impl<Idx> Iterator for RangeIter<Idx, Upwards>
178where
179 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
180{
181 type Item = Idx;
182
183 fn next(&mut self) -> Option<Self::Item> {
184 if !self.init {
185 self.init = true;
186
187 return Some(self.current.clone());
188 }
189
190 if self.current == self.limit {
191 return None;
192 }
193
194 self.current += Idx::one();
195
196 Some(self.current.clone())
197 }
198}
199
200impl<Idx> Iterator for RangeIter<Idx, Downwards>
201where
202 Idx: Clone + PartialEq + One + AddAssign + SubAssign,
203{
204 type Item = Idx;
205
206 fn next(&mut self) -> Option<Self::Item> {
207 if !self.init {
208 self.init = true;
209
210 return Some(self.current.clone());
211 }
212
213 if self.current == self.limit {
214 return None;
215 }
216
217 self.current -= Idx::one();
218
219 Some(self.current.clone())
220 }
221}
222
223#[test]
224fn range_collect() {
225 let x: Vec<i32> = from(10).up_to(14).into_iter().take(10).collect();
226 assert_eq!(x, vec![10, 11, 12, 13, 14]);
227}
228
229#[test]
230fn rev_range_collect() {
231 let x: Vec<i32> = from(14).down_to(10).into_iter().take(10).collect();
232 assert_eq!(x, vec![14, 13, 12, 11, 10]);
233}