|
319 | 319 | use cmp;
|
320 | 320 | use fmt;
|
321 | 321 | use iter_private::TrustedRandomAccess;
|
322 |
| -use ops::Try; |
| 322 | +use ops::{self, Try}; |
323 | 323 | use usize;
|
324 | 324 | use intrinsics;
|
| 325 | +use mem; |
325 | 326 |
|
326 | 327 | #[stable(feature = "rust1", since = "1.0.0")]
|
327 | 328 | pub use self::iterator::Iterator;
|
@@ -672,12 +673,7 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
|
672 | 673 |
|
673 | 674 | #[inline]
|
674 | 675 | fn next(&mut self) -> Option<Self::Item> {
|
675 |
| - if self.first_take { |
676 |
| - self.first_take = false; |
677 |
| - self.iter.next() |
678 |
| - } else { |
679 |
| - self.iter.nth(self.step) |
680 |
| - } |
| 676 | + <Self as StepBySpecIterator>::spec_next(self) |
681 | 677 | }
|
682 | 678 |
|
683 | 679 | #[inline]
|
@@ -737,6 +733,76 @@ impl<I> Iterator for StepBy<I> where I: Iterator {
|
737 | 733 | }
|
738 | 734 | }
|
739 | 735 |
|
| 736 | +// hidden trait for specializing iterator methods |
| 737 | +// could be generalized but is currently only used for StepBy |
| 738 | +trait StepBySpecIterator { |
| 739 | + type Item; |
| 740 | + fn spec_next(&mut self) -> Option<Self::Item>; |
| 741 | +} |
| 742 | + |
| 743 | +impl<I> StepBySpecIterator for StepBy<I> |
| 744 | +where |
| 745 | + I: Iterator, |
| 746 | +{ |
| 747 | + type Item = I::Item; |
| 748 | + |
| 749 | + #[inline] |
| 750 | + default fn spec_next(&mut self) -> Option<I::Item> { |
| 751 | + if self.first_take { |
| 752 | + self.first_take = false; |
| 753 | + self.iter.next() |
| 754 | + } else { |
| 755 | + self.iter.nth(self.step) |
| 756 | + } |
| 757 | + } |
| 758 | +} |
| 759 | + |
| 760 | +impl<T> StepBySpecIterator for StepBy<ops::Range<T>> |
| 761 | +where |
| 762 | + T: Step, |
| 763 | +{ |
| 764 | + #[inline] |
| 765 | + fn spec_next(&mut self) -> Option<Self::Item> { |
| 766 | + self.first_take = false; |
| 767 | + if !(self.iter.start < self.iter.end) { |
| 768 | + return None; |
| 769 | + } |
| 770 | + // add 1 to self.step to get original step size back |
| 771 | + // it was decremented for the general case on construction |
| 772 | + if let Some(n) = self.iter.start.add_usize(self.step+1) { |
| 773 | + let next = mem::replace(&mut self.iter.start, n); |
| 774 | + Some(next) |
| 775 | + } else { |
| 776 | + let last = self.iter.start.clone(); |
| 777 | + self.iter.start = self.iter.end.clone(); |
| 778 | + Some(last) |
| 779 | + } |
| 780 | + } |
| 781 | +} |
| 782 | + |
| 783 | +impl<T> StepBySpecIterator for StepBy<ops::RangeInclusive<T>> |
| 784 | +where |
| 785 | + T: Step, |
| 786 | +{ |
| 787 | + #[inline] |
| 788 | + fn spec_next(&mut self) -> Option<Self::Item> { |
| 789 | + self.first_take = false; |
| 790 | + if !(self.iter.start <= self.iter.end) { |
| 791 | + return None; |
| 792 | + } |
| 793 | + // add 1 to self.step to get original step size back |
| 794 | + // it was decremented for the general case on construction |
| 795 | + if let Some(n) = self.iter.start.add_usize(self.step+1) { |
| 796 | + let next = mem::replace(&mut self.iter.start, n); |
| 797 | + Some(next) |
| 798 | + } else { |
| 799 | + let last = self.iter.start.replace_one(); |
| 800 | + self.iter.end.replace_zero(); |
| 801 | + Some(last) |
| 802 | + } |
| 803 | + } |
| 804 | +} |
| 805 | + |
740 | 806 | // StepBy can only make the iterator shorter, so the len will still fit.
|
741 | 807 | #[stable(feature = "iterator_step_by", since = "1.28.0")]
|
742 | 808 | impl<I> ExactSizeIterator for StepBy<I> where I: ExactSizeIterator {}
|
|
0 commit comments