Skip to content

Commit ef33054

Browse files
committed
Implement Step for AsciiChar
1 parent 3071e0a commit ef33054

File tree

4 files changed

+64
-3
lines changed

4 files changed

+64
-3
lines changed

Diff for: library/core/src/iter/range.rs

+44-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ascii::Char as AsciiChar;
12
use crate::convert::TryFrom;
23
use crate::mem;
34
use crate::num::NonZeroUsize;
@@ -14,7 +15,7 @@ macro_rules! unsafe_impl_trusted_step {
1415
unsafe impl TrustedStep for $type {}
1516
)*};
1617
}
17-
unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
18+
unsafe_impl_trusted_step![AsciiChar char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize];
1819

1920
/// Objects that have a notion of *successor* and *predecessor* operations.
2021
///
@@ -484,6 +485,48 @@ impl Step for char {
484485
}
485486
}
486487

488+
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
489+
impl Step for AsciiChar {
490+
#[inline]
491+
fn steps_between(&start: &AsciiChar, &end: &AsciiChar) -> Option<usize> {
492+
Step::steps_between(&start.to_u8(), &end.to_u8())
493+
}
494+
495+
#[inline]
496+
fn forward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
497+
let end = Step::forward_checked(start.to_u8(), count)?;
498+
AsciiChar::from_u8(end)
499+
}
500+
501+
#[inline]
502+
fn backward_checked(start: AsciiChar, count: usize) -> Option<AsciiChar> {
503+
let end = Step::backward_checked(start.to_u8(), count)?;
504+
505+
// SAFETY: Values below that of a valid ASCII character are also valid ASCII
506+
Some(unsafe { AsciiChar::from_u8_unchecked(end) })
507+
}
508+
509+
#[inline]
510+
unsafe fn forward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
511+
// SAFETY: Caller asserts that result is a valid ASCII character,
512+
// and therefore it is a valid u8.
513+
let end = unsafe { Step::forward_unchecked(start.to_u8(), count) };
514+
515+
// SAFETY: Caller asserts that result is a valid ASCII character.
516+
unsafe { AsciiChar::from_u8_unchecked(end) }
517+
}
518+
519+
#[inline]
520+
unsafe fn backward_unchecked(start: AsciiChar, count: usize) -> AsciiChar {
521+
// SAFETY: Caller asserts that result is a valid ASCII character,
522+
// and therefore it is a valid u8.
523+
let end = unsafe { Step::backward_unchecked(start.to_u8(), count) };
524+
525+
// SAFETY: Caller asserts that result is a valid ASCII character.
526+
unsafe { AsciiChar::from_u8_unchecked(end) }
527+
}
528+
}
529+
487530
macro_rules! range_exact_iter_impl {
488531
($($t:ty)*) => ($(
489532
#[stable(feature = "rust1", since = "1.0.0")]

Diff for: library/core/tests/iter/range.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use core::num::NonZeroUsize;
21
use super::*;
2+
use core::ascii::Char as AsciiChar;
3+
use core::num::NonZeroUsize;
34

45
#[test]
56
fn test_range() {
@@ -39,6 +40,21 @@ fn test_char_range() {
3940
assert_eq!(('\u{D7FF}'..'\u{E000}').size_hint(), (1, Some(1)));
4041
}
4142

43+
#[test]
44+
fn test_ascii_char_range() {
45+
let from = AsciiChar::Null;
46+
let to = AsciiChar::Delete;
47+
assert!((from..=to).eq((from as u8..=to as u8).filter_map(AsciiChar::from_u8)));
48+
assert!((from..=to).rev().eq((from as u8..=to as u8).filter_map(AsciiChar::from_u8).rev()));
49+
50+
assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).count(), 26);
51+
assert_eq!((AsciiChar::CapitalA..=AsciiChar::CapitalZ).size_hint(), (26, Some(26)));
52+
assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).count(), 26);
53+
assert_eq!((AsciiChar::SmallA..=AsciiChar::SmallZ).size_hint(), (26, Some(26)));
54+
assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).count(), 10);
55+
assert_eq!((AsciiChar::Digit0..=AsciiChar::Digit9).size_hint(), (10, Some(10)));
56+
}
57+
4258
#[test]
4359
fn test_range_exhaustion() {
4460
let mut r = 10..10;

Diff for: library/core/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#![feature(array_chunks)]
33
#![feature(array_methods)]
44
#![feature(array_windows)]
5+
#![feature(ascii_char)]
6+
#![feature(ascii_char_variants)]
57
#![feature(bigint_helper_methods)]
68
#![feature(cell_update)]
79
#![feature(const_align_offset)]

Diff for: tests/ui/range/range-1.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | for i in false..true {}
1919
i64
2020
i128
2121
usize
22-
and 5 others
22+
and 6 others
2323
= note: required for `std::ops::Range<bool>` to implement `Iterator`
2424
= note: required for `std::ops::Range<bool>` to implement `IntoIterator`
2525

0 commit comments

Comments
 (0)