Stablize slice::strip_prefix and strip_suffix, with SlicePattern
We hope later to extend `core::str::Pattern` to slices too, perhaps as part of stabilising that. We want to minimise the amount of type inference breakage when we do that, so we don't want to stabilise strip_prefix and strip_suffix taking a simple `&[T]`. @KodrAus suggested the approach of introducing a new perma-unstable trait, which reduces this future inference break risk. I found it necessary to make two impls of this trait, as the unsize coercion don't apply when hunting for trait implementations. Since SlicePattern's only method returns a reference, and the whole trait is just a wrapper for slices, I made the trait type be the non-reference type [T] or [T;N] rather than the reference. Otherwise the trait would have a lifetime parameter. I marked both the no-op conversion functions `#[inline]`. I'm not sure if that is necessary but it seemed at the very least harmless. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
This commit is contained in:
parent
0b644e4196
commit
274e2993cb
@ -1778,7 +1778,6 @@ impl<T> [T] {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_strip)]
|
|
||||||
/// let v = &[10, 40, 30];
|
/// let v = &[10, 40, 30];
|
||||||
/// assert_eq!(v.strip_prefix(&[10]), Some(&[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(&[10, 40]), Some(&[30][..]));
|
||||||
@ -1786,12 +1785,14 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(v.strip_prefix(&[10, 50]), None);
|
/// assert_eq!(v.strip_prefix(&[10, 50]), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "returns the subslice without modifying the original"]
|
#[must_use = "returns the subslice without modifying the original"]
|
||||||
#[unstable(feature = "slice_strip", issue = "73413")]
|
#[stable(feature = "slice_strip", since = "1.50.0")]
|
||||||
pub fn strip_prefix(&self, prefix: &[T]) -> Option<&[T]>
|
pub fn strip_prefix<P: SlicePattern<Item = T>>(&self, prefix: &P) -> Option<&[T]>
|
||||||
where
|
where
|
||||||
T: PartialEq,
|
T: PartialEq,
|
||||||
{
|
{
|
||||||
let n = prefix.len();
|
// This function will need rewriting if and when SlicePattern becomes more sophisticated.
|
||||||
|
let prefix = prefix.as_slice();
|
||||||
|
let n = prefix.as_slice().len();
|
||||||
if n <= self.len() {
|
if n <= self.len() {
|
||||||
let (head, tail) = self.split_at(n);
|
let (head, tail) = self.split_at(n);
|
||||||
if head == prefix {
|
if head == prefix {
|
||||||
@ -1811,7 +1812,6 @@ impl<T> [T] {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// #![feature(slice_strip)]
|
|
||||||
/// let v = &[10, 40, 30];
|
/// let v = &[10, 40, 30];
|
||||||
/// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
|
/// assert_eq!(v.strip_suffix(&[30]), Some(&[10, 40][..]));
|
||||||
/// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
|
/// assert_eq!(v.strip_suffix(&[40, 30]), Some(&[10][..]));
|
||||||
@ -1819,11 +1819,13 @@ impl<T> [T] {
|
|||||||
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
|
/// assert_eq!(v.strip_suffix(&[50, 30]), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[must_use = "returns the subslice without modifying the original"]
|
#[must_use = "returns the subslice without modifying the original"]
|
||||||
#[unstable(feature = "slice_strip", issue = "73413")]
|
#[stable(feature = "slice_strip", since = "1.50.0")]
|
||||||
pub fn strip_suffix(&self, suffix: &[T]) -> Option<&[T]>
|
pub fn strip_suffix<P: SlicePattern<Item = T>>(&self, suffix: &P) -> Option<&[T]>
|
||||||
where
|
where
|
||||||
T: PartialEq,
|
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());
|
let (len, n) = (self.len(), suffix.len());
|
||||||
if n <= len {
|
if n <= len {
|
||||||
let (head, tail) = self.split_at(len - n);
|
let (head, tail) = self.split_at(len - n);
|
||||||
@ -3216,3 +3218,35 @@ impl<T> Default for &mut [T] {
|
|||||||
&mut []
|
&mut []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "x", issue = "none")]
|
||||||
|
/// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -307,7 +307,6 @@
|
|||||||
#![feature(slice_internals)]
|
#![feature(slice_internals)]
|
||||||
#![feature(slice_ptr_get)]
|
#![feature(slice_ptr_get)]
|
||||||
#![feature(slice_ptr_len)]
|
#![feature(slice_ptr_len)]
|
||||||
#![feature(slice_strip)]
|
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_internals)]
|
#![feature(std_internals)]
|
||||||
#![feature(stdsimd)]
|
#![feature(stdsimd)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user