Skip to content
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
#![feature(slice_ptr_get)]
#![feature(slice_ptr_len)]
#![feature(slice_range)]
#![feature(split_inclusive_variants)]
#![feature(str_internals)]
#![feature(strict_provenance)]
#![feature(trusted_len)]
Expand Down
7 changes: 7 additions & 0 deletions library/alloc/src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ pub use core::slice::{Iter, IterMut};
pub use core::slice::{RChunks, RChunksExact, RChunksExactMut, RChunksMut};
#[stable(feature = "slice_rsplit", since = "1.27.0")]
pub use core::slice::{RSplit, RSplitMut};
#[unstable(feature = "split_inclusive_variants", issue = "none")]
pub use core::slice::{
RSplitInclusive, RSplitInclusiveMut, RSplitLeftInclusive, RSplitLeftInclusiveMut,
RSplitNInclusive, RSplitNInclusiveMut, RSplitNLeftInclusive, RSplitNLeftInclusiveMut,
SplitLeftInclusive, SplitLeftInclusiveMut, SplitNInclusive, SplitNInclusiveMut,
SplitNLeftInclusive, SplitNLeftInclusiveMut,
};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::slice::{RSplitN, RSplitNMut, SplitN, SplitNMut};
#[stable(feature = "split_inclusive", since = "1.51.0")]
Expand Down
5 changes: 5 additions & 0 deletions library/alloc/src/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ pub use core::str::{MatchIndices, RMatchIndices};
pub use core::str::{Matches, RMatches};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{RSplit, Split};
#[unstable(feature = "split_inclusive_variants", issue = "none")]
pub use core::str::{
RSplitInclusive, RSplitLeftInclusive, RSplitNInclusive, RSplitNLeftInclusive, SplitEnds,
SplitInitiator, SplitLeftInclusive, SplitNInclusive, SplitNLeftInclusive,
};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::str::{RSplitN, SplitN};
#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#![feature(bench_black_box)]
#![feature(strict_provenance)]
#![feature(once_cell)]
#![feature(split_inclusive_variants)]

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
Expand Down
253 changes: 248 additions & 5 deletions library/alloc/tests/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,246 @@ fn test_splitator_mut_inclusive_reverse() {
assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
}

#[test]
fn test_splitator_left_inclusive() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1], &[2, 3], &[4, 5]];
assert_eq!(xs.split_left_inclusive(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4], &[5]];
assert_eq!(xs.split_left_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.split_left_inclusive(|_| true).collect::<Vec<&[i32]>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_left_inclusive(|x| *x == 5).collect::<Vec<&[i32]>>(), splits);
}

#[test]
fn test_splitator_left_inclusive_reverse() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[4, 5], &[2, 3], &[1]];
assert_eq!(xs.split_left_inclusive(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[1, 2, 3, 4]];
assert_eq!(xs.split_left_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.split_left_inclusive(|_| true).rev().collect::<Vec<_>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_left_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
}

#[test]
fn test_splitator_left_inclusive_mut() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1], &[2, 3], &[4, 5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4], &[5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.split_left_inclusive_mut(|_| true).collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
}

#[test]
fn test_splitator_left_inclusive_reverse_mut() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[4, 5], &[2, 3], &[1]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[1, 2, 3, 4]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.split_left_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_inclusive() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
assert_eq!(xs.rsplit_inclusive(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.rsplit_inclusive(|_| true).collect::<Vec<_>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_inclusive_reverse() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
assert_eq!(xs.rsplit_inclusive(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.rsplit_inclusive(|_| true).rev().collect::<Vec<&[i32]>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_inclusive(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits);
}

#[test]
fn test_rsplitator_mut_inclusive() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.rsplit_inclusive_mut(|_| true).collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_mut_inclusive_reverse() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.rsplit_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_left_inclusive() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[4, 5], &[2, 3], &[1]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[1, 2, 3, 4]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.rsplit_left_inclusive(|_| true).collect::<Vec<_>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 5).collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_left_inclusive_reverse() {
let xs = &[1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1], &[2, 3], &[4, 5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4], &[5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.rsplit_left_inclusive(|_| true).rev().collect::<Vec<&[i32]>>(), splits);

let xs: &[i32] = &[];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_left_inclusive(|x| *x == 5).rev().collect::<Vec<&[i32]>>(), splits);
}

#[test]
fn test_rsplitator_left_inclusive_mut() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[4, 5], &[2, 3], &[1]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x % 2 == 0).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 1).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[1, 2, 3, 4]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 10).collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]];
assert_eq!(xs.rsplit_left_inclusive_mut(|_| true).collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 5).collect::<Vec<_>>(), splits);
}

