Skip to content

Commit ea0b650

Browse files
authored
Rollup merge of rust-lang#111009 - scottmcm:ascii-char, r=BurntSushi
Add `ascii::Char` (ACP#179) ACP second: rust-lang/libs-team#179 (comment) New tracking issue: rust-lang#110998 For now this is an `enum` as `@kupiakos` [suggested](rust-lang/libs-team#179 (comment)), with the variants under a different feature flag. There's lots more things that could be added here, and place for further doc updates, but this seems like a plausible starting point PR. I've gone through and put an `as_ascii` next to every `is_ascii`: on `u8`, `char`, `[u8]`, and `str`. As a demonstration, made a commit updating some formatting code to use this: scottmcm@ascii-char-in-fmt (I don't want to include that in this PR, though, because that brings in perf questions that don't exist if this is just adding new unstable APIs.)
2 parents 8d66f01 + 8c781b0 commit ea0b650

File tree

12 files changed

+724
-1
lines changed

12 files changed

+724
-1
lines changed

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#![feature(array_into_iter_constructors)]
102102
#![feature(array_methods)]
103103
#![feature(array_windows)]
104+
#![feature(ascii_char)]
104105
#![feature(assert_matches)]
105106
#![feature(async_iterator)]
106107
#![feature(coerce_unsized)]

library/alloc/src/string.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2526,6 +2526,15 @@ impl<T: fmt::Display + ?Sized> ToString for T {
25262526
}
25272527
}
25282528

2529+
#[cfg(not(no_global_oom_handling))]
2530+
#[unstable(feature = "ascii_char", issue = "110998")]
2531+
impl ToString for core::ascii::Char {
2532+
#[inline]
2533+
fn to_string(&self) -> String {
2534+
self.as_str().to_owned()
2535+
}
2536+
}
2537+
25292538
#[cfg(not(no_global_oom_handling))]
25302539
#[stable(feature = "char_to_string_specialization", since = "1.46.0")]
25312540
impl ToString for char {

library/core/src/array/ascii.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use crate::ascii;
2+
3+
#[cfg(not(test))]
4+
impl<const N: usize> [u8; N] {
5+
/// Converts this array of bytes into a array of ASCII characters,
6+
/// or returns `None` if any of the characters is non-ASCII.
7+
#[unstable(feature = "ascii_char", issue = "110998")]
8+
#[must_use]
9+
#[inline]
10+
pub fn as_ascii(&self) -> Option<&[ascii::Char; N]> {
11+
if self.is_ascii() {
12+
// SAFETY: Just checked that it's ASCII
13+
Some(unsafe { self.as_ascii_unchecked() })
14+
} else {
15+
None
16+
}
17+
}
18+
19+
/// Converts this array of bytes into a array of ASCII characters,
20+
/// without checking whether they're valid.
21+
///
22+
/// # Safety
23+
///
24+
/// Every byte in the array must be in `0..=127`, or else this is UB.
25+
#[unstable(feature = "ascii_char", issue = "110998")]
26+
#[must_use]
27+
#[inline]
28+
pub const unsafe fn as_ascii_unchecked(&self) -> &[ascii::Char; N] {
29+
let byte_ptr: *const [u8; N] = self;
30+
let ascii_ptr = byte_ptr as *const [ascii::Char; N];
31+
// SAFETY: The caller promised all the bytes are ASCII
32+
unsafe { &*ascii_ptr }
33+
}
34+
}

library/core/src/array/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::ops::{
1717
};
1818
use crate::slice::{Iter, IterMut};
1919

20+
mod ascii;
2021
mod drain;
2122
mod equality;
2223
mod iter;

library/core/src/ascii.rs

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use crate::fmt;
1414
use crate::iter::FusedIterator;
1515
use crate::num::NonZeroUsize;
1616

17+
mod ascii_char;
18+
#[unstable(feature = "ascii_char", issue = "110998")]
19+
pub use ascii_char::AsciiChar as Char;
20+
1721
/// An iterator over the escaped version of a byte.
1822
///
1923
/// This `struct` is created by the [`escape_default`] function. See its

0 commit comments

Comments
 (0)