|  | 
| 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