Skip to content

Commit 521aacb

Browse files
committed
Auto merge of #59591 - kennytm:needle-api, r=<try>
[WIP] Implement Needle API (RFC 2500) cc #56345 ---- Insta-stable changes: * `impl Index<Range***> for OsStr` cannot be gated and is insta-stable. I'll add more comments after the crater run.
2 parents 7754865 + 6cc67c7 commit 521aacb

32 files changed

+7127
-3458
lines changed

src/liballoc/boxed.rs

+33
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ use core::hash::{Hash, Hasher};
7878
use core::iter::{Iterator, FromIterator, FusedIterator};
7979
use core::marker::{Unpin, Unsize};
8080
use core::mem;
81+
use core::needle::Needle;
8182
use core::pin::Pin;
8283
use core::ops::{
8384
CoerceUnsized, DispatchFromDyn, Deref, DerefMut, Receiver, Generator, GeneratorState
@@ -919,3 +920,35 @@ impl<F: ?Sized + Future + Unpin> Future for Box<F> {
919920
F::poll(Pin::new(&mut *self), cx)
920921
}
921922
}
923+
924+
#[unstable(feature = "needle", issue = "56345")]
925+
impl<'p, 'h, T: PartialEq + 'p + 'h> Needle<&'h [T]> for &'p Box<[T]> {
926+
type Searcher = <&'p [T] as Needle<&'h [T]>>::Searcher;
927+
type Consumer = <&'p [T] as Needle<&'h [T]>>::Consumer;
928+
929+
#[inline]
930+
fn into_searcher(self) -> Self::Searcher {
931+
<&'p [T] as Needle<&'h [T]>>::into_searcher(&**self)
932+
}
933+
934+
#[inline]
935+
fn into_consumer(self) -> Self::Consumer {
936+
<&'p [T] as Needle<&'h [T]>>::into_consumer(&**self)
937+
}
938+
}
939+
940+
#[unstable(feature = "needle", issue = "56345")]
941+
impl<'p, 'h, T: PartialEq + 'p + 'h> Needle<&'h mut [T]> for &'p Box<[T]> {
942+
type Searcher = <&'p [T] as Needle<&'h mut [T]>>::Searcher;
943+
type Consumer = <&'p [T] as Needle<&'h mut [T]>>::Consumer;
944+
945+
#[inline]
946+
fn into_searcher(self) -> Self::Searcher {
947+
<&'p [T] as Needle<&'h mut [T]>>::into_searcher(&**self)
948+
}
949+
950+
#[inline]
951+
fn into_consumer(self) -> Self::Consumer {
952+
<&'p [T] as Needle<&'h mut [T]>>::into_consumer(&**self)
953+
}
954+
}

src/liballoc/lib.rs

+1-1
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/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/str.rs

+19-23
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@
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::needle::{ext, Needle, Searcher, Consumer};
3333
use core::mem;
3434
use core::ptr;
3535
use core::iter::FusedIterator;
3636
use core::unicode::conversions;
3737

38-
use crate::borrow::ToOwned;
38+
use crate::borrow::{Borrow, ToOwned};
3939
use crate::boxed::Box;
4040
use crate::slice::{SliceConcatExt, SliceIndex};
4141
use crate::string::String;
@@ -62,8 +62,6 @@ pub use core::str::{from_utf8, from_utf8_mut, Chars, CharIndices, Bytes};
6262
pub use core::str::{from_utf8_unchecked, from_utf8_unchecked_mut, ParseBoolError};
6363
#[stable(feature = "rust1", since = "1.0.0")]
6464
pub use core::str::SplitWhitespace;
65-
#[stable(feature = "rust1", since = "1.0.0")]
66-
pub use core::str::pattern;
6765
#[stable(feature = "encode_utf16", since = "1.8.0")]
6866
pub use core::str::EncodeUtf16;
6967
#[stable(feature = "split_ascii_whitespace", since = "1.34.0")]
@@ -255,15 +253,14 @@ impl str {
255253
without modifying the original"]
256254
#[stable(feature = "rust1", since = "1.0.0")]
257255
#[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()) });
256+
pub fn replace<'s: 'a, 'a, P>(&'s self, from: P, to: &'a str) -> String
257+
where
258+
P: Needle<&'a str>,
259+
P::Searcher: Searcher<str>, // FIXME: RFC 2089
260+
P::Consumer: Consumer<str>, // FIXME: RFC 2089
261+
{
262+
let mut result = String::with_capacity(self.len());
263+
ext::replace_with(self, from, |_| to, |s| result.push_str(s));
267264
result
268265
}
269266

@@ -295,16 +292,15 @@ impl str {
295292
#[must_use = "this returns the replaced string as a new allocation, \
296293
without modifying the original"]
297294
#[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 {
295+
pub fn replacen<'s: 'a, 'a, P>(&'s self, pat: P, to: &'a str, count: usize) -> String
296+
where
297+
P: Needle<&'a str>,
298+
P::Searcher: Searcher<str>, // FIXME: RFC 2089
299+
P::Consumer: Consumer<str>, // FIXME: RFC 2089
300+
{
299301
// 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()) });
302+
let mut result = String::with_capacity(self.len());
303+
ext::replacen_with(self, pat, |_| to, count, |s| result.push_str(s));
308304
result
309305
}
310306

src/liballoc/string.rs

+10-14
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

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
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)]
77
#![feature(try_reserve)]
88
#![feature(unboxed_closures)]
99
#![feature(vecdeque_rotate)]
10+
#![feature(mut_str_needle_methods)]
11+
#![feature(slice_needle_methods)]
1012

1113
use std::hash::{Hash, Hasher};
1214
use std::collections::hash_map::DefaultHasher;

0 commit comments

Comments
 (0)