summaryrefslogtreecommitdiffstats
path: root/library/core/src/iter/range.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/iter/range.rs')
-rw-r--r--library/core/src/iter/range.rs130
1 files changed, 129 insertions, 1 deletions
diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 462f7170a..0e03d0c2d 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,5 +1,7 @@
+use crate::ascii::Char as AsciiChar;
use crate::convert::TryFrom;
use crate::mem;
+use crate::net::{Ipv4Addr, Ipv6Addr};
use crate::num::NonZeroUsize;
use crate::ops::{self, Try};
@@ -14,7 +16,7 @@ macro_rules! unsafe_impl_trusted_step {
unsafe impl TrustedStep for $type {}
)*};
}
-unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
+unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize Ipv4Addr Ipv6Addr];
/// Objects that have a notion of *successor* and *predecessor* operations.
///
@@ -484,6 +486,112 @@ impl Step for char {
}
}
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for AsciiChar {
+ #[inline]
+ fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> Option<usize> {
+ Step::steps_between(&start.to_u8(), &end.to_u8())
+ }
+
+ #[inline]
+ fn forward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
+ let end = Step::forward_checked(start.to_u8(), count)?;
+ AsciiChar::from_u8(end)
+ }
+
+ #[inline]
+ fn backward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
+ let end = Step::backward_checked(start.to_u8(), count)?;
+
+ // SAFETY: Values below that of a valid ASCII character are also valid ASCII
+ Some(unsafe { AsciiChar::from_u8_unchecked(end) })
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
+ // SAFETY: Caller asserts that result is a valid ASCII character,
+ // and therefore it is a valid u8.
+ let end = unsafe { Step::forward_unchecked(start.to_u8(), count) };
+
+ // SAFETY: Caller asserts that result is a valid ASCII character.
+ unsafe { AsciiChar::from_u8_unchecked(end) }
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
+ // SAFETY: Caller asserts that result is a valid ASCII character,
+ // and therefore it is a valid u8.
+ let end = unsafe { Step::backward_unchecked(start.to_u8(), count) };
+
+ // SAFETY: Caller asserts that result is a valid ASCII character.
+ unsafe { AsciiChar::from_u8_unchecked(end) }
+ }
+}
+
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for Ipv4Addr {
+ #[inline]
+ fn steps_between(&start: &Ipv4Addr, &end: &Ipv4Addr) -> Option<usize> {
+ u32::steps_between(&start.to_bits(), &end.to_bits())
+ }
+
+ #[inline]
+ fn forward_checked(start: Ipv4Addr, count: usize) -> Option<Ipv4Addr> {
+ u32::forward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits)
+ }
+
+ #[inline]
+ fn backward_checked(start: Ipv4Addr, count: usize) -> Option<Ipv4Addr> {
+ u32::backward_checked(start.to_bits(), count).map(Ipv4Addr::from_bits)
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
+ // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
+ // this is as safe as the u32 version.
+ Ipv4Addr::from_bits(unsafe { u32::forward_unchecked(start.to_bits(), count) })
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: Ipv4Addr, count: usize) -> Ipv4Addr {
+ // SAFETY: Since u32 and Ipv4Addr are losslessly convertible,
+ // this is as safe as the u32 version.
+ Ipv4Addr::from_bits(unsafe { u32::backward_unchecked(start.to_bits(), count) })
+ }
+}
+
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+impl Step for Ipv6Addr {
+ #[inline]
+ fn steps_between(&start: &Ipv6Addr, &end: &Ipv6Addr) -> Option<usize> {
+ u128::steps_between(&start.to_bits(), &end.to_bits())
+ }
+
+ #[inline]
+ fn forward_checked(start: Ipv6Addr, count: usize) -> Option<Ipv6Addr> {
+ u128::forward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits)
+ }
+
+ #[inline]
+ fn backward_checked(start: Ipv6Addr, count: usize) -> Option<Ipv6Addr> {
+ u128::backward_checked(start.to_bits(), count).map(Ipv6Addr::from_bits)
+ }
+
+ #[inline]
+ unsafe fn forward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr {
+ // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
+ // this is as safe as the u128 version.
+ Ipv6Addr::from_bits(unsafe { u128::forward_unchecked(start.to_bits(), count) })
+ }
+
+ #[inline]
+ unsafe fn backward_unchecked(start: Ipv6Addr, count: usize) -> Ipv6Addr {
+ // SAFETY: Since u128 and Ipv6Addr are losslessly convertible,
+ // this is as safe as the u128 version.
+ Ipv6Addr::from_bits(unsafe { u128::backward_unchecked(start.to_bits(), count) })
+ }
+}
+
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
@@ -723,6 +831,15 @@ impl<A: Step> Iterator for ops::Range<A> {
}
#[inline]
+ fn count(self) -> usize {
+ if self.start < self.end {
+ Step::steps_between(&self.start, &self.end).expect("count overflowed usize")
+ } else {
+ 0
+ }
+ }
+
+ #[inline]
fn nth(&mut self, n: usize) -> Option<A> {
self.spec_nth(n)
}
@@ -1120,6 +1237,17 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
}
#[inline]
+ fn count(self) -> usize {
+ if self.is_empty() {
+ return 0;
+ }
+
+ Step::steps_between(&self.start, &self.end)
+ .and_then(|steps| steps.checked_add(1))
+ .expect("count overflowed usize")
+ }
+
+ #[inline]
fn nth(&mut self, n: usize) -> Option<A> {
if self.is_empty() {
return None;