Rollup merge of #41065 - jorendorff:slice-rsplit-41020, r=alexcrichton
[T]::rsplit() and rsplit_mut(), #41020
This commit is contained in:
commit
d8b61091f6
@ -172,6 +172,7 @@
|
||||
- [slice_concat_ext](slice-concat-ext.md)
|
||||
- [slice_get_slice](slice-get-slice.md)
|
||||
- [slice_patterns](slice-patterns.md)
|
||||
- [slice_rsplit](slice-rsplit.md)
|
||||
- [sort_internals](sort-internals.md)
|
||||
- [sort_unstable](sort-unstable.md)
|
||||
- [specialization](specialization.md)
|
||||
|
10
src/doc/unstable-book/src/slice-rsplit.md
Normal file
10
src/doc/unstable-book/src/slice-rsplit.md
Normal file
@ -0,0 +1,10 @@
|
||||
# `slice_rsplit`
|
||||
|
||||
The tracking issue for this feature is: [#41020]
|
||||
|
||||
[#41020]: https://github.com/rust-lang/rust/issues/41020
|
||||
|
||||
------------------------
|
||||
|
||||
The `slice_rsplit` feature enables two methods on slices:
|
||||
`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`.
|
@ -52,6 +52,7 @@
|
||||
#![feature(shared)]
|
||||
#![feature(slice_get_slice)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(slice_rsplit)]
|
||||
#![cfg_attr(not(test), feature(sort_unstable))]
|
||||
#![feature(specialization)]
|
||||
#![feature(staged_api)]
|
||||
|
@ -115,6 +115,8 @@ pub use core::slice::{Iter, IterMut};
|
||||
pub use core::slice::{SplitMut, ChunksMut, Split};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
pub use core::slice::{RSplit, RSplitMut};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
|
||||
#[unstable(feature = "slice_get_slice", issue = "35729")]
|
||||
@ -779,6 +781,72 @@ impl<T> [T] {
|
||||
core_slice::SliceExt::split_mut(self, pred)
|
||||
}
|
||||
|
||||
/// Returns an iterator over subslices separated by elements that match
|
||||
/// `pred`, starting at the end of the slice and working backwards.
|
||||
/// The matched element is not contained in the subslices.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_rsplit)]
|
||||
///
|
||||
/// let slice = [11, 22, 33, 0, 44, 55];
|
||||
/// let mut iter = slice.rsplit(|num| *num == 0);
|
||||
///
|
||||
/// assert_eq!(iter.next().unwrap(), &[44, 55]);
|
||||
/// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
|
||||
/// assert_eq!(iter.next(), None);
|
||||
/// ```
|
||||
///
|
||||
/// As with `split()`, if the first or last element is matched, an empty
|
||||
/// slice will be the first (or last) item returned by the iterator.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_rsplit)]
|
||||
///
|
||||
/// let v = &[0, 1, 1, 2, 3, 5, 8];
|
||||
/// let mut it = v.rsplit(|n| *n % 2 == 0);
|
||||
/// assert_eq!(it.next().unwrap(), &[]);
|
||||
/// assert_eq!(it.next().unwrap(), &[3, 5]);
|
||||
/// assert_eq!(it.next().unwrap(), &[1, 1]);
|
||||
/// assert_eq!(it.next().unwrap(), &[]);
|
||||
/// assert_eq!(it.next(), None);
|
||||
/// ```
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
#[inline]
|
||||
pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
|
||||
where F: FnMut(&T) -> bool
|
||||
{
|
||||
core_slice::SliceExt::rsplit(self, pred)
|
||||
}
|
||||
|
||||
/// Returns an iterator over mutable subslices separated by elements that
|
||||
/// match `pred`, starting at the end of the slice and working
|
||||
/// backwards. The matched element is not contained in the subslices.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(slice_rsplit)]
|
||||
///
|
||||
/// let mut v = [100, 400, 300, 200, 600, 500];
|
||||
///
|
||||
/// let mut count = 0;
|
||||
/// for group in v.rsplit_mut(|num| *num % 3 == 0) {
|
||||
/// count += 1;
|
||||
/// group[0] = count;
|
||||
/// }
|
||||
/// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
|
||||
/// ```
|
||||
///
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
#[inline]
|
||||
pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
|
||||
where F: FnMut(&T) -> bool
|
||||
{
|
||||
core_slice::SliceExt::rsplit_mut(self, pred)
|
||||
}
|
||||
|
||||
/// Returns an iterator over subslices separated by elements that match
|
||||
/// `pred`, limited to returning at most `n` items. The matched element is
|
||||
/// not contained in the subslices.
|
||||
|
@ -81,6 +81,10 @@ pub trait SliceExt {
|
||||
fn split<P>(&self, pred: P) -> Split<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
@ -159,6 +163,10 @@ pub trait SliceExt {
|
||||
fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<Self::Item, P>
|
||||
where P: FnMut(&Self::Item) -> bool;
|
||||
@ -293,6 +301,13 @@ impl<T> SliceExt for [T] {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rsplit<P>(&self, pred: P) -> RSplit<T, P>
|
||||
where P: FnMut(&T) -> bool
|
||||
{
|
||||
RSplit { inner: self.split(pred) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
|
||||
where P: FnMut(&T) -> bool
|
||||
@ -300,8 +315,7 @@ impl<T> SliceExt for [T] {
|
||||
SplitN {
|
||||
inner: GenericSplitN {
|
||||
iter: self.split(pred),
|
||||
count: n,
|
||||
invert: false
|
||||
count: n
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -312,9 +326,8 @@ impl<T> SliceExt for [T] {
|
||||
{
|
||||
RSplitN {
|
||||
inner: GenericSplitN {
|
||||
iter: self.split(pred),
|
||||
count: n,
|
||||
invert: true
|
||||
iter: self.rsplit(pred),
|
||||
count: n
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -475,6 +488,13 @@ impl<T> SliceExt for [T] {
|
||||
SplitMut { v: self, pred: pred, finished: false }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
|
||||
where P: FnMut(&T) -> bool
|
||||
{
|
||||
RSplitMut { inner: self.split_mut(pred) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
|
||||
where P: FnMut(&T) -> bool
|
||||
@ -482,8 +502,7 @@ impl<T> SliceExt for [T] {
|
||||
SplitNMut {
|
||||
inner: GenericSplitN {
|
||||
iter: self.split_mut(pred),
|
||||
count: n,
|
||||
invert: false
|
||||
count: n
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -494,9 +513,8 @@ impl<T> SliceExt for [T] {
|
||||
{
|
||||
RSplitNMut {
|
||||
inner: GenericSplitN {
|
||||
iter: self.split_mut(pred),
|
||||
count: n,
|
||||
invert: true
|
||||
iter: self.rsplit_mut(pred),
|
||||
count: n
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1736,6 +1754,123 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
|
||||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
|
||||
|
||||
/// An iterator over subslices separated by elements that match a predicate
|
||||
/// function, starting from the end of the slice.
|
||||
///
|
||||
/// This struct is created by the [`rsplit`] method on [slices].
|
||||
///
|
||||
/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
|
||||
pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
|
||||
inner: Split<'a, T, P>
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("RSplit")
|
||||
.field("v", &self.inner.v)
|
||||
.field("finished", &self.inner.finished)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
type Item = &'a [T];
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a [T]> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a [T]> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
#[inline]
|
||||
fn finish(&mut self) -> Option<&'a [T]> {
|
||||
self.inner.finish()
|
||||
}
|
||||
}
|
||||
|
||||
//#[unstable(feature = "fused", issue = "35602")]
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
|
||||
|
||||
/// An iterator over the subslices of the vector which are separated
|
||||
/// by elements that match `pred`, starting from the end of the slice.
|
||||
///
|
||||
/// This struct is created by the [`rsplit_mut`] method on [slices].
|
||||
///
|
||||
/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
|
||||
inner: SplitMut<'a, T, P>
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("RSplitMut")
|
||||
.field("v", &self.inner.v)
|
||||
.field("finished", &self.inner.finished)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
#[inline]
|
||||
fn finish(&mut self) -> Option<&'a mut [T]> {
|
||||
self.inner.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
type Item = &'a mut [T];
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a mut [T]> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
|
||||
P: FnMut(&T) -> bool,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a mut [T]> {
|
||||
self.inner.next()
|
||||
}
|
||||
}
|
||||
|
||||
//#[unstable(feature = "fused", issue = "35602")]
|
||||
#[unstable(feature = "slice_rsplit", issue = "41020")]
|
||||
impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
|
||||
|
||||
/// An private iterator over subslices separated by elements that
|
||||
/// match a predicate function, splitting at most a fixed number of
|
||||
/// times.
|
||||
@ -1743,7 +1878,6 @@ impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
struct GenericSplitN<I> {
|
||||
iter: I,
|
||||
count: usize,
|
||||
invert: bool
|
||||
}
|
||||
|
||||
impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
|
||||
@ -1754,10 +1888,7 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
|
||||
match self.count {
|
||||
0 => None,
|
||||
1 => { self.count -= 1; self.iter.finish() }
|
||||
_ => {
|
||||
self.count -= 1;
|
||||
if self.invert {self.iter.next_back()} else {self.iter.next()}
|
||||
}
|
||||
_ => { self.count -= 1; self.iter.next() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1799,7 +1930,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
|
||||
inner: GenericSplitN<Split<'a, T, P>>
|
||||
inner: GenericSplitN<RSplit<'a, T, P>>
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
@ -1842,7 +1973,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMu
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
|
||||
inner: GenericSplitN<SplitMut<'a, T, P>>
|
||||
inner: GenericSplitN<RSplitMut<'a, T, P>>
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
|
Loading…
Reference in New Issue
Block a user