Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d118cd0

Browse files
committedApr 19, 2019
Added needle methods for slices
1 parent a10c43a commit d118cd0

File tree

4 files changed

+403
-1
lines changed

4 files changed

+403
-1
lines changed
 

‎src/liballoc/slice.rs

+35
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ use core::cmp::Ordering::{self, Less};
9292
use core::mem::{self, size_of};
9393
use core::ptr;
9494
use core::{u8, u16, u32};
95+
use core::needle::{ext, Needle, Searcher, Consumer};
9596

9697
use crate::borrow::ToOwned;
9798
use crate::boxed::Box;
@@ -485,6 +486,40 @@ impl<T> [T] {
485486
}
486487
buf
487488
}
489+
490+
/// Replaces all matches of a predicate with another slice.
491+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
492+
#[inline]
493+
#[must_use = "this returns the replaced slice as a new allocation, \
494+
without modifying the original"]
495+
pub fn replace<'s: 'a, 'a, F>(&'s self, from: F, to: &'a [T]) -> Vec<T>
496+
where
497+
T: Clone,
498+
F: Needle<&'a [T]>,
499+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
500+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
501+
{
502+
let mut result = Vec::with_capacity(self.len());
503+
ext::replace_with(self, from, |_| to, |s| result.extend_from_slice(s));
504+
result
505+
}
506+
507+
/// Replaces first N matches of a predicate with another slice.
508+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
509+
#[inline]
510+
#[must_use = "this returns the replaced slice as a new allocation, \
511+
without modifying the original"]
512+
pub fn replacen<'s: 'a, 'a, F>(&'s self, from: F, to: &'a [T], count: usize) -> Vec<T>
513+
where
514+
T: Clone,
515+
F: Needle<&'a [T]>,
516+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
517+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
518+
{
519+
let mut result = Vec::with_capacity(self.len());
520+
ext::replacen_with(self, from, |_| to, count, |s| result.extend_from_slice(s));
521+
result
522+
}
488523
}
489524

490525
#[lang = "slice_u8_alloc"]

‎src/liballoc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#![feature(unboxed_closures)]
1111
#![feature(vecdeque_rotate)]
1212
#![feature(mut_str_needle_methods)]
13+
#![feature(slice_needle_methods)]
1314

1415
use std::hash::{Hash, Hasher};
1516
use std::collections::hash_map::DefaultHasher;

‎src/liballoc/tests/slice.rs

+58
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::panic;
55
use std::rc::Rc;
66
use std::sync::atomic::{Ordering::Relaxed, AtomicUsize};
77
use std::thread;
8+
use std::f64::NAN;
89

910
use rand::{Rng, RngCore, thread_rng};
1011
use rand::seq::SliceRandom;
@@ -1655,3 +1656,60 @@ fn repeat_generic_slice() {
16551656
vec![1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
16561657
);
16571658
}
1659+
1660+
#[test]
1661+
fn test_match_indices_simple() {
1662+
let haystack = &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 2.0, 3.0, 2.0, 4.0, 8.0][..];
1663+
let needle = &[2.0, 3.0][..];
1664+
1665+
assert_eq!(haystack.match_indices(needle).collect::<Vec<_>>(), vec![
1666+
(1, needle),
1667+
(8, needle),
1668+
]);
1669+
}
1670+
1671+
#[test]
1672+
fn test_match_indices_nan_haystack() {
1673+
let haystack = &[1.0, 2.0, NAN, 1.0, 2.0, NAN, 1.0, NAN, NAN, NAN, 2.0, 1.0, 2.0][..];
1674+
let needle = &[1.0, 2.0][..];
1675+
1676+
assert_eq!(haystack.match_indices(needle).collect::<Vec<_>>(), vec![
1677+
(0, needle),
1678+
(3, needle),
1679+
(11, needle),
1680+
]);
1681+
}
1682+
1683+
#[test]
1684+
fn test_match_indices_nan_needle() {
1685+
let haystack = &[1.0, 2.0, NAN, 1.0, 2.0, NAN, 1.0, NAN, NAN, NAN, 2.0, 1.0, 2.0][..];
1686+
let needle = &[1.0, 2.0][..];
1687+
1688+
assert_eq!(haystack.match_indices(needle).collect::<Vec<_>>(), vec![
1689+
(0, needle),
1690+
(3, needle),
1691+
(11, needle),
1692+
]);
1693+
}
1694+
1695+
#[test]
1696+
fn test_match_indices_negative_zero() {
1697+
let haystack = &[1.0, 2.0, NAN, 1.0, 2.0, NAN, 1.0, NAN, NAN, NAN, 2.0, 1.0, 2.0][..];
1698+
let needle = &[1.0, 2.0][..];
1699+
1700+
assert_eq!(haystack.match_indices(needle).collect::<Vec<_>>(), vec![
1701+
(0, needle),
1702+
(3, needle),
1703+
(11, needle),
1704+
]);
1705+
}
1706+
1707+
#[test]
1708+
fn test_replace() {
1709+
let haystack = &b" empowering everyone to build reliable and efficient software."[..];
1710+
1711+
assert_eq!(
1712+
haystack.replace(&b" e"[..], b" **E**"),
1713+
b" **E**mpowering **E**veryone to build reliable and **E**fficient software.".to_vec()
1714+
);
1715+
}

