From 50246b0587f4d737ba7cd569c1be25adb98dfe62 Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Mon, 19 Jun 2023 17:50:14 -0700 Subject: [PATCH] Implement slice::split_once and slice::rsplit_once Feature gate is slice_split_once and tracking issue is #112811. --- library/core/src/slice/mod.rs | 56 +++++++++++++++++++++++++++++++++++ library/core/tests/lib.rs | 1 + library/core/tests/slice.rs | 20 +++++++++++++ 3 files changed, 77 insertions(+) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 5d6e7dcfcee..d9dcf14ba02 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2478,6 +2478,62 @@ pub fn rsplitn_mut(&mut self, n: usize, pred: F) -> RSplitNMut<'_, T, F> RSplitNMut::new(self.rsplit_mut(pred), n) } + /// Splits the slice on the first element that matches the specified + /// predicate. + /// + /// If any matching elements are resent in the slice, returns the prefix + /// before the match and suffix after. The matching element itself is not + /// included. If no elements match, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_split_once)] + /// let s = [1, 2, 3, 2, 4]; + /// assert_eq!(s.split_once(|&x| x == 2), Some(( + /// &[1][..], + /// &[3, 2, 4][..] + /// ))); + /// assert_eq!(s.split_once(|&x| x == 0), None); + /// ``` + #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")] + #[inline] + pub fn split_once(&self, pred: F) -> Option<(&[T], &[T])> + where + F: FnMut(&T) -> bool, + { + let index = self.iter().position(pred)?; + Some((&self[..index], &self[index + 1..])) + } + + /// Splits the slice on the last element that matches the specified + /// predicate. + /// + /// If any matching elements are resent in the slice, returns the prefix + /// before the match and suffix after. The matching element itself is not + /// included. If no elements match, returns `None`. + /// + /// # Examples + /// + /// ``` + /// #![feature(slice_split_once)] + /// let s = [1, 2, 3, 2, 4]; + /// assert_eq!(s.rsplit_once(|&x| x == 2), Some(( + /// &[1, 2, 3][..], + /// &[4][..] + /// ))); + /// assert_eq!(s.rsplit_once(|&x| x == 0), None); + /// ``` + #[unstable(feature = "slice_split_once", reason = "newly added", issue = "112811")] + #[inline] + pub fn rsplit_once(&self, pred: F) -> Option<(&[T], &[T])> + where + F: FnMut(&T) -> bool, + { + let index = self.iter().rposition(pred)?; + Some((&self[..index], &self[index + 1..])) + } + /// Returns `true` if the slice contains an element with the given value. /// /// This operation is *O*(*n*). diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index 3e6d31fcd2f..99c73a85b26 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -47,6 +47,7 @@ #![feature(sort_internals)] #![feature(slice_take)] #![feature(slice_from_ptr_range)] +#![feature(slice_split_once)] #![feature(split_as_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 88f54591bb4..5b0e825dc00 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -2448,6 +2448,26 @@ fn slice_rsplit_array_mut_out_of_bounds() { let _ = v.rsplit_array_mut::<7>(); } +#[test] +fn slice_split_once() { + let v = &[1, 2, 3, 2, 4][..]; + + assert_eq!(v.split_once(|&x| x == 2), Some((&[1][..], &[3, 2, 4][..]))); + assert_eq!(v.split_once(|&x| x == 1), Some((&[][..], &[2, 3, 2, 4][..]))); + assert_eq!(v.split_once(|&x| x == 4), Some((&[1, 2, 3, 2][..], &[][..]))); + assert_eq!(v.split_once(|&x| x == 0), None); +} + +#[test] +fn slice_rsplit_once() { + let v = &[1, 2, 3, 2, 4][..]; + + assert_eq!(v.rsplit_once(|&x| x == 2), Some((&[1, 2, 3][..], &[4][..]))); + assert_eq!(v.rsplit_once(|&x| x == 1), Some((&[][..], &[2, 3, 2, 4][..]))); + assert_eq!(v.rsplit_once(|&x| x == 4), Some((&[1, 2, 3, 2][..], &[][..]))); + assert_eq!(v.rsplit_once(|&x| x == 0), None); +} + macro_rules! take_tests { (slice: &[], $($tts:tt)*) => { take_tests!(ty: &[()], slice: &[], $($tts)*);