Skip to content

Commit d8b6109

Browse files
author
Ariel Ben-Yehuda
authored
Rollup merge of #41065 - jorendorff:slice-rsplit-41020, r=alexcrichton
[T]::rsplit() and rsplit_mut(), #41020
2 parents fa0f102 + a45fedf commit d8b6109

File tree

5 files changed

+228
-17
lines changed

5 files changed

+228
-17
lines changed

src/doc/unstable-book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@
172172
- [slice_concat_ext](slice-concat-ext.md)
173173
- [slice_get_slice](slice-get-slice.md)
174174
- [slice_patterns](slice-patterns.md)
175+
- [slice_rsplit](slice-rsplit.md)
175176
- [sort_internals](sort-internals.md)
176177
- [sort_unstable](sort-unstable.md)
177178
- [specialization](specialization.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)`.

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)]

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.

src/libcore/slice/mod.rs

+148-17
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,15 +301,21 @@ 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
299314
{
300315
SplitN {
301316
inner: GenericSplitN {
302317
iter: self.split(pred),
303-
count: n,
304-
invert: false
318+
count: n
305319
}
306320
}
307321
}
@@ -312,9 +326,8 @@ impl<T> SliceExt for [T] {
312326
{
313327
RSplitN {
314328
inner: GenericSplitN {
315-
iter: self.split(pred),
316-
count: n,
317-
invert: true
329+
iter: self.rsplit(pred),
330+
count: n
318331
}
319332
}
320333
}
@@ -475,15 +488,21 @@ impl<T> SliceExt for [T] {
475488
SplitMut { v: self, pred: pred, finished: false }
476489
}
477490

491+
#[inline]
492+
fn rsplit_mut<P>(&mut self, pred: P) -> RSplitMut<T, P>
493+
where P: FnMut(&T) -> bool
494+
{
495+
RSplitMut { inner: self.split_mut(pred) }
496+
}
497+
478498
#[inline]
479499
fn splitn_mut<P>(&mut self, n: usize, pred: P) -> SplitNMut<T, P>
480500
where P: FnMut(&T) -> bool
481501
{
482502
SplitNMut {
483503
inner: GenericSplitN {
484504
iter: self.split_mut(pred),
485-
count: n,
486-
invert: false
505+
count: n
487506
}
488507
}
489508
}
@@ -494,9 +513,8 @@ impl<T> SliceExt for [T] {
494513
{
495514
RSplitNMut {
496515
inner: GenericSplitN {
497-
iter: self.split_mut(pred),
498-
count: n,
499-
invert: true
516+
iter: self.rsplit_mut(pred),
517+
count: n
500518
}
501519
}
502520
}
@@ -1736,14 +1754,130 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where
17361754
#[unstable(feature = "fused", issue = "35602")]
17371755
impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {}
17381756

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

17491883
impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
@@ -1754,10 +1888,7 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
17541888
match self.count {
17551889
0 => None,
17561890
1 => { self.count -= 1; self.iter.finish() }
1757-
_ => {
1758-
self.count -= 1;
1759-
if self.invert {self.iter.next_back()} else {self.iter.next()}
1760-
}
1891+
_ => { self.count -= 1; self.iter.next() }
17611892
}
17621893
}
17631894

@@ -1799,7 +1930,7 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&
17991930
/// [slices]: ../../std/primitive.slice.html
18001931
#[stable(feature = "rust1", since = "1.0.0")]
18011932
pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
1802-
inner: GenericSplitN<Split<'a, T, P>>
1933+
inner: GenericSplitN<RSplit<'a, T, P>>
18031934
}
18041935

18051936
#[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
18421973
/// [slices]: ../../std/primitive.slice.html
18431974
#[stable(feature = "rust1", since = "1.0.0")]
18441975
pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
1845-
inner: GenericSplitN<SplitMut<'a, T, P>>
1976+
inner: GenericSplitN<RSplitMut<'a, T, P>>
18461977
}
18471978

18481979
#[stable(feature = "core_impl_debug", since = "1.9.0")]

0 commit comments

Comments
 (0)