]> git.lizzy.rs Git - rust.git/blob - src/libcore/iter/range.rs
Omit 'missing IndexMut impl' suggestion when IndexMut is implemented.
[rust.git] / src / libcore / iter / range.rs
1 // Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use convert::TryFrom;
12 use mem;
13 use ops::{self, Add, Sub};
14 use usize;
15
16 use super::{FusedIterator, TrustedLen};
17
18 /// Objects that can be stepped over in both directions.
19 ///
20 /// The `steps_between` function provides a way to efficiently compare
21 /// two `Step` objects.
22 #[unstable(feature = "step_trait",
23            reason = "likely to be replaced by finer-grained traits",
24            issue = "42168")]
25 pub trait Step: Clone + PartialOrd + Sized {
26     /// Returns the number of steps between two step objects. The count is
27     /// inclusive of `start` and exclusive of `end`.
28     ///
29     /// Returns `None` if it is not possible to calculate `steps_between`
30     /// without overflow.
31     fn steps_between(start: &Self, end: &Self) -> Option<usize>;
32
33     /// Replaces this step with `1`, returning itself
34     fn replace_one(&mut self) -> Self;
35
36     /// Replaces this step with `0`, returning itself
37     fn replace_zero(&mut self) -> Self;
38
39     /// Adds one to this step, returning the result
40     fn add_one(&self) -> Self;
41
42     /// Subtracts one to this step, returning the result
43     fn sub_one(&self) -> Self;
44
45     /// Add an usize, returning None on overflow
46     fn add_usize(&self, n: usize) -> Option<Self>;
47 }
48
49 // These are still macro-generated because the integer literals resolve to different types.
50 macro_rules! step_identical_methods {
51     () => {
52         #[inline]
53         fn replace_one(&mut self) -> Self {
54             mem::replace(self, 1)
55         }
56
57         #[inline]
58         fn replace_zero(&mut self) -> Self {
59             mem::replace(self, 0)
60         }
61
62         #[inline]
63         fn add_one(&self) -> Self {
64             Add::add(*self, 1)
65         }
66
67         #[inline]
68         fn sub_one(&self) -> Self {
69             Sub::sub(*self, 1)
70         }
71     }
72 }
73
74 macro_rules! step_impl_unsigned {
75     ($($t:ty)*) => ($(
76         #[unstable(feature = "step_trait",
77                    reason = "likely to be replaced by finer-grained traits",
78                    issue = "42168")]
79         impl Step for $t {
80             #[inline]
81             #[allow(trivial_numeric_casts)]
82             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
83                 if *start < *end {
84                     // Note: We assume $t <= usize here
85                     Some((*end - *start) as usize)
86                 } else {
87                     Some(0)
88                 }
89             }
90
91             #[inline]
92             #[allow(unreachable_patterns)]
93             fn add_usize(&self, n: usize) -> Option<Self> {
94                 match <$t>::try_from(n) {
95                     Ok(n_as_t) => self.checked_add(n_as_t),
96                     Err(_) => None,
97                 }
98             }
99
100             step_identical_methods!();
101         }
102     )*)
103 }
104 macro_rules! step_impl_signed {
105     ($( [$t:ty : $unsigned:ty] )*) => ($(
106         #[unstable(feature = "step_trait",
107                    reason = "likely to be replaced by finer-grained traits",
108                    issue = "42168")]
109         impl Step for $t {
110             #[inline]
111             #[allow(trivial_numeric_casts)]
112             fn steps_between(start: &$t, end: &$t) -> Option<usize> {
113                 if *start < *end {
114                     // Note: We assume $t <= isize here
115                     // Use .wrapping_sub and cast to usize to compute the
116                     // difference that may not fit inside the range of isize.
117                     Some((*end as isize).wrapping_sub(*start as isize) as usize)
118                 } else {
119                     Some(0)
120                 }
121             }
122
123             #[inline]
124             #[allow(unreachable_patterns)]
125             fn add_usize(&self, n: usize) -> Option<Self> {
126                 match <$unsigned>::try_from(n) {
127                     Ok(n_as_unsigned) => {
128                         // Wrapping in unsigned space handles cases like
129                         // `-120_i8.add_usize(200) == Some(80_i8)`,
130                         // even though 200_usize is out of range for i8.
131                         let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
132                         if wrapped >= *self {
133                             Some(wrapped)
134                         } else {
135                             None  // Addition overflowed
136                         }
137                     }
138                     Err(_) => None,
139                 }
140             }
141
142             step_identical_methods!();
143         }
144     )*)
145 }
146
147 macro_rules! step_impl_no_between {
148     ($($t:ty)*) => ($(
149         #[unstable(feature = "step_trait",
150                    reason = "likely to be replaced by finer-grained traits",
151                    issue = "42168")]
152         impl Step for $t {
153             #[inline]
154             fn steps_between(_start: &Self, _end: &Self) -> Option<usize> {
155                 None
156             }
157
158             #[inline]
159             fn add_usize(&self, n: usize) -> Option<Self> {
160                 self.checked_add(n as $t)
161             }
162
163             step_identical_methods!();
164         }
165     )*)
166 }
167
168 step_impl_unsigned!(usize u8 u16 u32);
169 step_impl_signed!([isize: usize] [i8: u8] [i16: u16] [i32: u32]);
170 #[cfg(target_pointer_width = "64")]
171 step_impl_unsigned!(u64);
172 #[cfg(target_pointer_width = "64")]
173 step_impl_signed!([i64: u64]);
174 // If the target pointer width is not 64-bits, we
175 // assume here that it is less than 64-bits.
176 #[cfg(not(target_pointer_width = "64"))]
177 step_impl_no_between!(u64 i64);
178 step_impl_no_between!(u128 i128);
179
180 macro_rules! range_exact_iter_impl {
181     ($($t:ty)*) => ($(
182         #[stable(feature = "rust1", since = "1.0.0")]
183         impl ExactSizeIterator for ops::Range<$t> { }
184     )*)
185 }
186
187 macro_rules! range_incl_exact_iter_impl {
188     ($($t:ty)*) => ($(
189         #[stable(feature = "inclusive_range", since = "1.26.0")]
190         impl ExactSizeIterator for ops::RangeInclusive<$t> { }
191     )*)
192 }
193
194 macro_rules! range_trusted_len_impl {
195     ($($t:ty)*) => ($(
196         #[unstable(feature = "trusted_len", issue = "37572")]
197         unsafe impl TrustedLen for ops::Range<$t> { }
198     )*)
199 }
200
201 macro_rules! range_incl_trusted_len_impl {
202     ($($t:ty)*) => ($(
203         #[unstable(feature = "trusted_len", issue = "37572")]
204         unsafe impl TrustedLen for ops::RangeInclusive<$t> { }
205     )*)
206 }
207
208 #[stable(feature = "rust1", since = "1.0.0")]
209 impl<A: Step> Iterator for ops::Range<A> {
210     type Item = A;
211
212     #[inline]
213     fn next(&mut self) -> Option<A> {
214         if self.start < self.end {
215             // We check for overflow here, even though it can't actually
216             // happen. Adding this check does however help llvm vectorize loops
217             // for some ranges that don't get vectorized otherwise,
218             // and this won't actually result in an extra check in an optimized build.
219             if let Some(mut n) = self.start.add_usize(1) {
220                 mem::swap(&mut n, &mut self.start);
221                 Some(n)
222             } else {
223                 None
224             }
225         } else {
226             None
227         }
228     }
229
230     #[inline]
231     fn size_hint(&self) -> (usize, Option<usize>) {
232         match Step::steps_between(&self.start, &self.end) {
233             Some(hint) => (hint, Some(hint)),
234             None => (0, None)
235         }
236     }
237
238     #[inline]
239     fn nth(&mut self, n: usize) -> Option<A> {
240         if let Some(plus_n) = self.start.add_usize(n) {
241             if plus_n < self.end {
242                 self.start = plus_n.add_one();
243                 return Some(plus_n)
244             }
245         }
246
247         self.start = self.end.clone();
248         None
249     }
250
251     #[inline]
252     fn last(mut self) -> Option<A> {
253         self.next_back()
254     }
255
256     #[inline]
257     fn min(mut self) -> Option<A> {
258         self.next()
259     }
260
261     #[inline]
262     fn max(mut self) -> Option<A> {
263         self.next_back()
264     }
265 }
266
267 // These macros generate `ExactSizeIterator` impls for various range types.
268 // Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded
269 // because they cannot guarantee having a length <= usize::MAX, which is
270 // required by ExactSizeIterator.
271 range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
272 range_incl_exact_iter_impl!(u8 u16 i8 i16);
273
274 // These macros generate `TrustedLen` impls.
275 //
276 // They need to guarantee that .size_hint() is either exact, or that
277 // the upper bound is None when it does not fit the type limits.
278 range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
279 range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
280
281 #[stable(feature = "rust1", since = "1.0.0")]
282 impl<A: Step> DoubleEndedIterator for ops::Range<A> {
283     #[inline]
284     fn next_back(&mut self) -> Option<A> {
285         if self.start < self.end {
286             self.end = self.end.sub_one();
287             Some(self.end.clone())
288         } else {
289             None
290         }
291     }
292 }
293
294 #[stable(feature = "fused", since = "1.26.0")]
295 impl<A: Step> FusedIterator for ops::Range<A> {}
296
297 #[stable(feature = "rust1", since = "1.0.0")]
298 impl<A: Step> Iterator for ops::RangeFrom<A> {
299     type Item = A;
300
301     #[inline]
302     fn next(&mut self) -> Option<A> {
303         let mut n = self.start.add_one();
304         mem::swap(&mut n, &mut self.start);
305         Some(n)
306     }
307
308     #[inline]
309     fn size_hint(&self) -> (usize, Option<usize>) {
310         (usize::MAX, None)
311     }
312
313     #[inline]
314     fn nth(&mut self, n: usize) -> Option<A> {
315         let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth");
316         self.start = plus_n.add_one();
317         Some(plus_n)
318     }
319 }
320
321 #[stable(feature = "fused", since = "1.26.0")]
322 impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
323
324 #[unstable(feature = "trusted_len", issue = "37572")]
325 unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}
326
327 #[stable(feature = "inclusive_range", since = "1.26.0")]
328 impl<A: Step> Iterator for ops::RangeInclusive<A> {
329     type Item = A;
330
331     #[inline]
332     fn next(&mut self) -> Option<A> {
333         self.compute_is_empty();
334         if self.is_empty.unwrap_or_default() {
335             return None;
336         }
337         let is_iterating = self.start < self.end;
338         self.is_empty = Some(!is_iterating);
339         Some(if is_iterating {
340             let n = self.start.add_one();
341             mem::replace(&mut self.start, n)
342         } else {
343             self.start.clone()
344         })
345     }
346
347     #[inline]
348     fn size_hint(&self) -> (usize, Option<usize>) {
349         if self.is_empty() {
350             return (0, Some(0));
351         }
352
353         match Step::steps_between(&self.start, &self.end) {
354             Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
355             None => (0, None),
356         }
357     }
358
359     #[inline]
360     fn nth(&mut self, n: usize) -> Option<A> {
361         self.compute_is_empty();
362         if self.is_empty.unwrap_or_default() {
363             return None;
364         }
365
366         if let Some(plus_n) = self.start.add_usize(n) {
367             use cmp::Ordering::*;
368
369             match plus_n.partial_cmp(&self.end) {
370                 Some(Less) => {
371                     self.is_empty = Some(false);
372                     self.start = plus_n.add_one();
373                     return Some(plus_n)
374                 }
375                 Some(Equal) => {
376                     self.is_empty = Some(true);
377                     return Some(plus_n)
378                 }
379                 _ => {}
380             }
381         }
382
383         self.is_empty = Some(true);
384         None
385     }
386
387     #[inline]
388     fn last(mut self) -> Option<A> {
389         self.next_back()
390     }
391
392     #[inline]
393     fn min(mut self) -> Option<A> {
394         self.next()
395     }
396
397     #[inline]
398     fn max(mut self) -> Option<A> {
399         self.next_back()
400     }
401 }
402
403 #[stable(feature = "inclusive_range", since = "1.26.0")]
404 impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
405     #[inline]
406     fn next_back(&mut self) -> Option<A> {
407         self.compute_is_empty();
408         if self.is_empty.unwrap_or_default() {
409             return None;
410         }
411         let is_iterating = self.start < self.end;
412         self.is_empty = Some(!is_iterating);
413         Some(if is_iterating {
414             let n = self.end.sub_one();
415             mem::replace(&mut self.end, n)
416         } else {
417             self.end.clone()
418         })
419     }
420 }
421
422 #[stable(feature = "fused", since = "1.26.0")]
423 impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}