Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tracking issue for strip_prefix, strip_suffix for str #67302

Closed
Dylan-DPC-zz opened this issue Dec 14, 2019 · 9 comments · Fixed by #72466
Closed

tracking issue for strip_prefix, strip_suffix for str #67302

Dylan-DPC-zz opened this issue Dec 14, 2019 · 9 comments · Fixed by #72466
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Dylan-DPC-zz
Copy link

Cc @KodrAus

Will fill the content later. Creating this so that #66735 can be merged and tracked.

@jonas-schievink jonas-schievink added B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Dec 14, 2019
@tesuji
Copy link
Contributor

tesuji commented Feb 13, 2020

The code generated by str::strip_prefix is really complicated and inefficient.
Godbolt link: https://rust.godbolt.org/z/AnEoHH
Should we add strip_prefix / strip_suffix method directly to Pattern or Searcher trait?

@CryZe
Copy link
Contributor

CryZe commented Feb 18, 2020

Oof that does indeed look pretty bad.

@benesch
Copy link
Contributor

benesch commented Mar 6, 2020

I whipped up that fix here: #69784

Not sure if it's actually the ideal fix, but figured it would be a good point to launch the discussion from.

Centril added a commit to Centril/rust that referenced this issue Mar 31, 2020
…=kennytm

Optimize strip_prefix and strip_suffix with str patterns

As mentioned in rust-lang#67302 (comment).
I'm not sure whether adding these methods to `Pattern` is desirable—but they have default implementations so the change is backwards compatible. Plus it seems like they're slated for wholesale replacement soon anyway? rust-lang#56345

----

Constructing a Searcher in strip_prefix and strip_suffix is
unnecessarily slow when the pattern is a fixed-length string. Add
strip_prefix and strip_suffix methods to the Pattern trait, and add
optimized implementations of these methods in the str implementation.
The old implementation is retained as the default for these methods.
Centril added a commit to Centril/rust that referenced this issue Mar 31, 2020
…=kennytm

Optimize strip_prefix and strip_suffix with str patterns

As mentioned in rust-lang#67302 (comment).
I'm not sure whether adding these methods to `Pattern` is desirable—but they have default implementations so the change is backwards compatible. Plus it seems like they're slated for wholesale replacement soon anyway? rust-lang#56345

----

Constructing a Searcher in strip_prefix and strip_suffix is
unnecessarily slow when the pattern is a fixed-length string. Add
strip_prefix and strip_suffix methods to the Pattern trait, and add
optimized implementations of these methods in the str implementation.
The old implementation is retained as the default for these methods.
Centril added a commit to Centril/rust that referenced this issue Mar 31, 2020
…=kennytm

Optimize strip_prefix and strip_suffix with str patterns

As mentioned in rust-lang#67302 (comment).
I'm not sure whether adding these methods to `Pattern` is desirable—but they have default implementations so the change is backwards compatible. Plus it seems like they're slated for wholesale replacement soon anyway? rust-lang#56345

----

Constructing a Searcher in strip_prefix and strip_suffix is
unnecessarily slow when the pattern is a fixed-length string. Add
strip_prefix and strip_suffix methods to the Pattern trait, and add
optimized implementations of these methods in the str implementation.
The old implementation is retained as the default for these methods.
@benesch
Copy link
Contributor

benesch commented Apr 1, 2020

Ok, the code should be far more optimized now. What remains to be done? The main issue description has yet to be filled in. 😄

@lights0123
Copy link

On some criterion benchmarks that I did, I'm seeing that

fn strip_suffix(input: &str) -> &str {
	input.strip_suffix(char::is_whitespace).unwrap_or(input)
}

is much faster than trim_end, at least for newlines only. Is this only because I'm stripping off a very small amount of text, or is this function more optimized than trim_end (assuming that I didn't screw something up)? See "Standard strip suffix" versus "Standard trim end", with "unix" having the input of "50\n" and "win" being "50\r\n":
benches

@benesch
Copy link
Contributor

