I have the next code (It compiles and works perfectly):
pub fn new<I: Into<PathBuf> + AsRef<Path>>(
modpack_path: &I,
destination: &I,
) -> Result<Self, ModpackError> {
let modpack = RinthDownloader::load_pack(modpack_path)?;
let (links, names) = RinthDownloader::get_data(&modpack);
let destination = destination.as_ref().to_owned();
if !destination.join("mods").exists() {
std::fs::create_dir(destination.join("mods"))
.map_err(|_| ModpackError::CantCreateDir)?;
}
if !destination.join("config").exists() {
std::fs::create_dir(destination.join("config"))
.map_err(|_| ModpackError::CantCreateDir)?;
}
Ok(RinthDownloader {
gen_downloader: Downloader2::new(
links.into(),
names,
destination.into(),
RinthRequester::new(),
),
modpack,
})
}
I want a reference to a type that can be converted to PathBuf with .into() and also want this same type to be converted to a Path when I used a reference ( &I ).
Am I doing it the right way or am I doing it wrong ?
I tried the code above and it worked fine but i want to know if I am doing it the right way and also the idiomatic way.
>Solution :
Get rid of the Into<PathBuf> as you don’t need it.
Also, the convention is to take impl AsRef<Path>, not &impl AsRef<Path> like you’re doing (see e.g. many functions in std::fs). This way, you can pass both references like &Path and &str, and also owned types such as PathBuf and String without needing to take a reference to them.