about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJethro Beekman <jethro@jbeekman.nl>2021-12-04 10:32:09 +0100
committerJethro Beekman <jethro@jbeekman.nl>2021-12-10 21:34:19 +0100
commit203cf2d3668e38dfa3088763789d2541c5943ae7 (patch)
tree23fc10c2b1f4e5768aa38d9e26a92d186f28282b
parent0b42deaccc2cbe17a68067aa5fdb76104369e1fd (diff)
downloadrust-203cf2d3668e38dfa3088763789d2541c5943ae7.tar.gz
rust-203cf2d3668e38dfa3088763789d2541c5943ae7.zip
Add rsplit_array variants to slices and arrays
-rw-r--r--library/core/src/array/mod.rs78
-rw-r--r--library/core/src/slice/mod.rs78
-rw-r--r--library/core/tests/array.rs33
-rw-r--r--library/core/tests/slice.rs33
4 files changed, 222 insertions, 0 deletions
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index 23fd1453e54..5e295ffbff7 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -645,6 +645,84 @@ impl<T, const N: usize> [T; N] {
     pub fn split_array_mut<const M: usize>(&mut self) -> (&mut [T; M], &mut [T]) {
         (&mut self[..]).split_array_mut::<M>()
     }
+
+    /// Divides one array reference into two at an index from the end.
+    ///
+    /// The first will contain all indices from `[0, N - M)` (excluding
+    /// the index `N - M` itself) and the second will contain all
+    /// indices from `[N - M, N)` (excluding the index `N` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `M > N`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_array)]
+    ///
+    /// let v = [1, 2, 3, 4, 5, 6];
+    ///
+    /// {
+    ///    let (left, right) = v.rsplit_array_ref::<0>();
+    ///    assert_eq!(left, &[1, 2, 3, 4, 5, 6]);
+    ///    assert_eq!(right, &[]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.rsplit_array_ref::<2>();
+    ///     assert_eq!(left, &[1, 2, 3, 4]);
+    ///     assert_eq!(right, &[5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.rsplit_array_ref::<6>();
+    ///     assert_eq!(left, &[]);
+    ///     assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
+    /// }
+    /// ```
+    #[unstable(
+        feature = "split_array",
+        reason = "return type should have array as 2nd element",
+        issue = "90091"
+    )]
+    #[inline]
+    pub fn rsplit_array_ref<const M: usize>(&self) -> (&[T], &[T; M]) {
+        (&self[..]).rsplit_array_ref::<M>()
+    }
+
+    /// Divides one mutable array reference into two at an index from the end.
+    ///
+    /// The first will contain all indices from `[0, N - M)` (excluding
+    /// the index `N - M` itself) and the second will contain all
+    /// indices from `[N - M, N)` (excluding the index `N` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `M > N`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_array)]
+    ///
+    /// let mut v = [1, 0, 3, 0, 5, 6];
+    /// let (left, right) = v.rsplit_array_mut::<4>();
+    /// assert_eq!(left, &mut [1, 0]);
+    /// assert_eq!(right, &mut [3, 0, 5, 6][..]);
+    /// left[1] = 2;
+    /// right[1] = 4;
+    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+    /// ```
+    #[unstable(
+        feature = "split_array",
+        reason = "return type should have array as 2nd element",
+        issue = "90091"
+    )]
+    #[inline]
+    pub fn rsplit_array_mut<const M: usize>(&mut self) -> (&mut [T], &mut [T; M]) {
+        (&mut self[..]).rsplit_array_mut::<M>()
+    }
 }
 
 /// Pulls `N` items from `iter` and returns them as an array. If the iterator
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index a3f59d30759..f9ea99ea8aa 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1705,6 +1705,84 @@ impl<T> [T] {
         unsafe { (&mut *(a.as_mut_ptr() as *mut [T; N]), b) }
     }
 
