Skip to content

Commit 66045fe

Browse files
Merge ef569a2 into f43e549
2 parents f43e549 + ef569a2 commit 66045fe

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

library/core/src/slice/iter.rs

+138
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,144 @@ forward_iterator! { RSplitN: T, &'a [T] }
13081308
forward_iterator! { SplitNMut: T, &'a mut [T] }
13091309
forward_iterator! { RSplitNMut: T, &'a mut [T] }
13101310

1311+
/// An iterator over subslices separated by a given slice
1312+
///
1313+
/// This struct is created by the [`split_pattern`] method on [slices].
1314+
///
1315+
/// # Example
1316+
///
1317+
/// ```
1318+
/// #![feature(split_pattern)]
1319+
/// let slice = [10, 10, 40, 33, 30, 10, 40, 20];
1320+
/// let pat = [10, 40];
1321+
/// let mut iter = slice.split_pattern(&pat);
1322+
/// assert_eq!(iter.next(), Some(&[10][..]));
1323+
/// assert_eq!(iter.next(), Some(&[33, 30][..]));
1324+
/// assert_eq!(iter.next(), Some(&[20][..]));
1325+
/// assert_eq!(iter.next(), None);
1326+
/// ```
1327+
///
1328+
/// [`split_pattern`]: slice::split_pattern
1329+
/// [slices]: slice
1330+
#[unstable(feature = "split_pattern", issue = "49036")]
1331+
#[must_use = "iterators are lazy and do nothing unless consumed"]
1332+
pub struct SplitPattern<'a, 'b, T>
1333+
where
1334+
T: cmp::PartialEq,
1335+
{
1336+
v: &'a [T],
1337+
pattern: &'b [T],
1338+
finished: bool,
1339+
}
1340+
1341+
#[unstable(feature = "split_pattern", issue = "49036")]
1342+
impl<'a, 'b, T: cmp::PartialEq> SplitPattern<'a, 'b, T> {
1343+
#![allow(unused)]
1344+
#[inline]
1345+
pub(super) fn new(slice: &'a [T], pattern: &'b [T]) -> Self {
1346+
Self { v: slice, pattern, finished: false }
1347+
}
1348+
}
1349+
1350+
#[unstable(feature = "split_pattern", issue = "49036")]
1351+
impl<T: fmt::Debug> fmt::Debug for SplitPattern<'_, '_, T>
1352+
where
1353+
T: cmp::PartialEq,
1354+
{
1355+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1356+
f.debug_struct("SplitPattern")
1357+
.field("v", &self.v)
1358+
.field("pattern", &self.pattern)
1359+
.field("finished", &self.finished)
1360+
.finish()
1361+
}
1362+
}
1363+
1364+
#[unstable(feature = "split_pattern", issue = "49036")]
1365+
impl<T> Clone for SplitPattern<'_, '_, T>
1366+
where
1367+
T: cmp::PartialEq,
1368+
{
1369+
fn clone(&self) -> Self {
1370+
SplitPattern { v: self.v, pattern: self.pattern, finished: self.finished }
1371+
}
1372+
}
1373+
1374+
#[unstable(feature = "split_pattern", issue = "49036")]
1375+
impl<'a, 'b, T> Iterator for SplitPattern<'a, 'b, T>
1376+
where
1377+
T: cmp::PartialEq,
1378+
{
1379+
type Item = &'a [T];
1380+
1381+
#[inline]
1382+
fn next(&mut self) -> Option<&'a [T]> {
1383+
if self.finished {
1384+
return None;
1385+
}
1386+
1387+
for i in 0..self.v.len() {
1388+
if self.v[i..].starts_with(&self.pattern) {
1389+
let (left, right) = (&self.v[0..i], &self.v[i + self.pattern.len()..]);
1390+
let ret = Some(left);
1391+
self.v = right;
1392+
return ret;
1393+
}
1394+
}
1395+
self.finish()
1396+
}
1397+
1398+
#[inline]
1399+
fn size_hint(&self) -> (usize, Option<usize>) {
1400+
if self.finished {
1401+
(0, Some(0))
1402+
} else {
1403+
// If the predicate doesn't match anything, we yield one slice.
1404+
// If it matches every element, we yield `len() + 1` empty slices.
1405+
(1, Some(self.v.len() + 1))
1406+
}
1407+
}
1408+
}
1409+
1410+
#[unstable(feature = "split_pattern", issue = "49036")]
1411+
impl<'a, 'b, T> DoubleEndedIterator for SplitPattern<'a, 'b, T>
1412+
where
1413+
T: cmp::PartialEq,
1414+
{
1415+
#[inline]
1416+
fn next_back(&mut self) -> Option<&'a [T]> {
1417+
if self.finished {
1418+
return None;
1419+
}
1420+
1421+
for i in (0..self.v.len()).rev() {
1422+
if self.v[..i].ends_with(&self.pattern) {
1423+
let (left, right) = (&self.v[i..], &self.v[..i - self.pattern.len()]);
1424+
let ret = Some(left);
1425+
self.v = right;
1426+
return ret;
1427+
}
1428+
}
1429+
self.finish()
1430+
}
1431+
}
1432+
1433+
#[unstable(feature = "split_pattern", issue = "49036")]
1434+
impl<'a, 'b, T> SplitIter for SplitPattern<'a, 'b, T>
1435+
where
1436+
T: cmp::PartialEq,
1437+
{
1438+
#[inline]
1439+
fn finish(&mut self) -> Option<&'a [T]> {
1440+
if self.finished {
1441+
None
1442+
} else {
1443+
self.finished = true;
1444+
Some(self.v)
1445+
}
1446+
}
1447+
}
1448+
13111449
/// An iterator over overlapping subslices of length `size`.
13121450
///
13131451
/// This struct is created by the [`windows`] method on [slices].

library/core/src/slice/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ pub use index::SliceIndex;
5151
pub use index::{range, try_range};
5252
#[unstable(feature = "array_windows", issue = "75027")]
5353
pub use iter::ArrayWindows;
54+
#[unstable(feature = "split_pattern", issue = "49036")]
55+
pub use iter::SplitPattern;
5456
#[unstable(feature = "array_chunks", issue = "74985")]
5557
pub use iter::{ArrayChunks, ArrayChunksMut};
5658
#[stable(feature = "slice_group_by", since = "1.77.0")]
@@ -4089,6 +4091,16 @@ impl<T> [T] {
40894091
unsafe { self.align_to() }
40904092
}
40914093

4094+
/// Splits a slice by a pattern
4095+
#[unstable(feature = "split_pattern", issue = "49036")]
4096+
#[inline]
4097+
pub fn split_pattern<'a, 'b>(&'a self, pattern: &'b [T]) -> SplitPattern<'a, 'b, T>
4098+
where
4099+
T: PartialEq,
4100+
{
4101+
SplitPattern::new(&self, pattern)
4102+
}
4103+
40924104
/// Splits a mutable slice into a mutable prefix, a middle of aligned SIMD types,
40934105
/// and a mutable suffix.
40944106
///

0 commit comments

Comments
 (0)