Хотя я думаю, что ответ trentcl чище , стоит показать несколько нераспределенных версий.
Использование Path::strip_prefix
Чтобы использовать Path::strip_prefix
, вам необходимо знать префикс. Мы можем создать его, пройдя по parent
s первоначального пути, пока не найдем тот, который ends_with
"foo".
use std::path::Path;
fn thing1<P>(path: &P) -> Result<&Path, ()>
where
P: AsRef<Path> + ?Sized,
{
let original = path.as_ref();
let mut prefix = original;
while !prefix.ends_with("foo") {
prefix = match prefix.parent() {
Some(p) => p,
None => return Err(()),
};
}
original.strip_prefix(prefix).map_err(|_| ())
}
fn main() {
let x = thing1("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}
с итератором
Мы можем перебирать по частям пути, принимать значения, в то время как это не "foo". Как только мы продвинемся итератор достаточно, мы можем получить остаток как путь .
use std::path::Path;
fn thing2<P>(path: &P) -> &Path
where
P: AsRef<Path> + ?Sized,
{
let path = path.as_ref();
let mut i = path.iter();
for _ in i.by_ref().take_while(|c| *c != "foo") {}
i.as_path()
}
fn main() {
let x = thing2("some/unknown/path/foo/bar/baz");
println!("{:?}", x);
}
Возвращает пустой путь, когда "foo" не существует.