I want to be able to receive a path-like value in a generic function. The idea would be that I want to be able to receive anything that could be converted into PathBuf, like this:
fn build<P>(path: P) -> Some<Handler>{
let mut base_path = PathBuf::from(path);
...
}
But, of course, this doesn't work without the proper trait. Yet I'm unable to figure out how to write the generic trait stating that I want to accept a value that can be accepted as from
for another type. Like this (which of course doesn't work):
fn build<P>(path: P) -> Some<Handler>
where P: PathBuf::from::<P>
{
let mut base_path = PathBuf::from(path);
...
}
The proper trait for cases where you want "anything that converts to" is Into
.
However, the idiomatic trait for accepting paths in particular is AsRef<Path>
. This is how the standard library functions taking a path do it.
fn build<P>(path: P) where P: AsRef<Path>
or the shorter form:
fn build<P: AsRef<Path>>(path: P)
or even shorter:
fn build(path: impl AsRef<Path>)
If your function is not trivial, you should immediately forward to a non-generic function:
fn build(path: impl AsRef<Path>) {
build_impl(path.as_ref())
}
fn build_impl(path: &Path) { .... }
And if you need a PathBuf
, you simply call to_owned()
on the Path
.
For reference, you use the same technique with Into
:
fn build(p: impl Into<PathBuf>) { build_impl(p.into()) }
fn build_impl(p: PathBuf) {}