From 0b923d3ca0b7f5a1a611564ee48c1e92f896d79e Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 1 Oct 2020 20:06:44 +0300 Subject: [PATCH 1/4] add `str::{Split,RSplit}::as_str` methods This commit introduses 2 methods under "str_split_as_str" gate with common signature of `&Split<'a, _> -> &'a str'`. Both of them work like `Chars::as_str` - return unyield part of the inner string. --- library/core/src/lib.rs | 1 + library/core/src/str/iter.rs | 55 ++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 22bf2b15d66..c7588f618e1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -125,6 +125,7 @@ #![feature(staged_api)] #![feature(std_internals)] #![feature(stmt_expr_attributes)] +#![feature(str_split_as_str)] #![feature(transparent_unions)] #![feature(unboxed_closures)] #![feature(unsized_locals)] diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 27a67e2b22f..1b71f54bd84 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -690,6 +690,19 @@ fn next_back_inclusive(&mut self) -> Option<&'a str> }, } } + + #[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! { @@ -710,6 +723,48 @@ fn next_back_inclusive(&mut self) -> Option<&'a str> 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 = "none")] + 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 = "none")] + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} + generate_pattern_iterators! { forward: /// Created with the method [`split_terminator`]. From 4747215d778abd9f280202d07f279fdeaea519f8 Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 1 Oct 2020 23:08:15 +0300 Subject: [PATCH 2/4] add `str::{SplitN, RSplitN, SplitTerminator, RSplitTerminator}::as_str` methods This commit entroduce 4 methods smililar to `Split::as_str` all under the same gate "str_split_as_str". --- library/core/src/str/iter.rs | 89 ++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 1b71f54bd84..dc2c2e0168f 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -783,6 +783,48 @@ pub fn as_str(&self) -> &'a str { 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 = "none")] + 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 = "none")] + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} + derive_pattern_clone! { clone SplitNInternal with |s| SplitNInternal { iter: s.iter.clone(), ..*s } @@ -839,6 +881,11 @@ fn next_back(&mut self) -> Option<&'a str> } } } + + #[inline] + fn as_str(&self) -> &'a str { + self.iter.as_str() + } } generate_pattern_iterators! { @@ -859,6 +906,48 @@ fn next_back(&mut self) -> Option<&'a str> 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 = "none")] + 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 = "none")] + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} + derive_pattern_clone! { clone MatchIndicesInternal with |s| MatchIndicesInternal(s.0.clone()) From 076514c8a82591547116a7a2212c4de4bdc56f76 Mon Sep 17 00:00:00 2001 From: Waffle Date: Thu, 1 Oct 2020 23:39:20 +0300 Subject: [PATCH 3/4] add `str::SplitInclusive::as_str` method This commit entroduces `core::str::SplitInclusive::as_str` method similar to `core::str::Split::as_str`, but under different gate - "str_split_inclusive_as_str" (this is done so because `SplitInclusive` is itself unstable). --- library/core/src/lib.rs | 1 + library/core/src/str/iter.rs | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index c7588f618e1..8f1826a47e1 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -126,6 +126,7 @@ #![feature(std_internals)] #![feature(stmt_expr_attributes)] #![feature(str_split_as_str)] +#![feature(str_split_inclusive_as_str)] #![feature(transparent_unions)] #![feature(unboxed_closures)] #![feature(unsized_locals)] diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index dc2c2e0168f..2da390b2b2b 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -699,9 +699,7 @@ fn as_str(&self) -> &'a str { } // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. - unsafe { - self.matcher.haystack().get_unchecked(self.start..self.end) - } + unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) } } } @@ -1278,6 +1276,28 @@ fn next_back(&mut self) -> Option<&'a str> { #[unstable(feature = "split_inclusive", issue = "72360")] 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 = "none")] + pub fn as_str(&self) -> &'a str { + self.0.as_str() + } +} + /// An iterator of [`u16`] over the string encoded as UTF-16. /// /// This struct is created by the [`encode_utf16`] method on [`str`]. From 7bd6403b38965a17bd0f0693fa1563d09681d422 Mon Sep 17 00:00:00 2001 From: Waffle Date: Fri, 16 Oct 2020 01:11:39 +0300 Subject: [PATCH 4/4] fill in the tracking issue --- library/core/src/str/iter.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 2da390b2b2b..bee86df520c 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -736,7 +736,7 @@ impl<'a, P: Pattern<'a>> Split<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -757,7 +757,7 @@ impl<'a, P: Pattern<'a>> RSplit<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -796,7 +796,7 @@ impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -817,7 +817,7 @@ impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -919,7 +919,7 @@ impl<'a, P: Pattern<'a>> SplitN<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -940,7 +940,7 @@ impl<'a, P: Pattern<'a>> RSplitN<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "none")] + #[unstable(feature = "str_split_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() } @@ -1292,7 +1292,7 @@ impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> { /// assert_eq!(split.as_str(), ""); /// ``` #[inline] - #[unstable(feature = "str_split_inclusive_as_str", issue = "none")] + #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")] pub fn as_str(&self) -> &'a str { self.0.as_str() }