#[test]
fn test_rsplitator_left_inclusive_reverse_mut() {
let xs = &mut [1, 2, 3, 4, 5];

let splits: &[&[_]] = &[&[1], &[2, 3], &[4, 5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x % 2 == 0).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 1).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4], &[5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|x| *x == 10).rev().collect::<Vec<_>>(), splits);
let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]];
assert_eq!(xs.rsplit_left_inclusive_mut(|_| true).rev().collect::<Vec<_>>(), splits);

let xs: &mut [i32] = &mut [];
let splits: &[&[i32]] = &[];
assert_eq!(xs.split_left_inclusive_mut(|x| *x == 5).rev().collect::<Vec<_>>(), splits);
}

#[test]
fn test_splitnator() {
let xs = &[1, 2, 3, 4, 5];
Expand Down Expand Up @@ -996,7 +1236,7 @@ fn test_rsplitnator() {

#[test]
fn test_split_iterators_size_hint() {
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq, Eq)]
enum Bounds {
Lower,
Upper,
Expand Down Expand Up @@ -1027,8 +1267,9 @@ fn test_split_iterators_size_hint() {

// p: predicate, b: bound selection
for (p, b) in [
// with a predicate always returning false, the split*-iterators
// become maximally short, so the size_hint lower bounds are tight
// with a predicate always returning false, the non-inclusive
// split*-iterators become maximally short, so the size_hint
// lower bounds are tight
((|_| false) as fn(&_) -> _, Bounds::Lower),
// with a predicate always returning true, the split*-iterators
// become maximally long, so the size_hint upper bounds are tight
Expand All @@ -1039,8 +1280,10 @@ fn test_split_iterators_size_hint() {

a(v.split(p), b, "split");
a(v.split_mut(p), b, "split_mut");
a(v.split_inclusive(p), b, "split_inclusive");
a(v.split_inclusive_mut(p), b, "split_inclusive_mut");
if b == Bounds::Upper {
a(v.split_inclusive(p), b, "split_inclusive");
a(v.split_inclusive_mut(p), b, "split_inclusive_mut");
}
a(v.rsplit(p), b, "rsplit");
a(v.rsplit_mut(p), b, "rsplit_mut");

Expand Down
57 changes: 57 additions & 0 deletions library/alloc/tests/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1438,6 +1438,63 @@ fn test_split_char_iterator_inclusive_rev() {
assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
}

#[test]
fn test_split_char_iterator_left_inclusive() {
let split: Vec<&str> = "\n\n\n\n".split_left_inclusive('\n').collect();
assert_eq!(split, ["\n", "\n", "\n", "\n"]);

let split: Vec<&str> = "".split_left_inclusive('\n').collect();
let rhs: [&str; 0] = [];
assert_eq!(split, rhs);

let data = "\nMäry häd ä little lämb\nLittle lämb\n";

let split: Vec<&str> = data.split_left_inclusive('\n').collect();
assert_eq!(split, ["\nMäry häd ä little lämb", "\nLittle lämb", "\n"]);

let uppercase_separated = "SheePSharKTurtlECaT";
let mut first_char = true;
let split: Vec<&str> = uppercase_separated
.split_left_inclusive(|c: char| {
let split = !first_char && c.is_uppercase();
first_char = split;
split
})
.collect();
assert_eq!(split, ["Shee", "PShar", "KTurtl", "ECa", "T"]);
}

#[test]
fn test_split_char_iterator_left_inclusive_rev() {
let split: Vec<&str> = "\n\n\n\n".split_left_inclusive('\n').rev().collect();
assert_eq!(split, ["\n", "\n", "\n", "\n"]);

let split: Vec<&str> = "".split_left_inclusive('\n').rev().collect();
let rhs: [&str; 0] = [];
assert_eq!(split, rhs);

let data = "\nMäry häd ä little lämb\nLittle lämb\n";

let split: Vec<&str> = data.split_left_inclusive('\n').rev().collect();
assert_eq!(split, ["\n", "\nLittle lämb", "\nMäry häd ä little lämb"]);

// Note that the predicate is stateful and thus dependent
// on the iteration order.
// (A different predicate is needed for reverse iterator vs normal iterator.)
// Not sure if anything can be done though.
let uppercase_separated = "SheePSharKTurtlECaT";
let mut term_char = true;
let split: Vec<&str> = uppercase_separated
.split_left_inclusive(|c: char| {
let split = term_char && c.is_uppercase();
term_char = c.is_uppercase();
split
})
.rev()
.collect();
assert_eq!(split, ["T", "ECa", "KTurtl", "PShar", "Shee",]);
}

#[test]
fn test_rsplit() {
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
Expand Down
Loading