‎src/libcore/slice/mod.rs

+309-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ use crate::ptr;
3535
use crate::mem;
3636
use crate::marker::{Copy, Send, Sync, Sized, self};
3737
use crate::iter_private::TrustedRandomAccess;
38-
use crate::needle::{ext, Needle, Searcher, ReverseSearcher, Consumer, ReverseConsumer};
38+
use crate::needle::{
39+
ext, Needle, Searcher, ReverseSearcher, Consumer, ReverseConsumer, DoubleEndedConsumer,
40+
};
3941

4042
#[unstable(feature = "slice_internals", issue = "0",
4143
reason = "exposed from core to be reused in std; use the memchr crate")]
@@ -1286,6 +1288,312 @@ impl<T> [T] {
12861288
x.slice_contains(self)
12871289
}
12881290

1291+
/// Returns `true` if the given predicate matches a sub-slice of this slice.
1292+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1293+
#[inline]
1294+
pub fn contains_match<'a, F>(&'a self, pred: F) -> bool
1295+
where
1296+
F: Needle<&'a [T]>,
1297+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1298+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1299+
{
1300+
ext::contains(self, pred)
1301+
}
1302+
1303+
/// Returns the index of the first sub-slice of this slice that matches the
1304+
/// predicate.
1305+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1306+
#[inline]
1307+
pub fn find<'a, F>(&'a self, pred: F) -> Option<usize>
1308+
where
1309+
F: Needle<&'a [T]>,
1310+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1311+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1312+
{
1313+
ext::find(self, pred)
1314+
}
1315+
1316+
/// Returns the index of the last sub-slice of this slice that matches the
1317+
/// predicate.
1318+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1319+
#[inline]
1320+
pub fn rfind<'a, F>(&'a self, pred: F) -> Option<usize>
1321+
where
1322+
F: Needle<&'a [T]>,
1323+
F::Searcher: ReverseSearcher<[T]>,
1324+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1325+
{
1326+
ext::rfind(self, pred)
1327+
}
1328+
1329+
/// Returns the index range of the first sub-slice of this slice that
1330+
/// matches the predicate.
1331+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1332+
#[inline]
1333+
pub fn find_range<'a, F>(&'a self, pred: F) -> Option<ops::Range<usize>>
1334+
where
1335+
F: Needle<&'a [T]>,
1336+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1337+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1338+
{
1339+
ext::find_range(self, pred)
1340+
}
1341+
1342+
/// Returns the index range of the last sub-slice of this slice that matches
1343+
/// the predicate.
1344+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1345+
#[inline]
1346+
pub fn rfind_range<'a, F>(&'a self, pred: F) -> Option<ops::Range<usize>>
1347+
where
1348+
F: Needle<&'a [T]>,
1349+
F::Searcher: ReverseSearcher<[T]>,
1350+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1351+
{
1352+
ext::rfind_range(self, pred)
1353+
}
1354+
1355+
/// An iterator over the disjoint matches of a predicate within the given
1356+
/// slice.
1357+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1358+
#[inline]
1359+
pub fn matches<'a, F>(&'a self, pred: F) -> ext::Matches<&'a [T], F::Searcher>
1360+
where
1361+
F: Needle<&'a [T]>,
1362+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1363+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1364+
{
1365+
ext::matches(self, pred)
1366+
}
1367+
1368+
/// An iterator over the disjoint matches of a predicate within the given
1369+
/// mutable slice.
1370+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1371+
#[inline]
1372+
pub fn matches_mut<'a, F>(&'a mut self, pred: F) -> ext::Matches<&'a mut [T], F::Searcher>
1373+
where
1374+
F: Needle<&'a mut [T]>,
1375+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1376+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1377+
{
1378+
ext::matches(self, pred)
1379+
}
1380+
1381+
/// An iterator over the disjoint matches of a predicate within the given
1382+
/// slice, yielded in reverse order.
1383+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1384+
#[inline]
1385+
pub fn rmatches<'a, F>(&'a self, pred: F) -> ext::RMatches<&'a [T], F::Searcher>
1386+
where
1387+
F: Needle<&'a [T]>,
1388+
F::Searcher: ReverseSearcher<[T]>,
1389+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1390+
{
1391+
ext::rmatches(self, pred)
1392+
}
1393+
1394+
/// An iterator over the disjoint matches of a predicate within the given
1395+
/// mutable slice, yielded in reverse order.
1396+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1397+
#[inline]
1398+
pub fn rmatches_mut<'a, F>(&'a mut self, pred: F) -> ext::RMatches<&'a mut [T], F::Searcher>
1399+
where
1400+
F: Needle<&'a mut [T]>,
1401+
F::Searcher: ReverseSearcher<[T]>,
1402+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1403+
{
1404+
ext::rmatches(self, pred)
1405+
}
1406+
1407+
/// An iterator over the disjoint matches of a predicate within the given
1408+
/// slice as well as the index that the match starts at.
1409+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1410+
#[inline]
1411+
pub fn match_indices<'a, F>(&'a self, pred: F)
1412+
-> ext::MatchIndices<&'a [T], F::Searcher>
1413+
where
1414+
F: Needle<&'a [T]>,
1415+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1416+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1417+
{
1418+
ext::match_indices(self, pred)
1419+
}
1420+
1421+
/// An iterator over the disjoint match_indices of a predicate within the given
1422+
/// mutable slice as well as the range that the match covers.
1423+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1424+
#[inline]
1425+
pub fn match_indices_mut<'a, F>(&'a mut self, pred: F)
1426+
-> ext::MatchIndices<&'a mut [T], F::Searcher>
1427+
where
1428+
F: Needle<&'a mut [T]>,
1429+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1430+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1431+
{
1432+
ext::match_indices(self, pred)
1433+
}
1434+
1435+
/// An iterator over the disjoint match_indices of a predicate within the given
1436+
/// slice as well as the index that the match starts at, yielded in reverse order.
1437+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1438+
#[inline]
1439+
pub fn rmatch_indices<'a, F>(&'a self, pred: F)
1440+
-> ext::RMatchIndices<&'a [T], F::Searcher>
1441+
where
1442+
F: Needle<&'a [T]>,
1443+
F::Searcher: ReverseSearcher<[T]>,
1444+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1445+
{
1446+
ext::rmatch_indices(self, pred)
1447+
}
1448+
1449+
/// An iterator over the disjoint match_indices of a predicate within the given
1450+
/// mutable slice as well as the index that the match starts at, yielded in reverse order.
1451+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1452+
#[inline]
1453+
pub fn rmatch_indices_mut<'a, F>(&'a mut self, pred: F)
1454+
-> ext::RMatchIndices<&'a mut [T], F::Searcher>
1455+
where
1456+
F: Needle<&'a mut [T]>,
1457+
F::Searcher: ReverseSearcher<[T]>,
1458+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1459+
{
1460+
ext::rmatch_indices(self, pred)
1461+
}
1462+
1463+
/// An iterator over the disjoint matches of a predicate within the given
1464+
/// slice as well as the range that the match covers.
1465+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1466+
#[inline]
1467+
pub fn match_ranges<'a, F>(&'a self, pred: F)
1468+
-> ext::MatchRanges<&'a [T], F::Searcher>
1469+
where
1470+
F: Needle<&'a [T]>,
1471+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1472+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1473+
{
1474+
ext::match_ranges(self, pred)
1475+
}
1476+
1477+
/// An iterator over the disjoint match_ranges of a predicate within the given
1478+
/// mutable slice as well as the range that the match coversat.
1479+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1480+
#[inline]
1481+
pub fn match_ranges_mut<'a, F>(&'a mut self, pred: F)
1482+
-> ext::MatchRanges<&'a mut [T], F::Searcher>
1483+
where
1484+
F: Needle<&'a mut [T]>,
1485+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1486+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1487+
{
1488+
ext::match_ranges(self, pred)
1489+
}
1490+
1491+
/// An iterator over the disjoint match_ranges of a predicate within the given
1492+
/// slice as well as the range that the match covers, yielded in reverse order.
1493+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1494+
#[inline]
1495+
pub fn rmatch_ranges<'a, F>(&'a self, pred: F)
1496+
-> ext::RMatchRanges<&'a [T], F::Searcher>
1497+
where
1498+
F: Needle<&'a [T]>,
1499+
F::Searcher: ReverseSearcher<[T]>,
1500+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1501+
{
1502+
ext::rmatch_ranges(self, pred)
1503+
}
1504+
1505+
/// An iterator over the disjoint match_ranges of a predicate within the given
1506+
/// mutable slice as well as the range that the match covers, yielded in reverse order.
1507+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1508+
#[inline]
1509+
pub fn rmatch_ranges_mut<'a, F>(&'a mut self, pred: F)
1510+
-> ext::RMatchRanges<&'a mut [T], F::Searcher>
1511+
where
1512+
F: Needle<&'a mut [T]>,
1513+
F::Searcher: ReverseSearcher<[T]>,
1514+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1515+
{
1516+
ext::rmatch_ranges(self, pred)
1517+
}
1518+
1519+
/// Returns a slice with all prefixes and suffixes that match a predicate
1520+
/// repeatedly removed.
1521+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1522+
#[inline]
1523+
pub fn trim_matches<'a, F>(&'a self, pred: F) -> &'a [T]
1524+
where
1525+
F: Needle<&'a [T]>,
1526+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1527+
F::Consumer: DoubleEndedConsumer<[T]>,
1528+
{
1529+
ext::trim(self, pred)
1530+
}
1531+
1532+
/// Returns a mutable slice with all prefixes and suffixes that match a
1533+
/// predicate repeatedly removed.
1534+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1535+
#[inline]
1536+
pub fn trim_matches_mut<'a, F>(&'a mut self, pred: F) -> &'a mut [T]
1537+
where
1538+
F: Needle<&'a mut [T]>,
1539+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1540+
F::Consumer: DoubleEndedConsumer<[T]>,
1541+
{
1542+
ext::trim(self, pred)
1543+
}
1544+
1545+
/// Returns a slice with all prefixes that match a predicate repeatedly
1546+
/// removed.
1547+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1548+
#[inline]
1549+
pub fn trim_start_matches<'a, F>(&'a self, pred: F) -> &'a [T]
1550+
where
1551+
F: Needle<&'a [T]>,
1552+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1553+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1554+
{
1555+
ext::trim_start(self, pred)
1556+
}
1557+
1558+
/// Returns a mutable slice with all prefixes that match a predicate
1559+
/// repeatedly removed.
1560+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1561+
#[inline]
1562+
pub fn trim_start_matches_mut<'a, F>(&'a mut self, pred: F) -> &'a mut [T]
1563+
where
1564+
F: Needle<&'a mut [T]>,
1565+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1566+
F::Consumer: Consumer<[T]>, // FIXME: RFC 2089
1567+
{
1568+
ext::trim_start(self, pred)
1569+
}
1570+
1571+
/// Returns a slice with all suffixes that match a predicate repeatedly
1572+
/// removed.
1573+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1574+
#[inline]
1575+
pub fn trim_end_matches<'a, F>(&'a self, pred: F) -> &'a [T]
1576+
where
1577+
F: Needle<&'a [T]>,
1578+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1579+
F::Consumer: ReverseConsumer<[T]>,
1580+
{
1581+
ext::trim_end(self, pred)
1582+
}
1583+
1584+
/// Returns a mutable slice with all suffixes that match a predicate
1585+
/// repeatedly removed.
1586+
#[unstable(feature = "slice_needle_methods", issue = "56345")]
1587+
#[inline]
1588+
pub fn trim_end_matches_mut<'a, F>(&'a mut self, pred: F) -> &'a mut [T]
1589+
where
1590+
F: Needle<&'a mut [T]>,
1591+
F::Searcher: Searcher<[T]>, // FIXME: RFC 2089
1592+
F::Consumer: ReverseConsumer<[T]>,
1593+
{
1594+
ext::trim_end(self, pred)
1595+
}
1596+
12891597
/// Returns `true` if `needle` is a prefix of the slice.
12901598
///
12911599
/// # Examples

0 commit comments

Comments
 (0)
Please sign in to comment.