diff options
| author | Jason Orendorff <jason.orendorff@gmail.com> | 2017-04-03 15:25:30 -0500 |
|---|---|---|
| committer | Jason Orendorff <jason.orendorff@gmail.com> | 2017-04-04 13:40:26 -0500 |
| commit | 2e3f0d845113995c26a9d59dd69146975a692516 (patch) | |
| tree | d1566ac7788b5de85896bd676c6dcbafc5572ecb | |
| parent | 5309a3e31d88def1f3ea966162ed4f81f161d500 (diff) | |
| download | rust-2e3f0d845113995c26a9d59dd69146975a692516.tar.gz rust-2e3f0d845113995c26a9d59dd69146975a692516.zip | |
add [T]::rsplit() and rsplit_mut() #41020
| -rw-r--r-- | src/doc/unstable-book/src/SUMMARY.md | 1 | ||||
| -rw-r--r-- | src/doc/unstable-book/src/slice-rsplit.md | 10 | ||||
| -rw-r--r-- | src/libcollections/lib.rs | 1 | ||||
| -rw-r--r-- | src/libcollections/slice.rs | 68 | ||||
| -rw-r--r-- | src/libcore/slice/mod.rs | 139 |
5 files changed, 219 insertions, 0 deletions
diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 292f5a1ec81..52f33244695 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -171,6 +171,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) diff --git a/src/doc/unstable-book/src/slice-rsplit.md b/src/doc/unstable-book/src/slice-rsplit.md new file mode 100644 index 00000000000..8c2954f7294 --- /dev/null +++ b/src/doc/unstable-book/src/slice-rsplit.md @@ -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)`. diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 00448b6abb2..ff020f53e0e 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -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)] diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 6f8843c2374..6cff315a6cc 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -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")] @@ -780,6 +782,72 @@ impl<T> [T] { } /// 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. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 45667bb4299..1e0037755c1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -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; @@ -294,6 +302,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 { @@ -476,6 +491,13 @@ impl<T> SliceExt for [T] { } #[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 { @@ -1735,6 +1757,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. |
