rustpathancestor

How do I change a &Path's first ancestor in Rust?


I want to change the first ancestor of a &Path, possibly by returning a new PathBuf like so.

fn change_parent(path: &Path, new_parent: &Path) -> PathBuf;

Here's how I expect it to work.

let old_path = change_root(Path::new("/hello/world.html"), Path::new("/html"));
let new_path = PathBuf::from("/html/world.html");
assert_eq!(old_path, new_path)

I tried .ancestors() but the Path::new("/hello/world.html").ancestors(); returns an iterator over ["/hello/world.html", "/hello", "/"] which is kind of the opposite of what I want. What I want is ["/hello/world.html", "hello/world.html", "/world.html"] so I can append a new path easily.

Should I switch to using split on "(/|\)" then replacing the first result instead?


Solution

  • This is using strip_prefix provided by conradludgate on The Rust Programming Language Community (Discord):

    use std::path::{Path, PathBuf, StripPrefixError}; 
    
    fn replace_prefix(p: impl AsRef<Path>, from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<PathBuf, StripPrefixError> {
      p.as_ref().strip_prefix(from).map(|p| to.as_ref().join(p))
    }
    
    (
      replace_prefix("/public/file.html", "/public", "/.html_output"),
      replace_prefix("/public/folder/nested/file.html", "/public", "/.html_output"),
      replace_prefix("/folder/nested/file.html", "/public", "/.html_output"),
    )
    
    (Ok("/.html_output/file.html"), Ok("/.html_output/folder/nested/file.html"), Err(StripPrefixError(())))