Is there a way to trim a String without allocating another one?

but probably an in-place action on a String is not a good idea.

The binding is mutable in mut s: &String, not the string itself. You would take s: &mut String if you wanted to mutate the string itself.

That said, I don't think there's anything in the standard library to do this.


I know this is old, but there is a nice two liner, trim_right_matches is deprecated now, but trim_end_matches() returns a &str with the length you want

fn read_csv_rilev(code: &mut String) {
        // code.to_uppercase();
        let l = code.trim_end_matches("UNI").len();
        code.truncate(l);
}



Is there a way to trim a String without allocating another one?

Yes, you can use truncate to remove trailing parts of the string:

const TRAILER: &'static str = "UNI";

fn read_csv_rilev(s: &mut String) {
    while s.ends_with(TRAILER) {
        let len = s.len();
        let new_len = len.saturating_sub(TRAILER.len());
        s.truncate(new_len);
    }
}

fn main() {
    let mut code = "Hello WorldUNIUNIUNI".into();
    
    read_csv_rilev(&mut code);
    
    assert_eq!("Hello World", code);
}

You don't need to mess with the allocated string at all. You can use the same logic and make successive subslices of the string. This is basically how trim_right_matches works, but a bit less generic:

const TRAILER: &'static str = "UNI";

fn read_csv_rilev(mut s: &str) -> &str {
    while s.ends_with(TRAILER) {
        let len = s.len();
        let new_len = len.saturating_sub(TRAILER.len());
        s = &s[..new_len];
    }
    s
}

fn main() {
    let code = "Hello WorldUNIUNIUNI";

    let truncated = read_csv_rilev(code);

    assert_eq!("Hello World", truncated);
}

In general, I'd probably go with the second solution.


Another solution is to use the owning_ref crate, which lets you return both a &str and its backing String at the same time:

extern crate owning_ref;
use owning_ref::StringRef;

fn read_csv_rilev(code: String) -> StringRef {
    StringRef::new(code).map(|s| s.trim_right_matches("UNI"))
}

Tags:

String

Trim

Rust