+    /// Divides one slice into an array and a remainder slice at an index from
+    /// the end.
+    ///
+    /// The slice will contain all indices from `[0, len - N)` (excluding
+    /// the index `len - N` itself) and the array will contain all
+    /// indices from `[len - N, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_array)]
+    ///
+    /// let v = &[1, 2, 3, 4, 5, 6][..];
+    ///
+    /// {
+    ///    let (left, right) = v.rsplit_array_ref::<0>();
+    ///    assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+    ///    assert_eq!(right, &[]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.rsplit_array_ref::<2>();
+    ///     assert_eq!(left, [1, 2, 3, 4]);
+    ///     assert_eq!(right, &[5, 6]);
+    /// }
+    ///
+    /// {
+    ///     let (left, right) = v.rsplit_array_ref::<6>();
+    ///     assert_eq!(left, []);
+    ///     assert_eq!(right, &[1, 2, 3, 4, 5, 6]);
+    /// }
+    /// ```
+    #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
+    #[inline]
+    pub fn rsplit_array_ref<const N: usize>(&self) -> (&[T], &[T; N]) {
+        assert!(N <= self.len());
+        let (a, b) = self.split_at(self.len() - N);
+        // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at)
+        unsafe { (a, &*(b.as_ptr() as *const [T; N])) }
+    }
+
+    /// Divides one mutable slice into an array and a remainder slice at an
+    /// index from the end.
+    ///
+    /// The slice will contain all indices from `[0, len - N)` (excluding
+    /// the index `N` itself) and the array will contain all
+    /// indices from `[len - N, len)` (excluding the index `len` itself).
+    ///
+    /// # Panics
+    ///
+    /// Panics if `N > len`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(split_array)]
+    ///
+    /// let mut v = &mut [1, 0, 3, 0, 5, 6][..];
+    /// let (left, right) = v.rsplit_array_mut::<4>();
+    /// assert_eq!(left, [1, 0]);
+    /// assert_eq!(right, &mut [3, 0, 5, 6]);
+    /// left[1] = 2;
+    /// right[1] = 4;
+    /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+    /// ```
+    #[unstable(feature = "split_array", reason = "new API", issue = "90091")]
+    #[inline]
+    pub fn rsplit_array_mut<const N: usize>(&mut self) -> (&mut [T], &mut [T; N]) {
+        assert!(N <= self.len());
+        let (a, b) = self.split_at_mut(self.len() - N);
+        // SAFETY: b points to [T; N]? Yes it's [T] of length N (checked by split_at_mut)
+        unsafe { (a, &mut *(b.as_mut_ptr() as *mut [T; N])) }
+    }
+
     /// Returns an iterator over subslices separated by elements that match
     /// `pred`. The matched element is not contained in the subslices.
     ///
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index d212a3a3a05..8524a0bf8dd 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -459,6 +459,23 @@ fn array_split_array_mut() {
     }
 }
 
+#[test]
+fn array_rsplit_array_mut() {
+    let mut v = [1, 2, 3, 4, 5, 6];
+
+    {
+        let (left, right) = v.rsplit_array_mut::<0>();
+        assert_eq!(left, &mut [1, 2, 3, 4, 5, 6]);
+        assert_eq!(right, &mut []);
+    }
+
+    {
+        let (left, right) = v.rsplit_array_mut::<6>();
+        assert_eq!(left, &mut []);
+        assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
+    }
+}
+
 #[should_panic]
 #[test]
 fn array_split_array_ref_out_of_bounds() {
@@ -475,6 +492,22 @@ fn array_split_array_mut_out_of_bounds() {
     v.split_array_mut::<7>();
 }
 
+#[should_panic]
+#[test]
+fn array_rsplit_array_ref_out_of_bounds() {
+    let v = [1, 2, 3, 4, 5, 6];
+
+    v.rsplit_array_ref::<7>();
+}
+
+#[should_panic]
+#[test]
+fn array_rsplit_array_mut_out_of_bounds() {
+    let mut v = [1, 2, 3, 4, 5, 6];
+
+    v.rsplit_array_mut::<7>();
+}
+
 #[test]
 fn array_intoiter_advance_by() {
     use std::cell::Cell;
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 281df8a1326..20e2d8d47c0 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -2219,6 +2219,23 @@ fn slice_split_array_mut() {
     }
 }
 
+#[test]
+fn slice_rsplit_array_mut() {
+    let v = &mut [1, 2, 3, 4, 5, 6][..];
+
+    {
+        let (left, right) = v.rsplit_array_mut::<0>();
+        assert_eq!(left, [1, 2, 3, 4, 5, 6]);
+        assert_eq!(right, &mut []);
+    }
+
+    {
+        let (left, right) = v.rsplit_array_mut::<6>();
+        assert_eq!(left, []);
+        assert_eq!(right, &mut [1, 2, 3, 4, 5, 6]);
+    }
+}
+
 #[should_panic]
 #[test]
 fn slice_split_array_ref_out_of_bounds() {
@@ -2235,6 +2252,22 @@ fn slice_split_array_mut_out_of_bounds() {
     v.split_array_mut::<7>();
 }
 
+#[should_panic]
+#[test]
+fn slice_rsplit_array_ref_out_of_bounds() {
+    let v = &[1, 2, 3, 4, 5, 6][..];
+
+    v.rsplit_array_ref::<7>();
+}
+
+#[should_panic]
+#[test]
+fn slice_rsplit_array_mut_out_of_bounds() {
+    let v = &mut [1, 2, 3, 4, 5, 6][..];
+
+    v.rsplit_array_mut::<7>();
+}
+
 macro_rules! take_tests {
     (slice: &[], $($tts:tt)*) => {
         take_tests!(ty: &[()], slice: &[], $($tts)*);