benesch commented Apr 28, 2020

Ah, yeah, looks the optimizations I made to strip_prefix/strip_suffix in #69784 are optimizations that don't exist for trim_end:

rust/src/libcore/str/mod.rs

Lines 4137 to 4148 in 20fc02f

pub fn trim_end_matches<'a, P>(&'a self, pat: P) -> &'a str
where
P: Pattern<'a, Searcher: ReverseSearcher<'a>>,
{
let mut j = 0;
let mut matcher = pat.into_searcher(self);
if let Some((_, b)) = matcher.next_reject_back() {
j = b;
}
// SAFETY: `Searcher` is known to return valid indices.
unsafe { self.get_unchecked(0..j) }
}

I wonder if trim_end_matches could be reimplemented as a loop over strip_suffix_of...

By the way, since I'm here, @Dylan-DPC (or anyone else on the Rust team), what remains to be done for this issue?

@Dylan-DPC-zz
Copy link
Author

By the way, since I'm here, @Dylan-DPC (or anyone else on the Rust team), what remains to be done for this issue?

If you want to change the implementation this is a good time. Else, the thing left is stabilisation with the libs team approving it (if needed) but i'd wait for some time to check if there are any other issues.

@benesch
Copy link
Contributor

benesch commented Apr 28, 2020

The implementation is now faster than the existing similar stable functions trim_start and trim_end, so I think we're in a good spot implementation wise. Would you be able to add a note about the progress and when we expect to start the stabilization discussion in the issue description? (Or whatever normally goes in there?)

@Dylan-DPC-zz
Copy link
Author

@benesch you can submit a stabilisation PR by following the instructions here: https://forge.rust-lang.org/libs/maintaining-std.html?highlight=stabi#when-a-feature-is-being-stabilized.

JohnTitor added a commit to JohnTitor/rust that referenced this issue May 28, 2020
Stabilize str_strip feature

This PR stabilizes these APIs:

```rust
impl str {
    /// Returns a string slice with the prefix removed.
    ///
    /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where
    /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly
    /// once.
    pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str>;

    /// Returns a string slice with the suffix removed.
    ///
    /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where
    /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly
    /// once.
    pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str>
    where
        P: Pattern<'a>,
        <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>;
}
```

Closes  rust-lang#67302
@bors bors closed this as completed in 3bcf697 May 29, 2020
tesuji pushed a commit to tesuji/rustc that referenced this issue Jun 4, 2020
Stabilize str_strip feature

This PR stabilizes these APIs:

```rust
impl str {
    /// Returns a string slice with the prefix removed.
    ///
    /// If the string starts with the pattern `prefix`, `Some` is returned with the substring where
    /// the prefix is removed. Unlike `trim_start_matches`, this method removes the prefix exactly
    /// once.
    pub fn strip_prefix<'a, P: Pattern<'a>>(&'a self, prefix: P) -> Option<&'a str>;

    /// Returns a string slice with the suffix removed.
    ///
    /// If the string ends with the pattern `suffix`, `Some` is returned with the substring where
    /// the suffix is removed. Unlike `trim_end_matches`, this method removes the suffix exactly
    /// once.
    pub fn strip_suffix<'a, P>(&'a self, suffix: P) -> Option<&'a str>
    where
        P: Pattern<'a>,
        <P as Pattern<'a>>::Searcher: ReverseSearcher<'a>;
}
```

Closes  rust-lang#67302
juztamau5 added a commit to juztamau5/descartes that referenced this issue Nov 19, 2021
Error was:

  error[E0658]: use of unstable library feature 'str_strip': newly added
    --> /usr/local/cargo/registry/src/github.com-1ecc6299db9ec823/impl-serde-0.3.2/src/serialize.rs:97:24
     |
  97 |     let (v, stripped) = v.strip_prefix("0x").map_or((v, false), |v| (v, true));
     |                           ^^^^^^^^^^^^
     |
     = note: see issue #67302 <rust-lang/rust#67302> for more information
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants