Skip to content

Commit 2e3f0d8

Browse files
committed
add [T]::rsplit() and rsplit_mut() #41020
1 parent 5309a3e commit 2e3f0d8

File tree

5 files changed

+219
-0
lines changed

5 files changed

+219
-0
lines changed

Diff for: src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@
171171
- [slice_concat_ext](slice-concat-ext.md)
172172
- [slice_get_slice](slice-get-slice.md)
173173
- [slice_patterns](slice-patterns.md)
174+
- [slice_rsplit](slice-rsplit.md)
174175
- [sort_internals](sort-internals.md)
175176
- [sort_unstable](sort-unstable.md)
176177
- [specialization](specialization.md)

Diff for: src/doc/unstable-book/src/slice-rsplit.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# `slice_rsplit`
2+
3+
The tracking issue for this feature is: [#41020]
4+
5+
[#41020]: https://github.com/rust-lang/rust/issues/41020
6+
7+
------------------------
8+
9+
The `slice_rsplit` feature enables two methods on slices:
10+
`slice.rsplit(predicate)` and `slice.rsplit_mut(predicate)`.

Diff for: src/libcollections/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#![feature(shared)]
5353
#![feature(slice_get_slice)]
5454
#![feature(slice_patterns)]
55+
#![feature(slice_rsplit)]
5556
#![cfg_attr(not(test), feature(sort_unstable))]
5657
#![feature(specialization)]
5758
#![feature(staged_api)]

Diff for: src/libcollections/slice.rs

+68
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ pub use core::slice::{Iter, IterMut};
115115
pub use core::slice::{SplitMut, ChunksMut, Split};
116116
#[stable(feature = "rust1", since = "1.0.0")]
117117
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
118+
#[unstable(feature = "slice_rsplit", issue = "41020")]
119+
pub use core::slice::{RSplit, RSplitMut};
118120
#[stable(feature = "rust1", since = "1.0.0")]
119121
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
120122
#[unstable(feature = "slice_get_slice", issue = "35729")]
@@ -779,6 +781,72 @@ impl<T> [T] {
779781
core_slice::SliceExt::split_mut(self, pred)
780782
}
781783

784+
/// Returns an iterator over subslices separated by elements that match
785+
/// `pred`, starting at the end of the slice and working backwards.
786+
/// The matched element is not contained in the subslices.
787+
///
788+
/// # Examples
789+
///
790+
/// ```
791+
/// #![feature(slice_rsplit)]
792+
///
793+
/// let slice = [11, 22, 33, 0, 44, 55];
794+
/// let mut iter = slice.rsplit(|num| *num == 0);
795+
///
796+
/// assert_eq!(iter.next().unwrap(), &[44, 55]);
797+
/// assert_eq!(iter.next().unwrap(), &[11, 22, 33]);
798+
/// assert_eq!(iter.next(), None);
799+
/// ```
800+
///
801+
/// As with `split()`, if the first or last element is matched, an empty
802+
/// slice will be the first (or last) item returned by the iterator.
803+
///
804+
/// ```
805+
/// #![feature(slice_rsplit)]
806+
///
807+
/// let v = &[0, 1, 1, 2, 3, 5, 8];
808+
/// let mut it = v.rsplit(|n| *n % 2 == 0);
809+
/// assert_eq!(it.next().unwrap(), &[]);
810+
/// assert_eq!(it.next().unwrap(), &[3, 5]);
811+
/// assert_eq!(it.next().unwrap(), &[1, 1]);
812+
/// assert_eq!(it.next().unwrap(), &[]);
813+
/// assert_eq!(it.next(), None);
814+
/// ```
815+
#[unstable(feature = "slice_rsplit", issue = "41020")]
816+
#[inline]
817+
pub fn rsplit<F>(&self, pred: F) -> RSplit<T, F>
818+
where F: FnMut(&T) -> bool
819+
{
820+
core_slice::SliceExt::rsplit(self, pred)
821+
}
822+
823+
/// Returns an iterator over mutable subslices separated by elements that
824+
/// match `pred`, starting at the end of the slice and working
825+
/// backwards. The matched element is not contained in the subslices.
826+
///
827+
/// # Examples
828+
///
829+
/// ```
830+
/// #![feature(slice_rsplit)]
831+
///
832+
/// let mut v = [100, 400, 300, 200, 600, 500];
833+
///
834+
/// let mut count = 0;
835+
/// for group in v.rsplit_mut(|num| *num % 3 == 0) {
836+
/// count += 1;
837+
/// group[0] = count;
838+
/// }
839+
/// assert_eq!(v, [3, 400, 300, 2, 600, 1]);
840+
/// ```
841+
///
842+
#[unstable(feature = "slice_rsplit", issue = "41020")]
843+
#[inline]
844+
pub fn rsplit_mut<F>(&mut self, pred: F) -> RSplitMut<T, F>
845+
where F: FnMut(&T) -> bool
846+
{
847+
core_slice::SliceExt::rsplit_mut(self, pred)
848+
}
849+
782850
/// Returns an iterator over subslices separated by elements that match
783851
/// `pred`, limited to returning at most `n` items. The matched element is
784852
/// not contained in the subslices.

Diff for: src/libcore/slice/mod.rs

+139
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ pub trait SliceExt {
8181
fn split<P>(&self, pred: P) -> Split<Self::Item, P>
8282
where P: FnMut(&Self::Item) -> bool;
8383

84+
#[unstable(feature = "slice_rsplit", issue = "41020")]
85+
fn rsplit<P>(&self, pred: P) -> RSplit<Self::Item, P>
86+
where P: FnMut(&Self::Item) -> bool;
87+
8488
#[stable(feature = "core", since = "1.6.0")]
8589
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<Self::Item, P>
8690
where P: FnMut(&Self::Item) -> bool;
@@ -159,6 +163,10 @@ pub trait SliceExt {
159163
fn split_mut<P>(&mut self, pred: P) -> SplitMut<Self::Item, P>
160164
where P: FnMut(&Self::Item) -> bool;
161165

166+
#[unstable(feature = "slice_rsplit", issue = "41020")]
167+
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<Self::Item, P>
168+
where P: FnMut(&Self::Item) -> bool;
169+
162170
#[stable(feature = "core", since = "1.6.0")]
163171
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<Self::Item, P>
164172
where P: FnMut(&Self::Item) -> bool;
@@ -293,6 +301,13 @@ impl<T> SliceExt for [T] {
293301
}
294302
}
295303

304+
#[inline]
305+
fn rsplit<P>(&self, pred: P) -> RSplit<T, P>
306+
where P: FnMut(&T) -> bool
307+
{
308+
RSplit { inner: self.split(pred) }
309+
}
310+
296311
#[inline]
297312
fn splitn<P>(&self, n: usize, pred: P) -> SplitN<T, P>
298313
where P: FnMut(&T) -> bool
@@ -475,6 +490,13 @@ impl<T> SliceExt for [T] {
475490
SplitMut { v: self, pred: pred, finished: false }
476491
}
477492

493+
#[inline]
494+
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
495+
where P: FnMut(&T) -> bool
496+
{
497+
RSplitMut { inner: self.split_mut(pred) }
498+
}
499+
478500
#[inline]
479501
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
480502
where P: FnMut(&T) -> bool
@@ -1735,6 +1757,123 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
17351757
#[unstable(feature = "fused", issue = "35602")]
17361758
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
17371759

1760+
/// An iterator over subslices separated by elements that match a predicate
1761+
/// function, starting from the end of the slice.
1762+
///
1763+
/// This struct is created by the [`rsplit`] method on [slices].
1764+
///
1765+
/// [`rsplit`]: ../../std/primitive.slice.html#method.rsplit
1766+
/// [slices]: ../../std/primitive.slice.html
1767+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1768+
#[derive(Clone)] // Is this correct, or does it incorrectly require `T: Clone`?
1769+
pub struct RSplit<'a, T:'a, P> where P: FnMut(&T) -> bool {
1770+
inner: Split<'a, T, P>
1771+
}
1772+
1773+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1774+
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
1775+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1776+
f.debug_struct("RSplit")
1777+
.field("v", &self.inner.v)
1778+
.field("finished", &self.inner.finished)
1779+
.finish()
1780+
}
1781+
}
1782+
1783+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1784+
impl<'a, T, P> Iterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
1785+
type Item = &'a [T];
1786+
1787+
#[inline]
1788+
fn next(&mut self) -> Option<&'a [T]> {
1789+
self.inner.next_back()
1790+
}
1791+
1792+
#[inline]
1793+
fn size_hint(&self) -> (usize, Option<usize>) {
1794+
self.inner.size_hint()
1795+
}
1796+
}
1797+
1798+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1799+
impl<'a, T, P> DoubleEndedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
1800+
#[inline]
1801+
fn next_back(&mut self) -> Option<&'a [T]> {
1802+
self.inner.next()
1803+
}
1804+
}
1805+
1806+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1807+
impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool {
1808+
#[inline]
1809+
fn finish(&mut self) -> Option<&'a [T]> {
1810+
self.inner.finish()
1811+
}
1812+
}
1813+
1814+
//#[unstable(feature = "fused", issue = "35602")]
1815+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1816+
impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {}
1817+
1818+
/// An iterator over the subslices of the vector which are separated
1819+
/// by elements that match `pred`, starting from the end of the slice.
1820+
///
1821+
/// This struct is created by the [`rsplit_mut`] method on [slices].
1822+
///
1823+
/// [`rsplit_mut`]: ../../std/primitive.slice.html#method.rsplit_mut
1824+
/// [slices]: ../../std/primitive.slice.html
1825+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1826+
pub struct RSplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
1827+
inner: SplitMut<'a, T, P>
1828+
}
1829+
1830+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1831+
impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
1832+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1833+
f.debug_struct("RSplitMut")
1834+
.field("v", &self.inner.v)
1835+
.field("finished", &self.inner.finished)
1836+
.finish()
1837+
}
1838+
}
1839+
1840+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1841+
impl<'a, T, P> SplitIter for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
1842+
#[inline]
1843+
fn finish(&mut self) -> Option<&'a mut [T]> {
1844+
self.inner.finish()
1845+
}
1846+
}
1847+
1848+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1849+
impl<'a, T, P> Iterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {
1850+
type Item = &'a mut [T];
1851+
1852+
#[inline]
1853+
fn next(&mut self) -> Option<&'a mut [T]> {
1854+
self.inner.next_back()
1855+
}
1856+
1857+
#[inline]
1858+
fn size_hint(&self) -> (usize, Option<usize>) {
1859+
self.inner.size_hint()
1860+
}
1861+
}
1862+
1863+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1864+
impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where
1865+
P: FnMut(&T) -> bool,
1866+
{
1867+
#[inline]
1868+
fn next_back(&mut self) -> Option<&'a mut [T]> {
1869+
self.inner.next()
1870+
}
1871+
}
1872+
1873+
//#[unstable(feature = "fused", issue = "35602")]
1874+
#[unstable(feature = "slice_rsplit", issue = "41020")]
1875+
impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
1876+
17381877
/// An private iterator over subslices separated by elements that
17391878
/// match a predicate function, splitting at most a fixed number of
17401879
/// times.

0 commit comments

Comments
 (0)