Skip to content

Commit a795af0

Browse files
committed
Migrate the existing string pattern APIs to use the new Needle API.
1 parent 175d8e8 commit a795af0

File tree

12 files changed

+1552
-2392
lines changed

12 files changed

+1552
-2392
lines changed

src/liballoc/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
#![feature(needs_allocator)]
9292
#![feature(nll)]
9393
#![feature(optin_builtin_traits)]
94-
#![feature(pattern)]
94+
#![feature(needle)]
9595
#![feature(ptr_internals)]
9696
#![feature(ptr_offset_from)]
9797
#![feature(rustc_attrs)]

src/liballoc/str.rs

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
// It's cleaner to just turn off the unused_imports warning than to fix them.
2929
#![allow(unused_imports)]
3030

31-
use core::borrow::Borrow;
32-
use core::str::pattern::{Pattern, Searcher, ReverseSearcher, DoubleEndedSearcher};
31+
use core::fmt;
32+
use core::str as core_str;
33+
use core::needle::{ext, Needle, Searcher, Consumer};
3334
use core::mem;
3435
use core::ptr;
3536
use core::iter::FusedIterator;
@@ -62,8 +63,6 @@ pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes};
6263
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
6364
#[stable(feature = "rust1", since = "1.0.0")]
6465
pub use core::str::SplitWhitespace;
65-
#[stable(feature = "rust1", since = "1.0.0")]
66-
pub use core::str::pattern;
6766
#[stable(feature = "encode_utf16", since = "1.8.0")]
6867
pub use core::str::EncodeUtf16;
6968
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
@@ -255,15 +254,14 @@ impl str {
255254
without modifying the original"]
256255
#[stable(feature = "rust1", since = "1.0.0")]
257256
#[inline]
258-
pub fn replace<'a, P: Pattern<'a>>(&'a self, from: P, to: &str) -> String {
259-
let mut result = String::new();
260-
let mut last_end = 0;
261-
for (start, part) in self.match_indices(from) {
262-
result.push_str(unsafe { self.get_unchecked(last_end..start) });
263-
result.push_str(to);
264-
last_end = start + part.len();
265-
}
266-
result.push_str(unsafe { self.get_unchecked(last_end..self.len()) });
257+
pub fn replace<'s: 'a, 'a, P>(&'s self, from: P, to: &'a str) -> String
258+
where
259+
P: Needle<&'a str>,
260+
P::Searcher: Searcher<str>, // FIXME: RFC 2089
261+
P::Consumer: Consumer<str>, // FIXME: RFC 2089
262+
{
263+
let mut result = String::with_capacity(self.len());
264+
ext::replace_with(self, from, |_| to, |s| result.push_str(s));
267265
result
268266
}
269267

@@ -295,16 +293,15 @@ impl str {
295293
#[must_use = "this returns the replaced string as a new allocation, \
296294
without modifying the original"]
297295
#[stable(feature = "str_replacen", since = "1.16.0")]
298-
pub fn replacen<'a, P: Pattern<'a>>(&'a self, pat: P, to: &str, count: usize) -> String {
296+
pub fn replacen<'s: 'a, 'a, P>(&'s self, pat: P, to: &'a str, count: usize) -> String
297+
where
298+
P: Needle<&'a str>,
299+
P::Searcher: Searcher<str>, // FIXME: RFC 2089
300+
P::Consumer: Consumer<str>, // FIXME: RFC 2089
301+
{
299302
// Hope to reduce the times of re-allocation
300-
let mut result = String::with_capacity(32);
301-
let mut last_end = 0;
302-
for (start, part) in self.match_indices(pat).take(count) {
303-
result.push_str(unsafe { self.get_unchecked(last_end..start) });
304-
result.push_str(to);
305-
last_end = start + part.len();
306-
}
307-
result.push_str(unsafe { self.get_unchecked(last_end..self.len()) });
303+
let mut result = String::with_capacity(self.len());
304+
ext::replacen_with(self, pat, |_| to, count, |s| result.push_str(s));
308305
result
309306
}
310307

src/liballoc/string.rs

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ use core::iter::{FromIterator, FusedIterator};
5353
use core::ops::{self, Add, AddAssign, Index, IndexMut, RangeBounds};
5454
use core::ops::Bound::{Excluded, Included, Unbounded};
5555
use core::ptr;
56-
use core::str::{pattern::Pattern, lossy};
56+
use core::needle::Needle;
57+
use core::str::lossy;
5758

5859
use crate::borrow::{Cow, ToOwned};
5960
use crate::collections::CollectionAllocErr;
@@ -1792,24 +1793,19 @@ impl<'a> Extend<Cow<'a, str>> for String {
17921793
}
17931794

17941795
/// A convenience impl that delegates to the impl for `&str`
1795-
#[unstable(feature = "pattern",
1796-
reason = "API not fully fleshed out and ready to be stabilized",
1797-
issue = "27721")]
1798-
impl<'a, 'b> Pattern<'a> for &'b String {
1799-
type Searcher = <&'b str as Pattern<'a>>::Searcher;
1800-
1801-
fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher {
1802-
self[..].into_searcher(haystack)
1803-
}
1796+
#[unstable(feature = "needle", issue = "56345")]
1797+
impl<'a, 'b> Needle<&'a str> for &'b String {
1798+
type Searcher = <&'b str as Needle<&'a str>>::Searcher;
1799+
type Consumer = <&'b str as Needle<&'a str>>::Consumer;
18041800

18051801
#[inline]
1806-
fn is_contained_in(self, haystack: &'a str) -> bool {
1807-
self[..].is_contained_in(haystack)
1802+
fn into_searcher(self) -> Self::Searcher {
1803+
<&'b str as Needle<&'a str>>::into_searcher(&**self)
18081804
}
18091805

18101806
#[inline]
1811-
fn is_prefix_of(self, haystack: &'a str) -> bool {
1812-
self[..].is_prefix_of(haystack)
1807+
fn into_consumer(self) -> Self::Consumer {
1808+
<&'b str as Needle<&'a str>>::into_consumer(&**self)
18131809
}
18141810
}
18151811

src/liballoc/tests/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
#![feature(box_syntax)]
33
#![feature(drain_filter)]
44
#![feature(exact_size_is_empty)]
5-
#![feature(pattern)]
65
#![feature(repeat_generic_slice)]
6+
#![feature(needle)]
7+
#![feature(slice_sort_by_cached_key)]
8+
#![feature(str_escape)]
79
#![feature(try_reserve)]
810
#![feature(unboxed_closures)]
911
#![feature(vecdeque_rotate)]

src/liballoc/tests/str.rs

Lines changed: 4 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,145 +1606,6 @@ fn test_repeat() {
16061606
assert_eq!("α".repeat(3), "ααα");
16071607
}
16081608

1609-
mod pattern {
1610-
use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1611-
use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1612-
1613-
macro_rules! make_test {
1614-
($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1615-
#[allow(unused_imports)]
1616-
mod $name {
1617-
use std::str::pattern::SearchStep::{Match, Reject};
1618-
use super::{cmp_search_to_vec};
1619-
#[test]
1620-
fn fwd() {
1621-
cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1622-
}
1623-
#[test]
1624-
fn bwd() {
1625-
cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1626-
}
1627-
}
1628-
}
1629-
}
1630-
1631-
fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1632-
right: Vec<SearchStep>)
1633-
where P::Searcher: ReverseSearcher<'a>
1634-
{
1635-
let mut searcher = pat.into_searcher(haystack);
1636-
let mut v = vec![];
1637-
loop {
1638-
match if !rev {searcher.next()} else {searcher.next_back()} {
1639-
Match(a, b) => v.push(Match(a, b)),
1640-
Reject(a, b) => v.push(Reject(a, b)),
1641-
Done => break,
1642-
}
1643-
}
1644-
if rev {
1645-
v.reverse();
1646-
}
1647-
1648-
let mut first_index = 0;
1649-
let mut err = None;
1650-
1651-
for (i, e) in right.iter().enumerate() {
1652-
match *e {
1653-
Match(a, b) | Reject(a, b)
1654-
if a <= b && a == first_index => {
1655-
first_index = b;
1656-
}
1657-
_ => {
1658-
err = Some(i);
1659-
break;
1660-
}
1661-
}
1662-
}
1663-
1664-
if let Some(err) = err {
1665-
panic!("Input skipped range at {}", err);
1666-
}
1667-
1668-
if first_index != haystack.len() {
1669-
panic!("Did not cover whole input");
1670-
}
1671-
1672-
assert_eq!(v, right);
1673-
}
1674-
1675-
make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1676-
Reject(0, 1),
1677-
Match (1, 3),
1678-
Reject(3, 4),
1679-
Match (4, 6),
1680-
Reject(6, 7),
1681-
]);
1682-
make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1683-
Reject(0, 1),
1684-
Match (1, 3),
1685-
Reject(3, 4),
1686-
Match (4, 6),
1687-
Match (6, 8),
1688-
Reject(8, 9),
1689-
]);
1690-
make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1691-
Match (0, 0),
1692-
Reject(0, 1),
1693-
Match (1, 1),
1694-
Reject(1, 2),
1695-
Match (2, 2),
1696-
Reject(2, 3),
1697-
Match (3, 3),
1698-
Reject(3, 4),
1699-
Match (4, 4),
1700-
Reject(4, 5),
1701-
Match (5, 5),
1702-
Reject(5, 6),
1703-
Match (6, 6),
1704-
Reject(6, 7),
1705-
Match (7, 7),
1706-
]);
1707-
make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1708-
Reject(0, 3),
1709-
Reject(3, 6),
1710-
Reject(6, 9),
1711-
]);
1712-
make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1713-
Match (0, 0),
1714-
Reject(0, 3),
1715-
Match (3, 3),
1716-
Reject(3, 6),
1717-
Match (6, 6),
1718-
Reject(6, 9),
1719-
Match (9, 9),
1720-
]);
1721-
make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1722-
Match(0, 0),
1723-
]);
1724-
make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1725-
]);
1726-
make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1727-
Reject(0, 1),
1728-
Match (1, 2),
1729-
Match (2, 3),
1730-
Reject(3, 4),
1731-
Match (4, 5),
1732-
Match (5, 6),
1733-
Reject(6, 7),
1734-
]);
1735-
make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1736-
Reject(0, 3),
1737-
Reject(3, 6),
1738-
Reject(6, 9),
1739-
]);
1740-
make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1741-
Reject(0, 1),
1742-
Reject(1, 2),
1743-
Reject(2, 3),
1744-
]);
1745-
1746-
}
1747-
17481609
macro_rules! generate_iterator_test {
17491610
{
17501611
$name:ident {
@@ -1837,13 +1698,14 @@ generate_iterator_test! {
18371698

18381699
#[test]
18391700
fn different_str_pattern_forwarding_lifetimes() {
1840-
use std::str::pattern::Pattern;
1701+
// FIXME: The generic form (see PR 31989) causes a strange "trait bound not satisfied" error.
1702+
// revisit this after RFC 2089 is implemented.
18411703

1842-
fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1704+
fn foo(p: &str) {
18431705
for _ in 0..3 {
18441706
"asdf".find(&p);
18451707
}
18461708
}
18471709

1848-
foo::<&str>("x");
1710+
foo("x");
18491711
}

src/libcore/slice/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ pub mod memchr;
4343
mod rotate;
4444
mod sort;
4545

46+
/// Needle implementations for slices
47+
#[unstable(
48+
feature = "slice_internals",
49+
issue = "0",
50+
reason = "exposed from core to be reused in std",
51+
)]
52+
#[doc(hidden)]
53+
pub mod needles;
54+
4655
#[repr(C)]
4756
union Repr<'a, T: 'a> {
4857
rust: &'a [T],

0 commit comments

Comments
 (0)