Skip to content

Add ASCII whitespace trimming functions to &str #118523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions library/core/src/slice/ascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ impl [u8] {
/// assert_eq!(b"".trim_ascii_start(), b"");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[inline]
pub const fn trim_ascii_start(&self) -> &[u8] {
let mut bytes = self;
// Note: A pattern matching based approach (instead of indexing) allows
Expand Down Expand Up @@ -154,6 +155,7 @@ impl [u8] {
/// assert_eq!(b"".trim_ascii_end(), b"");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[inline]
pub const fn trim_ascii_end(&self) -> &[u8] {
let mut bytes = self;
// Note: A pattern matching based approach (instead of indexing) allows
Expand Down Expand Up @@ -184,6 +186,7 @@ impl [u8] {
/// assert_eq!(b"".trim_ascii(), b"");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[inline]
pub const fn trim_ascii(&self) -> &[u8] {
self.trim_ascii_start().trim_ascii_end()
}
Expand Down
79 changes: 79 additions & 0 deletions library/core/src/str/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2423,6 +2423,85 @@ impl str {
me.make_ascii_lowercase()
}

/// Returns a string slice with leading ASCII whitespace removed.
///
/// 'Whitespace' refers to the definition used by
/// [`u8::is_ascii_whitespace`].
///
/// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace
///
/// # Examples
///
/// ```
/// #![feature(byte_slice_trim_ascii)]
///
/// assert_eq!(" \t \u{3000}hello world\n".trim_ascii_start(), "\u{3000}hello world\n");
/// assert_eq!(" ".trim_ascii_start(), "");
/// assert_eq!("".trim_ascii_start(), "");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[inline]
pub const fn trim_ascii_start(&self) -> &str {
// SAFETY: Removing ASCII characters from a `&str` does not invalidate
// UTF-8.
unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii_start()) }
}

/// Returns a string slice with trailing ASCII whitespace removed.
///
/// 'Whitespace' refers to the definition used by
/// [`u8::is_ascii_whitespace`].
///
/// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace
///
/// # Examples
///
/// ```
/// #![feature(byte_slice_trim_ascii)]
///
/// assert_eq!("\r hello world\u{3000}\n ".trim_ascii_end(), "\r hello world\u{3000}");
/// assert_eq!(" ".trim_ascii_end(), "");
/// assert_eq!("".trim_ascii_end(), "");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[inline]
pub const fn trim_ascii_end(&self) -> &str {
// SAFETY: Removing ASCII characters from a `&str` does not invalidate
// UTF-8.
unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii_end()) }
}

/// Returns a string slice with leading and trailing ASCII whitespace
/// removed.
///
/// 'Whitespace' refers to the definition used by
/// [`u8::is_ascii_whitespace`].
///
/// [`u8::is_ascii_whitespace`]: u8::is_ascii_whitespace
///
/// # Examples
///
/// ```
/// #![feature(byte_slice_trim_ascii)]
///
/// assert_eq!("\r hello world\n ".trim_ascii(), "hello world");
/// assert_eq!(" ".trim_ascii(), "");
/// assert_eq!("".trim_ascii(), "");
/// ```
#[unstable(feature = "byte_slice_trim_ascii", issue = "94035")]
#[must_use = "this returns the trimmed string as a new slice, \
without modifying the original"]
#[inline]
pub const fn trim_ascii(&self) -> &str {
// SAFETY: Removing ASCII characters from a `&str` does not invalidate
// UTF-8.
unsafe { core::str::from_utf8_unchecked(self.as_bytes().trim_ascii()) }
}

/// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
///
/// Note: only extended grapheme codepoints that begin the string will be
Expand Down