Created
January 9, 2018 22:22
-
-
Save oyvindln/a543f0d62da990c18a3575950c39ada1 to your computer and use it in GitHub Desktop.
Range specialisation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
macro_rules! spec_range { ($($t:ty)*) => | |
($( | |
impl Iterator for ops::Range<$t> { | |
#[inline] | |
default fn next(&mut self) -> Option<Self::Item> { | |
if self.start < self.end && self.start < <$t>::max_value() { | |
let temp = self.start; | |
self.start += 1; | |
Some(temp) | |
} else { | |
None | |
} | |
} | |
#[inline] | |
default fn size_hint(&self) -> (usize, Option<usize>) { | |
if self.start < self.end { | |
if let Ok(hint) = usize::try_from(self.end - self.start) { | |
return (hint, Some(hint)) | |
} | |
} | |
(0, None) | |
} | |
#[inline] | |
default fn nth(&mut self, n: usize) -> Option<Self::Item> { | |
if let Ok(nconv) = <$t>::try_from(n) { | |
if let Some(res) = self.start.checked_add(nconv) { | |
if res < self.end { | |
self.start = res + 1; | |
return Some(res) | |
} | |
} | |
} | |
self.start = self.end; | |
None | |
} | |
} | |
)*) | |
} | |
spec_range!(usize u8 u16 u32 u64); | |
spec_range!(isize i8 i16 i32 i64); | |
macro_rules! spec_range { | |
($($t:ty)*) => ($( | |
#[unstable(feature = "iterator_step_by", | |
reason = "unstable replacement of Range::step_by", | |
issue = "27741")] | |
impl Iterator for StepBy<ops::Range<$t>> { | |
#[inline] | |
fn next(&mut self) -> Option<Self::Item> { | |
if self.iter.start < self.iter.end { | |
self.first_take = false; | |
if let Ok(n) = <$t>::try_from(self.step) { | |
if let Some(step) = self.iter.start.checked_add(n) { | |
let ret = self.iter.start; | |
self.iter.start = step; | |
return Some(ret) | |
} | |
} | |
let ret = self.iter.start; | |
self.iter.start = self.iter.end; | |
Some(ret) | |
} else { | |
None | |
} | |
} | |
#[inline] | |
fn size_hint(&self) -> (usize, Option<usize>) { | |
let inner_hint = self.iter.size_hint(); | |
if self.first_take { | |
let f = |n| if n == 0 { 0 } else { 1 + (n-1)/(self.step+1) }; | |
(f(inner_hint.0), inner_hint.1.map(f)) | |
} else { | |
let f = |n| n / (self.step+1); | |
(f(inner_hint.0), inner_hint.1.map(f)) | |
} | |
} | |
} | |
)*) | |
} | |
spec_range!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment