Skip to content

Rollup of 6 pull requests #91776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Dec 11, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add rsplit_array variants to slices and arrays
  • Loading branch information
Jethro Beekman committed Dec 10, 2021
commit 203cf2d3668e38dfa3088763789d2541c5943ae7
78 changes: 78 additions & 0 deletions library/core/src/array/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
78 changes: 78 additions & 0 deletions library/core/src/slice/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down
33 changes: 33 additions & 0 deletions library/core/tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions library/core/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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)*);
Expand Down