diff options
| author | CAD97 <cad97@cad97.com> | 2020-05-20 23:46:57 -0400 |
|---|---|---|
| committer | CAD97 <cad97@cad97.com> | 2020-05-21 00:54:46 -0400 |
| commit | 96f387920c21a83fa620b1838066fd4c73c4b486 (patch) | |
| tree | fca025c1dd18616daaa7dfe407ffc842f1c561d5 | |
| parent | 3a7dfda40a3e798bf086bd58cc7e5e09deb808b5 (diff) | |
| download | rust-96f387920c21a83fa620b1838066fd4c73c4b486.tar.gz rust-96f387920c21a83fa620b1838066fd4c73c4b486.zip | |
impl Step for char
Enables Range<char> to be iterable
Note: https://rust.godbolt.org/z/fdveKo
An iteration over all char ('\0'..=char::MAX)
includes unreachable panic code currently.
Updating RangeInclusive::next to call
Step::forward_unchecked (which is safe to do
but not done yet becuase it wasn't necessary)
successfully removes the panic from this iteration.
| -rw-r--r-- | src/libcore/iter/range.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index d74df82bddd..6837aab7af1 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -1,3 +1,4 @@ +use crate::char; use crate::convert::TryFrom; use crate::mem; use crate::ops::{self, Add, Sub, Try}; @@ -400,6 +401,69 @@ step_integer_impls! { wider than usize: [u32 i32], [u64 i64], [u128 i128]; } +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +unsafe impl Step for char { + #[inline] + fn steps_between(&start: &char, &end: &char) -> Option<usize> { + let start = start as u32; + let end = end as u32; + if start <= end { + let count = end - start + 1; + if start < 0xD800 && 0xE000 <= end { + usize::try_from(count - 0x800).ok() + } else { + usize::try_from(count).ok() + } + } else { + None + } + } + + #[inline] + fn forward_checked(start: char, count: usize) -> Option<char> { + let start = start as u32; + let mut res = Step::forward_checked(start, count)?; + if start < 0xD800 && 0xD800 <= res { + res = Step::forward_checked(res, 0x800)?; + } + if res <= char::MAX as u32 { + Some(unsafe { char::from_u32_unchecked(res) }) + } else { + None + } + } + + #[inline] + fn backward_checked(start: char, count: usize) -> Option<char> { + let start = start as u32; + let mut res = Step::backward_checked(start, count)?; + if start >= 0xE000 && 0xE000 > res { + res = Step::backward_checked(res, 0x800)?; + } + Some(unsafe { char::from_u32_unchecked(res) }) + } + + #[inline] + unsafe fn forward_unchecked(start: char, count: usize) -> char { + let start = start as u32; + let mut res = Step::forward_unchecked(start, count); + if start < 0xD800 && 0xD800 <= res { + res = Step::forward_unchecked(res, 0x800); + } + char::from_u32_unchecked(res) + } + + #[inline] + unsafe fn backward_unchecked(start: char, count: usize) -> char { + let start = start as u32; + let mut res = Step::backward_unchecked(start, count); + if start >= 0xE000 && 0xE000 > res { + res = Step::backward_unchecked(res, 0x800); + } + char::from_u32_unchecked(res) + } +} + macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] |
