Repository navigation
Tracking Issue for remainder methods for str split iterators #77998
Description
This is a tracking issue for the methods implemented in #75265 and #82570, which allow viewing the remainder of the underlying string in str-split iterators. E.g.:
let mut split = "Mary had a little lamb".split(' ');
assert_eq!(split.remainder(), Some("Mary had a little lamb"));
_ = split.next();
assert_eq!(split.remainder(), Some("had a little lamb"));
split.by_ref().for_each(drop);
assert_eq!(split.remainder(), None);The feature gates for the issue are #![feature(str_split_remainder)] (for most split iterators), #![feature(str_split_inclusive_remainder)] (for SplitInclusive) and #![feature(str_split_whitespace_remainder)] (for SplitWhitespace and SplitAsciiWhitespace).
Public API
// mod core::str
impl<'a, P: Pattern<'a>> Split<'a, P> {
fn remainder(&self) -> Option<&'a str>;
}
// And the same for
// - `RSplit<'a, P>`
// - `SplitTerminator<'a, P>`
// - `RSplitTerminator<'a, P>`
// - `SplitN<'a, P>`
// - `RSplitN<'a, P>`
// - `SplitWhitespace<'a>`
// - `SplitAsciiWhitespace<'a>`
// - `SplitInclusive<'a, P>`Steps
- Implement the feature
- Adjust documentation (see instructions on rustc-dev-guide)
- Stabilization PR (see instructions on rustc-dev-guide)
Unresolved Questions
Should empty strings point to the end of the haystack, or they can be arbitrary constants? (see Addstr::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_strmethods #75265 (comment))Noneis now returned instead of an empty string, making this irrelevant
Implementation history
-
Add
str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive}::as_strmethods #75265 — implementedas_strmethods oncore::str::{Split,RSplit,SplitN,RSplitN,SplitTerminator,RSplitTerminator,SplitInclusive} -
Add
as_strmethod for split whitespace str iterators #82570 — implementedas_strmethods oncore::str::{SplitWhitespace, SplitAsciiWhitespace} -
Split*::as_strrefactor #95644 — renamedas_str=>remainderand changed return type toOption<&str>
Activity
SkiFire13 commentedon Oct 19, 2020
Looking at its name it isn't immediately clear what it returns. Wouldn't
remainderor something along that line be a more self-explanatory name?WaffleLapkin commentedon Oct 20, 2020
The name
as_strwas chosen to be in line withChars::as_strTyPR124 commentedon Feb 20, 2021
Can this be added to
SplitWhitespaceandSplitAsciiWhitespace?WaffleLapkin commentedon Feb 20, 2021
@TyPR124 as noted in the implementation PR discussion it is possible, but not trivial.
Both
Split*Whitespaceare using iterators internally which doesn't allow to access it's inner parts (^1, ^2). It's possible to 'solve' this problem either by making the fieldspub(crate::str::iter)(tbh it's a hack) or providing methods on iterator adaptors that allow accessing inner iterators (downside: there are lots of adaptors to change).I didn't want to complicate the original PR with this, so didn't include anything like this. I can now make a new PR that'll add the same methods to
Split*Whitespace, thanks for reminding about it!WaffleLapkin commentedon Mar 20, 2021
Update: #82570 was merged, so now
SplitWhitespaceandSplitAsciiWhitespacehasas_strmethod too!soerenmeier commentedon Apr 14, 2021
I just had a case we're i needed to split a str:
"tag:value"into atag: &strand avalue: Option<&str>.I know i can just use
Some(iter.as_str()).filter(str::is_empty)to get theOption, but maybe there could be another method namedas_opt_strorremainder. That method would returnNoneif calling next would also returnNone.What do you think?
SkiFire13 commentedon Apr 14, 2021
Note that split iterators could yield an empty str as their final item, so
as_opt_strcould returnSome("")while your code with always filter that case.soerenmeier commentedon Apr 14, 2021
That's true, to be correct the above code should look like this:
Would be nice to have
as_opt_str.m-ou-se commentedon May 4, 2021
That sounds like a use case for the recently stabilized
split_once.8 remaining items
Piturnah commentedon Jun 29, 2023
What's the status wrt stabilisation?
smarnach commentedon Aug 5, 2023
I noticed that
SplitWhitespace::remainder()has some counter-intuitive behaviour if tokens are separated by multiple whitespace characters. Theremainder()method includes all but the first whitespace character in the returned string:I would expect it to either include all of the whitespace or none of it (though I do understand why it behaves the way it does). This behaviour, if intended, should at least be documented.
kornelski commentedon Oct 21, 2023
I needed a functionality of "split the string once on X or Y, whichever is first", and I need to know whether X or Y was first.
I hoped I could use
str.split(|c: char| c == X || c == Y)and then inspect theiter.remainder()to see whether X or Y was there, but I was disappointed to learn that theremainderis after the next split, rather than immediately after the previously returned substring.Rollup merge of rust-lang#107464 - WaffleLapkin:all_that_remains_of_l…
Rollup merge of rust-lang#107464 - WaffleLapkin:all_that_remains_of_l…
Unrolled build for rust-lang#107464
lkurcak commentedon Jul 2, 2024
Could this work with
peekable?https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=73dea5523564c607bef9c4b3a93a2169
camsteffen commentedon Mar 11, 2025
I think
as_strwould be a fine name - I personally just expected it to exist since I am familiar withas_strandas_sliceon other iterators.I feel like the Option may be overcomplicating it. I expected it to just return an empty string as in
&string[string.len()..] == "". I think the reasoning for Option doesn't apply forsplit_inclusive()at least. Not having an Option would allow for simpler code when an empty string is not a special case.lo48576 commentedon Mar 11, 2025
I think returning None is more convenient. Assume you got the remainder as
iter.as_str().iter.as_str().unwrap_or_default()Some(iter.as_str()).filter(|s| !s.is_empty())iter.as_str())I don't remember if there is simpler or shorter way of doing
Some(val).filter(pred)without binding to a variable, but from this comparison I think returningOption<&str>from the method is more generic and straightforward to use in any situation.sumitpsm commentedon Nov 6, 2025
Here, is another use case of
remainderfunction:I am trying to implement a
Scannerhere
remainderfunction will boil down the code for thenext_linefunction in few linescramertj commentedon Jun 2, 2026
I have a use case for this where I want to split a file into a header and a footer, where the end of the header is determined by seeing a line that matches some predicate. I don't particularly care whether the remainder is empty or not, so in this case the
Optionwould be mapped to a an empty string.sffc commentedon Sep 24, 2026
I've landed on this issue multiple times after looking for a function like
split_once_inclusive.