Auto merge of #52994 - varkor:trim_direction, r=alexcrichton
Add trim_start, trim_end etc.; deprecate trim_left, trim_right, etc. in future Adds the methods: `trim_start`, `trim_end`, `trim_start_matches` and `trim_end_matches`. Deprecates `trim_left`, `trim_right`, `trim_left_matches` and `trim_right_matches` starting from Rust 1.33.0, three versions from when they'll initially be marked as being deprecated, using the future deprecation from https://github.com/rust-lang/rust/issues/30785 and https://github.com/rust-lang/rust/pull/51681. Fixes https://github.com/rust-lang/rust/issues/30459.
This commit is contained in:
commit
8b7f164eab
@ -727,33 +727,33 @@ fn test_is_char_boundary() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_left_matches() {
|
||||
fn test_trim_start_matches() {
|
||||
let v: &[char] = &[];
|
||||
assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
|
||||
assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
|
||||
let chars: &[char] = &['*', ' '];
|
||||
assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
|
||||
assert_eq!(" *** *** ".trim_left_matches(chars), "");
|
||||
assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
|
||||
assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
|
||||
assert_eq!(" *** *** ".trim_start_matches(chars), "");
|
||||
assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
|
||||
|
||||
assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
|
||||
assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
|
||||
let chars: &[char] = &['1', '2'];
|
||||
assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
|
||||
assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
|
||||
assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
|
||||
assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_right_matches() {
|
||||
fn test_trim_end_matches() {
|
||||
let v: &[char] = &[];
|
||||
assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
|
||||
assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
|
||||
let chars: &[char] = &['*', ' '];
|
||||
assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
|
||||
assert_eq!(" *** *** ".trim_right_matches(chars), "");
|
||||
assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
|
||||
assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
|
||||
assert_eq!(" *** *** ".trim_end_matches(chars), "");
|
||||
assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
|
||||
|
||||
assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
|
||||
assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
|
||||
let chars: &[char] = &['1', '2'];
|
||||
assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
|
||||
assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
|
||||
assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
|
||||
assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -772,23 +772,23 @@ fn test_trim_matches() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_left() {
|
||||
assert_eq!("".trim_left(), "");
|
||||
assert_eq!("a".trim_left(), "a");
|
||||
assert_eq!(" ".trim_left(), "");
|
||||
assert_eq!(" blah".trim_left(), "blah");
|
||||
assert_eq!(" \u{3000} wut".trim_left(), "wut");
|
||||
assert_eq!("hey ".trim_left(), "hey ");
|
||||
fn test_trim_start() {
|
||||
assert_eq!("".trim_start(), "");
|
||||
assert_eq!("a".trim_start(), "a");
|
||||
assert_eq!(" ".trim_start(), "");
|
||||
assert_eq!(" blah".trim_start(), "blah");
|
||||
assert_eq!(" \u{3000} wut".trim_start(), "wut");
|
||||
assert_eq!("hey ".trim_start(), "hey ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_right() {
|
||||
assert_eq!("".trim_right(), "");
|
||||
assert_eq!("a".trim_right(), "a");
|
||||
assert_eq!(" ".trim_right(), "");
|
||||
assert_eq!("blah ".trim_right(), "blah");
|
||||
assert_eq!("wut \u{3000} ".trim_right(), "wut");
|
||||
assert_eq!(" hey".trim_right(), " hey");
|
||||
fn test_trim_end() {
|
||||
assert_eq!("".trim_end(), "");
|
||||
assert_eq!("a".trim_end(), "a");
|
||||
assert_eq!(" ".trim_end(), "");
|
||||
assert_eq!("blah ".trim_end(), "blah");
|
||||
assert_eq!("wut \u{3000} ".trim_end(), "wut");
|
||||
assert_eq!(" hey".trim_end(), " hey");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1518,12 +1518,20 @@ fn trim_ws() {
|
||||
"a \t ");
|
||||
assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
|
||||
" \t a");
|
||||
assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"a \t ");
|
||||
assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
" \t a");
|
||||
assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
|
||||
"a");
|
||||
assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
|
||||
"");
|
||||
}
|
||||
|
@ -3563,6 +3563,76 @@ impl str {
|
||||
self.trim_matches(|c: char| c.is_whitespace())
|
||||
}
|
||||
|
||||
/// Returns a string slice with leading whitespace removed.
|
||||
///
|
||||
/// 'Whitespace' is defined according to the terms of the Unicode Derived
|
||||
/// Core Property `White_Space`.
|
||||
///
|
||||
/// # Text directionality
|
||||
///
|
||||
/// A string is a sequence of bytes. `start` in this context means the first
|
||||
/// position of that byte string; for a left-to-right language like English or
|
||||
/// Russian, this will be left side; and for right-to-left languages like
|
||||
/// like Arabic or Hebrew, this will be the right side.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let s = " Hello\tworld\t";
|
||||
/// assert_eq!("Hello\tworld\t", s.trim_start());
|
||||
/// ```
|
||||
///
|
||||
/// Directionality:
|
||||
///
|
||||
/// ```
|
||||
/// let s = " English ";
|
||||
/// assert!(Some('E') == s.trim_start().chars().next());
|
||||
///
|
||||
/// let s = " עברית ";
|
||||
/// assert!(Some('ע') == s.trim_start().chars().next());
|
||||
/// ```
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_start(&self) -> &str {
|
||||
self.trim_start_matches(|c: char| c.is_whitespace())
|
||||
}
|
||||
|
||||
/// Returns a string slice with trailing whitespace removed.
|
||||
///
|
||||
/// 'Whitespace' is defined according to the terms of the Unicode Derived
|
||||
/// Core Property `White_Space`.
|
||||
///
|
||||
/// # Text directionality
|
||||
///
|
||||
/// A string is a sequence of bytes. `end` in this context means the last
|
||||
/// position of that byte string; for a left-to-right language like English or
|
||||
/// Russian, this will be right side; and for right-to-left languages like
|
||||
/// like Arabic or Hebrew, this will be the left side.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let s = " Hello\tworld\t";
|
||||
/// assert_eq!(" Hello\tworld", s.trim_end());
|
||||
/// ```
|
||||
///
|
||||
/// Directionality:
|
||||
///
|
||||
/// ```
|
||||
/// let s = " English ";
|
||||
/// assert!(Some('h') == s.trim_end().chars().rev().next());
|
||||
///
|
||||
/// let s = " עברית ";
|
||||
/// assert!(Some('ת') == s.trim_end().chars().rev().next());
|
||||
/// ```
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_end(&self) -> &str {
|
||||
self.trim_end_matches(|c: char| c.is_whitespace())
|
||||
}
|
||||
|
||||
/// Returns a string slice with leading whitespace removed.
|
||||
///
|
||||
/// 'Whitespace' is defined according to the terms of the Unicode Derived
|
||||
@ -3595,8 +3665,9 @@ impl str {
|
||||
/// assert!(Some('ע') == s.trim_left().chars().next());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_start`", since = "1.33.0")]
|
||||
pub fn trim_left(&self) -> &str {
|
||||
self.trim_left_matches(|c: char| c.is_whitespace())
|
||||
self.trim_start()
|
||||
}
|
||||
|
||||
/// Returns a string slice with trailing whitespace removed.
|
||||
@ -3631,8 +3702,9 @@ impl str {
|
||||
/// assert!(Some('ת') == s.trim_right().chars().rev().next());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_end`", since = "1.33.0")]
|
||||
pub fn trim_right(&self) -> &str {
|
||||
self.trim_right_matches(|c: char| c.is_whitespace())
|
||||
self.trim_end()
|
||||
}
|
||||
|
||||
/// Returns a string slice with all prefixes and suffixes that match a
|
||||
@ -3697,14 +3769,14 @@ impl str {
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
|
||||
/// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
|
||||
/// assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
|
||||
/// assert_eq!("123foo1bar123".trim_start_matches(char::is_numeric), "foo1bar123");
|
||||
///
|
||||
/// let x: &[_] = &['1', '2'];
|
||||
/// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
|
||||
/// assert_eq!("12foo1bar12".trim_start_matches(x), "foo1bar12");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_start_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
let mut i = self.len();
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((a, _)) = matcher.next_reject() {
|
||||
@ -3734,6 +3806,85 @@ impl str {
|
||||
/// Simple patterns:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
|
||||
/// assert_eq!("123foo1bar123".trim_end_matches(char::is_numeric), "123foo1bar");
|
||||
///
|
||||
/// let x: &[_] = &['1', '2'];
|
||||
/// assert_eq!("12foo1bar12".trim_end_matches(x), "12foo1bar");
|
||||
/// ```
|
||||
///
|
||||
/// A more complex pattern, using a closure:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("1fooX".trim_end_matches(|c| c == '1' || c == 'X'), "1foo");
|
||||
/// ```
|
||||
#[stable(feature = "trim_direction", since = "1.30.0")]
|
||||
pub fn trim_end_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
{
|
||||
let mut j = 0;
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((_, b)) = matcher.next_reject_back() {
|
||||
j = b;
|
||||
}
|
||||
unsafe {
|
||||
// Searcher is known to return valid indices
|
||||
self.get_unchecked(0..j)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a string slice with all prefixes that match a pattern
|
||||
/// repeatedly removed.
|
||||
///
|
||||
/// The pattern can be a `&str`, [`char`], or a closure that determines if
|
||||
/// a character matches.
|
||||
///
|
||||
/// [`char`]: primitive.char.html
|
||||
///
|
||||
/// # Text directionality
|
||||
///
|
||||
/// A string is a sequence of bytes. 'Left' in this context means the first
|
||||
/// position of that byte string; for a language like Arabic or Hebrew
|
||||
/// which are 'right to left' rather than 'left to right', this will be
|
||||
/// the _right_ side, not the left.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
|
||||
/// assert_eq!("123foo1bar123".trim_left_matches(char::is_numeric), "foo1bar123");
|
||||
///
|
||||
/// let x: &[_] = &['1', '2'];
|
||||
/// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_start_matches`", since = "1.33.0")]
|
||||
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
self.trim_start_matches(pat)
|
||||
}
|
||||
|
||||
/// Returns a string slice with all suffixes that match a pattern
|
||||
/// repeatedly removed.
|
||||
///
|
||||
/// The pattern can be a `&str`, [`char`], or a closure that
|
||||
/// determines if a character matches.
|
||||
///
|
||||
/// [`char`]: primitive.char.html
|
||||
///
|
||||
/// # Text directionality
|
||||
///
|
||||
/// A string is a sequence of bytes. 'Right' in this context means the last
|
||||
/// position of that byte string; for a language like Arabic or Hebrew
|
||||
/// which are 'right to left' rather than 'left to right', this will be
|
||||
/// the _left_ side, not the right.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Simple patterns:
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
|
||||
/// assert_eq!("123foo1bar123".trim_right_matches(char::is_numeric), "123foo1bar");
|
||||
///
|
||||
@ -3747,18 +3898,11 @@ impl str {
|
||||
/// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_end_matches`", since = "1.33.0")]
|
||||
pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
{
|
||||
let mut j = 0;
|
||||
let mut matcher = pat.into_searcher(self);
|
||||
if let Some((_, b)) = matcher.next_reject_back() {
|
||||
j = b;
|
||||
}
|
||||
unsafe {
|
||||
// Searcher is known to return valid indices
|
||||
self.get_unchecked(0..j)
|
||||
}
|
||||
self.trim_end_matches(pat)
|
||||
}
|
||||
|
||||
/// Parses this string slice into another type.
|
||||
|
Loading…
Reference in New Issue
Block a user