2

I want a function that mutates the underlying String of a PathBuf object, but all I could achieve now is creation of a new object instead.

use std::path::{Path, PathBuf};

fn expanduser(path: &mut PathBuf) -> PathBuf {
    return PathBuf::from(
        &path
            .to_str()
            .unwrap()
            .replace("~", PathBuf::home().to_str().unwrap()),
    );
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Alex Deft
  • 2,531
  • 1
  • 19
  • 34
  • Also if you are just looking to replace references to "~", you might be better solved with the canonicalize method: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.canonicalize https://doc.rust-lang.org/std/fs/fn.canonicalize.html function – user1937198 Aug 04 '22 at 20:39
  • @John Kugelman I see. But can't we go back and forth between them? even if there are caveats? Do you reckon that it would be too much work, that creation of a new object would be cheaper (computationally)? – Alex Deft Aug 04 '22 at 20:41
  • 1
    @user1937198 `.canonicalize()` doesn't handle `~`, it only normalizes away `.`, `..`, and symlinks, you need [a crate](https://crates.io/search?page=1&per_page=10&q=home%20dir) to deal with `~` – kmdreko Aug 04 '22 at 20:42
  • @user1937198 I hate that function, cause if the path I'm canonicalizing doesn't exist, it throws an error instead of gracefully doing what it should do. No one asked it to check existence. – Alex Deft Aug 04 '22 at 20:42
  • You can go back and forth between them, yes. That's what you're already doing: convert path to string (which could fail), manipulate string, convert back. What you can't do is use string functions to manipulate the path *in place*. – John Kugelman Aug 04 '22 at 20:48
  • 2
    I think you might be looking for something like this: https://stackoverflow.com/a/54306906/11423104 – isaactfa Aug 04 '22 at 20:51
  • Does this answer your question? [Expand tilde in Rust Path idiomatically](https://stackoverflow.com/questions/54267608/expand-tilde-in-rust-path-idiomatically) – Jmb Aug 05 '22 at 06:52
  • @Jmb the tilde affair is only coincidental to the question. – Alex Deft Aug 05 '22 at 08:01

1 Answers1

4

PathBuf wraps an OsString, not a String. They are much different types - String contains a UTF-8 string while OsString depends on the platform: arbitrary bytes for Unix and potentially-malformed UTF-16 on Windows.

You can use into_os_string to convert a PathBuf to an OsString, and From for the reverse.

If you are just trying to replace ~ with the home path, your best bet is to check if the first component (via the components method) is a Normal component containing "~" and join the rest of the components to the home path if so. There's crates that do this for you.

I hate that function, cause if the path I'm canonicalizing doesn't exist, it throws an error instead of gracefully doing what it should do. No one asked it to check existence.

You're likely misunderstanding the function. canonicalize resolves symlinks, so of course it won't work if the path doesn't exist. Also worth mentioning is that foo/bar/../baz is NOT necessarily the same as foo/baz, if foo/bar is a symlink.

kmdreko
  • 42,554
  • 6
  • 57
  • 106
Colonel Thirty Two
  • 23,953
  • 8
  • 45
  • 85