Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Make alloc-free string manipulation more ergonomic with String::mutate(&mut self, ...) #2864

Copy link
Copy link
@mqudsi

Description

@mqudsi
Issue body actions

The current API for manipulating String objects is largely relegated to str, and many operations treat the source string as immutable and return a new &str reference with the result of the operation (unless non-contiguous results are not guaranteed, e.g. .replace(), etc.)

Oftentimes destructive modifications to a String are needed "while it is being created" and developers are forced to either write their own logic to duplicate str functionality to update String values or else use .to_owned() on the result of str functions.

e.g. a function runs a command and returns its output as a string, with trailing whitespace removed:

    ....
    let mut path = String::from_utf8(output.stdout)?;
    let new_len = path.trim_end().len();
    path.truncate(new_len);
    Ok(path)

vs

    ....
    let path = String::from_utf8(output.stdout)?;
    let path_str = path.trim_end();
    Ok(path_str.to_owned())

I believe we're close to being able to support a safe mutating api that provides a &str and uses an &str result to redefine the string (mainly to pop or dequeue elements from the underlying storage), something along the lines of

fn String::mutate(&mut self, F) -> ()
    where F: Fn(&'restricted str) -> &'restricted str`

which passes in an (exclusive) reference to the current value of the string and expects to receive a subset: &'restricted str as a result, where self.as_bytes() == &[.., subset.as_bytes(), ..] holds true (i.e. subset.as_bytes().as_ptr() >= self.as_bytes().as_ptr() && subset.as_bytes().as_ptr() + subset.as_bytes().len() < self.as_bytes().as_ptr() + self.as_bytes().len())

This makes the most sense it if it is possible to make compile-time guarantees ensuring the above predicate. I don't think #2000 via rust-lang/rust#44580 currently makes this possible, but I feel as if there is overlap between const generics and the ability to do so.

Using it would look something like this:

let mut start = "  hello, world  ".to_owned();
// Now trim both ends of the string without reallocating
start.mutate(|s| s.trim());
assert_eq!(&start, "hello, world");

while forbidding the following:

let other_string = "not my string";
let mut start = "  hello, world  ".to_owned();
// Try to provide a reference to an str that is not a subset of the string itself
start.mutate(|_| &other_string); // should not compile
mbartlett21 and chpiokennytmCryZe

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.