Rollup merge of #75265 - WaffleLapkin:str_split_as_str, r=dtolnay
Add `str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_str` methods tl;dr this allows viewing unyelded part of str-split-iterators, like so: ```rust let mut split = "Mary had a little lamb".split(' '); assert_eq!(split.as_str(), "Mary had a little lamb"); split.next(); assert_eq!(split.as_str(), "had a little lamb"); split.by_ref().for_each(drop); assert_eq!(split.as_str(), ""); ``` -------------- This PR adds semi-identical `as_str` methods to most str-split-iterators with signatures like `&'_ Split<'a, P: Pattern<'a>> -> &'a str` (Note: output `&str` lifetime is bound to the `'a`, not the `'_`). The methods are similar to [`Chars::as_str`] `SplitInclusive::as_str` is under `"str_split_inclusive_as_str"` feature gate, all other methods are under `"str_split_as_str"` feature gate. Before this PR you had to sum `len`s of all yielded parts or collect into `String` to emulate `as_str`. [`Chars::as_str`]: https://doc.rust-lang.org/core/str/struct.Chars.html#method.as_str
This commit is contained in:
commit
977df43c4a
2 changed files with 166 additions and 0 deletions
|
@ -126,6 +126,8 @@
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(std_internals)]
|
#![feature(std_internals)]
|
||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
|
#![feature(str_split_as_str)]
|
||||||
|
#![feature(str_split_inclusive_as_str)]
|
||||||
#![feature(transparent_unions)]
|
#![feature(transparent_unions)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unsized_locals)]
|
#![feature(unsized_locals)]
|
||||||
|
|
|
@ -690,6 +690,17 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &'a str {
|
||||||
|
// `Self::get_end` doesn't change `self.start`
|
||||||
|
if self.finished {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: `self.start` and `self.end` always lie on unicode boundaries.
|
||||||
|
unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_pattern_iterators! {
|
generate_pattern_iterators! {
|
||||||
|
@ -710,6 +721,48 @@ generate_pattern_iterators! {
|
||||||
delegate double ended;
|
delegate double ended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> Split<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "Mary had a little lamb".split(' ');
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> RSplit<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "Mary had a little lamb".rsplit(' ');
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
generate_pattern_iterators! {
|
generate_pattern_iterators! {
|
||||||
forward:
|
forward:
|
||||||
/// Created with the method [`split_terminator`].
|
/// Created with the method [`split_terminator`].
|
||||||
|
@ -728,6 +781,48 @@ generate_pattern_iterators! {
|
||||||
delegate double ended;
|
delegate double ended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "A..B..".split_terminator('.');
|
||||||
|
/// assert_eq!(split.as_str(), "A..B..");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), ".B..");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "A..B..".rsplit_terminator('.');
|
||||||
|
/// assert_eq!(split.as_str(), "A..B..");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "A..B");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
derive_pattern_clone! {
|
derive_pattern_clone! {
|
||||||
clone SplitNInternal
|
clone SplitNInternal
|
||||||
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
with |s| SplitNInternal { iter: s.iter.clone(), ..*s }
|
||||||
|
@ -784,6 +879,11 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &'a str {
|
||||||
|
self.iter.as_str()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_pattern_iterators! {
|
generate_pattern_iterators! {
|
||||||
|
@ -804,6 +904,48 @@ generate_pattern_iterators! {
|
||||||
delegate single ended;
|
delegate single ended;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> SplitN<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "Mary had a little lamb".splitn(3, ' ');
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> RSplitN<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_as_str)]
|
||||||
|
/// let mut split = "Mary had a little lamb".rsplitn(3, ' ');
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
derive_pattern_clone! {
|
derive_pattern_clone! {
|
||||||
clone MatchIndicesInternal
|
clone MatchIndicesInternal
|
||||||
with |s| MatchIndicesInternal(s.0.clone())
|
with |s| MatchIndicesInternal(s.0.clone())
|
||||||
|
@ -1134,6 +1276,28 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator
|
||||||
#[unstable(feature = "split_inclusive", issue = "72360")]
|
#[unstable(feature = "split_inclusive", issue = "72360")]
|
||||||
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
|
impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {}
|
||||||
|
|
||||||
|
impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> {
|
||||||
|
/// Returns remainder of the splitted string
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(str_split_inclusive_as_str)]
|
||||||
|
/// #![feature(split_inclusive)]
|
||||||
|
/// let mut split = "Mary had a little lamb".split_inclusive(' ');
|
||||||
|
/// assert_eq!(split.as_str(), "Mary had a little lamb");
|
||||||
|
/// split.next();
|
||||||
|
/// assert_eq!(split.as_str(), "had a little lamb");
|
||||||
|
/// split.by_ref().for_each(drop);
|
||||||
|
/// assert_eq!(split.as_str(), "");
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "str_split_inclusive_as_str", issue = "77998")]
|
||||||
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
self.0.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator of [`u16`] over the string encoded as UTF-16.
|
/// An iterator of [`u16`] over the string encoded as UTF-16.
|
||||||
///
|
///
|
||||||
/// This struct is created by the [`encode_utf16`] method on [`str`].
|
/// This struct is created by the [`encode_utf16`] method on [`str`].
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue