Skip to content

Commit

Permalink
Auto merge of #77853 - ijackson:slice-strip-stab, r=Amanieu
Browse files Browse the repository at this point in the history
Stabilize slice::strip_prefix and slice::strip_suffix

These two methods are useful.  The corresponding methods on `str` are already stable.

I believe that stablising these now would not get in the way of, in the future, extending these to take a richer pattern API a la `str`'s patterns.

Tracking PR: #73413.  I also have an outstanding PR to improve the docs for these two functions and the corresponding ones on `str`: #75078

I have tried to follow the [instructions in the dev guide](https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr).  The part to do with `compiler/rustc_feature` did not seem applicable.  I assume that's because these are just library features, so there is no corresponding machinery in rustc.
  • Loading branch information
bors committed Jan 7, 2021
2 parents b5c496d + 8b2e79d commit 8f0b945
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
50 changes: 44 additions & 6 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1872,19 +1872,24 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(slice_strip)]
/// let v = &[10, 40, 30];
/// assert_eq!(v.strip_prefix(&[10]), Some(&[40, 30][..]));
/// assert_eq!(v.strip_prefix(&[10, 40]), Some(&[30][..]));
/// assert_eq!(v.strip_prefix(&[50]), None);
/// assert_eq!(v.strip_prefix(&[10, 50]), None);
///
/// let prefix : &str = "he";
/// assert_eq!(b"hello".strip_prefix(prefix.as_bytes()),
/// Some(b"llo".as_ref()));
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[unstable(feature = "slice_strip", issue = "73413")]
pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
#[stable(feature = "slice_strip", since = "1.50.0")]
pub fn strip_prefix<P: SlicePattern<Item = T> + ?Sized>(&self, prefix: &P) -> Option<&[T]>
where
T: PartialEq,
{
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
let prefix = prefix.as_slice();
let n = prefix.len();
if n <= self.len() {
let (head, tail) = self.split_at(n);
Expand All @@ -1905,19 +1910,20 @@ impl<T> [T] {
/// # Examples
///
/// ```
/// #![feature(slice_strip)]
/// let v = &[10, 40, 30];
/// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
/// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
/// assert_eq!(v.strip_suffix(&[50]), None);
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
/// ```
#[must_use = "returns the subslice without modifying the original"]
#[unstable(feature = "slice_strip", issue = "73413")]
pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
#[stable(feature = "slice_strip", since = "1.50.0")]
pub fn strip_suffix<P: SlicePattern<Item = T> + ?Sized>(&self, suffix: &P) -> Option<&[T]>
where
T: PartialEq,
{
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
let suffix = suffix.as_slice();
let (len, n) = (self.len(), suffix.len());
if n <= len {
let (head, tail) = self.split_at(len - n);
Expand Down Expand Up @@ -3310,3 +3316,35 @@ impl<T> Default for &mut [T] {
&mut []
}
}

#[unstable(feature = "slice_pattern", reason = "stopgap trait for slice patterns", issue = "56345")]
/// Patterns in slices - currently, only used by `strip_prefix` and `strip_suffix`. At a future
/// point, we hope to generalise `core::str::Pattern` (which at the time of writing is limited to
/// `str`) to slices, and then this trait will be replaced or abolished.
pub trait SlicePattern {
/// The element type of the slice being matched on.
type Item;

/// Currently, the consumers of `SlicePattern` need a slice.
fn as_slice(&self) -> &[Self::Item];
}

#[stable(feature = "slice_strip", since = "1.50.0")]
impl<T> SlicePattern for [T] {
type Item = T;

#[inline]
fn as_slice(&self) -> &[Self::Item] {
self
}
}

#[stable(feature = "slice_strip", since = "1.50.0")]
impl<T, const N: usize> SlicePattern for [T; N] {
type Item = T;

#[inline]
fn as_slice(&self) -> &[Self::Item] {
self
}
}
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,6 @@
#![feature(slice_internals)]
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_strip)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(stdsimd)]
Expand Down

0 comments on commit 8f0b945

Please sign in to comment.